summaryrefslogtreecommitdiff
path: root/Volta
diff options
context:
space:
mode:
authorRonny Fenrich <Fenrich@Gmail.com>2013-06-13 13:40:44 -0600
committerRonny Fenrich <Fenrich@Gmail.com>2013-06-13 13:40:44 -0600
commitbf6c97cdee2264656211126ee01066c3c5d4bd8d (patch)
treedf4a6a9ed1b76109a57d1bf71c85b5632a6e3a0b /Volta
parentd6d01c9dd86561ad2121f0f85f0a4529142d5093 (diff)
added Xcode project and converted to CocoaPods (added a bunch of libraries)
Diffstat (limited to 'Volta')
-rwxr-xr-xVolta/Additions/GTMNSString+HTML.h66
-rwxr-xr-xVolta/Additions/GTMNSString+HTML.m522
-rw-r--r--Volta/Additions/KGJSON/KGJSON.h31
-rw-r--r--Volta/Additions/KGJSON/KGJSON.m61
-rw-r--r--Volta/Additions/KGJSON/readme.md23
-rw-r--r--Volta/Additions/NSDictionary+Additions.h13
-rw-r--r--Volta/Additions/NSDictionary+Additions.m26
-rw-r--r--Volta/Additions/NSMutableArray+Additions.h17
-rw-r--r--Volta/Additions/NSMutableArray.m27
-rw-r--r--Volta/Additions/NSString+Additions.h33
-rw-r--r--Volta/Additions/NSString+Additions.m159
-rwxr-xr-xVolta/Additions/NSString+HTML.h67
-rwxr-xr-xVolta/Additions/NSString+HTML.m344
-rw-r--r--Volta/Additions/UIImage+Additions.h18
-rw-r--r--Volta/Additions/UIImage+Additions.m68
-rw-r--r--Volta/Additions/UIView+Additions.h18
-rw-r--r--Volta/Additions/UIView+Additions.m44
-rw-r--r--Volta/Additions/UIView+Decoder.h28
-rw-r--r--Volta/Additions/UIView+Decoder.m135
-rw-r--r--Volta/AppDelegate.h15
-rw-r--r--Volta/AppDelegate.m46
-rw-r--r--Volta/Default-568h@2x.pngbin0 -> 18594 bytes
-rw-r--r--Volta/Default.pngbin0 -> 6540 bytes
-rw-r--r--Volta/Default@2x.pngbin0 -> 16107 bytes
-rw-r--r--Volta/Libraries/OrderedDictionary/MGOrderedDictionary.h56
-rw-r--r--Volta/Libraries/OrderedDictionary/MGOrderedDictionary.m194
-rwxr-xr-xVolta/Libraries/SSKeychain/SSKeychain.h333
-rwxr-xr-xVolta/Libraries/SSKeychain/SSKeychain.m312
-rw-r--r--Volta/Volta-Info.plist39
-rw-r--r--Volta/Volta-Prefix.pch28
-rw-r--r--Volta/en.lproj/InfoPlist.strings2
-rw-r--r--Volta/en.lproj/MainStoryboard.storyboard26
-rw-r--r--Volta/main.m18
33 files changed, 2769 insertions, 0 deletions
diff --git a/Volta/Additions/GTMNSString+HTML.h b/Volta/Additions/GTMNSString+HTML.h
new file mode 100755
index 0000000..0374ecc
--- /dev/null
+++ b/Volta/Additions/GTMNSString+HTML.h
@@ -0,0 +1,66 @@
+//
+// GTMNSString+HTML.h
+// Dealing with NSStrings that contain HTML
+//
+// Copyright 2006-2008 Google Inc.
+//
+// Licensed 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>
+
+/// Utilities for NSStrings containing HTML
+@interface NSString (GTMNSStringHTMLAdditions)
+
+/// Get a string where internal characters that need escaping for HTML are escaped
+//
+/// For example, '&' become '&amp;'. This will only cover characters from table
+/// A.2.2 of http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_Special_characters
+/// which is what you want for a unicode encoded webpage. If you have a ascii
+/// or non-encoded webpage, please use stringByEscapingAsciiHTML which will
+/// encode all characters.
+///
+/// For obvious reasons this call is only safe once.
+//
+// Returns:
+// Autoreleased NSString
+//
+- (NSString *)gtm_stringByEscapingForHTML;
+
+/// Get a string where internal characters that need escaping for HTML are escaped
+//
+/// For example, '&' become '&amp;'
+/// All non-mapped characters (unicode that don't have a &keyword; mapping)
+/// will be converted to the appropriate &#xxx; value. If your webpage is
+/// unicode encoded (UTF16 or UTF8) use stringByEscapingHTML instead as it is
+/// faster, and produces less bloated and more readable HTML (as long as you
+/// are using a unicode compliant HTML reader).
+///
+/// For obvious reasons this call is only safe once.
+//
+// Returns:
+// Autoreleased NSString
+//
+- (NSString *)gtm_stringByEscapingForAsciiHTML;
+
+/// Get a string where internal characters that are escaped for HTML are unescaped
+//
+/// For example, '&amp;' becomes '&'
+/// Handles &#32; and &#x32; cases as well
+///
+// Returns:
+// Autoreleased NSString
+//
+- (NSString *)gtm_stringByUnescapingFromHTML;
+
+@end \ No newline at end of file
diff --git a/Volta/Additions/GTMNSString+HTML.m b/Volta/Additions/GTMNSString+HTML.m
new file mode 100755
index 0000000..81a7144
--- /dev/null
+++ b/Volta/Additions/GTMNSString+HTML.m
@@ -0,0 +1,522 @@
+//
+// GTMNSString+HTML.m
+// Dealing with NSStrings that contain HTML
+//
+// Copyright 2006-2008 Google Inc.
+//
+// Licensed 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 "GTMDefines.h"
+#import "GTMNSString+HTML.h"
+
+typedef struct {
+ NSString *escapeSequence;
+ unichar uchar;
+} HTMLEscapeMap;
+
+// Taken from http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_Special_characters
+// Ordered by uchar lowest to highest for bsearching
+static HTMLEscapeMap gAsciiHTMLEscapeMap[] = {
+ // A.2.2. Special characters
+ { @"&quot;", 34 },
+ { @"&amp;", 38 },
+ { @"&apos;", 39 },
+ { @"&lt;", 60 },
+ { @"&gt;", 62 },
+
+ // A.2.1. Latin-1 characters
+ { @"&nbsp;", 160 },
+ { @"&iexcl;", 161 },
+ { @"&cent;", 162 },
+ { @"&pound;", 163 },
+ { @"&curren;", 164 },
+ { @"&yen;", 165 },
+ { @"&brvbar;", 166 },
+ { @"&sect;", 167 },
+ { @"&uml;", 168 },
+ { @"&copy;", 169 },
+ { @"&ordf;", 170 },
+ { @"&laquo;", 171 },
+ { @"&not;", 172 },
+ { @"&shy;", 173 },
+ { @"&reg;", 174 },
+ { @"&macr;", 175 },
+ { @"&deg;", 176 },
+ { @"&plusmn;", 177 },
+ { @"&sup2;", 178 },
+ { @"&sup3;", 179 },
+ { @"&acute;", 180 },
+ { @"&micro;", 181 },
+ { @"&para;", 182 },
+ { @"&middot;", 183 },
+ { @"&cedil;", 184 },
+ { @"&sup1;", 185 },
+ { @"&ordm;", 186 },
+ { @"&raquo;", 187 },
+ { @"&frac14;", 188 },
+ { @"&frac12;", 189 },
+ { @"&frac34;", 190 },
+ { @"&iquest;", 191 },
+ { @"&Agrave;", 192 },
+ { @"&Aacute;", 193 },
+ { @"&Acirc;", 194 },
+ { @"&Atilde;", 195 },
+ { @"&Auml;", 196 },
+ { @"&Aring;", 197 },
+ { @"&AElig;", 198 },
+ { @"&Ccedil;", 199 },
+ { @"&Egrave;", 200 },
+ { @"&Eacute;", 201 },
+ { @"&Ecirc;", 202 },
+ { @"&Euml;", 203 },
+ { @"&Igrave;", 204 },
+ { @"&Iacute;", 205 },
+ { @"&Icirc;", 206 },
+ { @"&Iuml;", 207 },
+ { @"&ETH;", 208 },
+ { @"&Ntilde;", 209 },
+ { @"&Ograve;", 210 },
+ { @"&Oacute;", 211 },
+ { @"&Ocirc;", 212 },
+ { @"&Otilde;", 213 },
+ { @"&Ouml;", 214 },
+ { @"&times;", 215 },
+ { @"&Oslash;", 216 },
+ { @"&Ugrave;", 217 },
+ { @"&Uacute;", 218 },
+ { @"&Ucirc;", 219 },
+ { @"&Uuml;", 220 },
+ { @"&Yacute;", 221 },
+ { @"&THORN;", 222 },
+ { @"&szlig;", 223 },
+ { @"&agrave;", 224 },
+ { @"&aacute;", 225 },
+ { @"&acirc;", 226 },
+ { @"&atilde;", 227 },
+ { @"&auml;", 228 },
+ { @"&aring;", 229 },
+ { @"&aelig;", 230 },
+ { @"&ccedil;", 231 },
+ { @"&egrave;", 232 },
+ { @"&eacute;", 233 },
+ { @"&ecirc;", 234 },
+ { @"&euml;", 235 },
+ { @"&igrave;", 236 },
+ { @"&iacute;", 237 },
+ { @"&icirc;", 238 },
+ { @"&iuml;", 239 },
+ { @"&eth;", 240 },
+ { @"&ntilde;", 241 },
+ { @"&ograve;", 242 },
+ { @"&oacute;", 243 },
+ { @"&ocirc;", 244 },
+ { @"&otilde;", 245 },
+ { @"&ouml;", 246 },
+ { @"&divide;", 247 },
+ { @"&oslash;", 248 },
+ { @"&ugrave;", 249 },
+ { @"&uacute;", 250 },
+ { @"&ucirc;", 251 },
+ { @"&uuml;", 252 },
+ { @"&yacute;", 253 },
+ { @"&thorn;", 254 },
+ { @"&yuml;", 255 },
+
+ // A.2.2. Special characters cont'd
+ { @"&OElig;", 338 },
+ { @"&oelig;", 339 },
+ { @"&Scaron;", 352 },
+ { @"&scaron;", 353 },
+ { @"&Yuml;", 376 },
+
+ // A.2.3. Symbols
+ { @"&fnof;", 402 },
+
+ // A.2.2. Special characters cont'd
+ { @"&circ;", 710 },
+ { @"&tilde;", 732 },
+
+ // A.2.3. Symbols cont'd
+ { @"&Alpha;", 913 },
+ { @"&Beta;", 914 },
+ { @"&Gamma;", 915 },
+ { @"&Delta;", 916 },
+ { @"&Epsilon;", 917 },
+ { @"&Zeta;", 918 },
+ { @"&Eta;", 919 },
+ { @"&Theta;", 920 },
+ { @"&Iota;", 921 },
+ { @"&Kappa;", 922 },
+ { @"&Lambda;", 923 },
+ { @"&Mu;", 924 },
+ { @"&Nu;", 925 },
+ { @"&Xi;", 926 },
+ { @"&Omicron;", 927 },
+ { @"&Pi;", 928 },
+ { @"&Rho;", 929 },
+ { @"&Sigma;", 931 },
+ { @"&Tau;", 932 },
+ { @"&Upsilon;", 933 },
+ { @"&Phi;", 934 },
+ { @"&Chi;", 935 },
+ { @"&Psi;", 936 },
+ { @"&Omega;", 937 },
+ { @"&alpha;", 945 },
+ { @"&beta;", 946 },
+ { @"&gamma;", 947 },
+ { @"&delta;", 948 },
+ { @"&epsilon;", 949 },
+ { @"&zeta;", 950 },
+ { @"&eta;", 951 },
+ { @"&theta;", 952 },
+ { @"&iota;", 953 },
+ { @"&kappa;", 954 },
+ { @"&lambda;", 955 },
+ { @"&mu;", 956 },
+ { @"&nu;", 957 },
+ { @"&xi;", 958 },
+ { @"&omicron;", 959 },
+ { @"&pi;", 960 },
+ { @"&rho;", 961 },
+ { @"&sigmaf;", 962 },
+ { @"&sigma;", 963 },
+ { @"&tau;", 964 },
+ { @"&upsilon;", 965 },
+ { @"&phi;", 966 },
+ { @"&chi;", 967 },
+ { @"&psi;", 968 },
+ { @"&omega;", 969 },
+ { @"&thetasym;", 977 },
+ { @"&upsih;", 978 },
+ { @"&piv;", 982 },
+
+ // A.2.2. Special characters cont'd
+ { @"&ensp;", 8194 },
+ { @"&emsp;", 8195 },
+ { @"&thinsp;", 8201 },
+ { @"&zwnj;", 8204 },
+ { @"&zwj;", 8205 },
+ { @"&lrm;", 8206 },
+ { @"&rlm;", 8207 },
+ { @"&ndash;", 8211 },
+ { @"&mdash;", 8212 },
+ { @"&lsquo;", 8216 },
+ { @"&rsquo;", 8217 },
+ { @"&sbquo;", 8218 },
+ { @"&ldquo;", 8220 },
+ { @"&rdquo;", 8221 },
+ { @"&bdquo;", 8222 },
+ { @"&dagger;", 8224 },
+ { @"&Dagger;", 8225 },
+ // A.2.3. Symbols cont'd
+ { @"&bull;", 8226 },
+ { @"&hellip;", 8230 },
+
+ // A.2.2. Special characters cont'd
+ { @"&permil;", 8240 },
+
+ // A.2.3. Symbols cont'd
+ { @"&prime;", 8242 },
+ { @"&Prime;", 8243 },
+
+ // A.2.2. Special characters cont'd
+ { @"&lsaquo;", 8249 },
+ { @"&rsaquo;", 8250 },
+
+ // A.2.3. Symbols cont'd
+ { @"&oline;", 8254 },
+ { @"&frasl;", 8260 },
+
+ // A.2.2. Special characters cont'd
+ { @"&euro;", 8364 },
+
+ // A.2.3. Symbols cont'd
+ { @"&image;", 8465 },
+ { @"&weierp;", 8472 },
+ { @"&real;", 8476 },
+ { @"&trade;", 8482 },
+ { @"&alefsym;", 8501 },
+ { @"&larr;", 8592 },
+ { @"&uarr;", 8593 },
+ { @"&rarr;", 8594 },
+ { @"&darr;", 8595 },
+ { @"&harr;", 8596 },
+ { @"&crarr;", 8629 },
+ { @"&lArr;", 8656 },
+ { @"&uArr;", 8657 },
+ { @"&rArr;", 8658 },
+ { @"&dArr;", 8659 },
+ { @"&hArr;", 8660 },
+ { @"&forall;", 8704 },
+ { @"&part;", 8706 },
+ { @"&exist;", 8707 },
+ { @"&empty;", 8709 },
+ { @"&nabla;", 8711 },
+ { @"&isin;", 8712 },
+ { @"&notin;", 8713 },
+ { @"&ni;", 8715 },
+ { @"&prod;", 8719 },
+ { @"&sum;", 8721 },
+ { @"&minus;", 8722 },
+ { @"&lowast;", 8727 },
+ { @"&radic;", 8730 },
+ { @"&prop;", 8733 },
+ { @"&infin;", 8734 },
+ { @"&ang;", 8736 },
+ { @"&and;", 8743 },
+ { @"&or;", 8744 },
+ { @"&cap;", 8745 },
+ { @"&cup;", 8746 },
+ { @"&int;", 8747 },
+ { @"&there4;", 8756 },
+ { @"&sim;", 8764 },
+ { @"&cong;", 8773 },
+ { @"&asymp;", 8776 },
+ { @"&ne;", 8800 },
+ { @"&equiv;", 8801 },
+ { @"&le;", 8804 },
+ { @"&ge;", 8805 },
+ { @"&sub;", 8834 },
+ { @"&sup;", 8835 },
+ { @"&nsub;", 8836 },
+ { @"&sube;", 8838 },
+ { @"&supe;", 8839 },
+ { @"&oplus;", 8853 },
+ { @"&otimes;", 8855 },
+ { @"&perp;", 8869 },
+ { @"&sdot;", 8901 },
+ { @"&lceil;", 8968 },
+ { @"&rceil;", 8969 },
+ { @"&lfloor;", 8970 },
+ { @"&rfloor;", 8971 },
+ { @"&lang;", 9001 },
+ { @"&rang;", 9002 },
+ { @"&loz;", 9674 },
+ { @"&spades;", 9824 },
+ { @"&clubs;", 9827 },
+ { @"&hearts;", 9829 },
+ { @"&diams;", 9830 }
+};
+
+// Taken from http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_Special_characters
+// This is table A.2.2 Special Characters
+static HTMLEscapeMap gUnicodeHTMLEscapeMap[] = {
+ // C0 Controls and Basic Latin
+ { @"&quot;", 34 },
+ { @"&amp;", 38 },
+ { @"&apos;", 39 },
+ { @"&lt;", 60 },
+ { @"&gt;", 62 },
+
+ // Latin Extended-A
+ { @"&OElig;", 338 },
+ { @"&oelig;", 339 },
+ { @"&Scaron;", 352 },
+ { @"&scaron;", 353 },
+ { @"&Yuml;", 376 },
+
+ // Spacing Modifier Letters
+ { @"&circ;", 710 },
+ { @"&tilde;", 732 },
+
+ // General Punctuation
+ { @"&ensp;", 8194 },
+ { @"&emsp;", 8195 },
+ { @"&thinsp;", 8201 },
+ { @"&zwnj;", 8204 },
+ { @"&zwj;", 8205 },
+ { @"&lrm;", 8206 },
+ { @"&rlm;", 8207 },
+ { @"&ndash;", 8211 },
+ { @"&mdash;", 8212 },
+ { @"&lsquo;", 8216 },
+ { @"&rsquo;", 8217 },
+ { @"&sbquo;", 8218 },
+ { @"&ldquo;", 8220 },
+ { @"&rdquo;", 8221 },
+ { @"&bdquo;", 8222 },
+ { @"&dagger;", 8224 },
+ { @"&Dagger;", 8225 },
+ { @"&permil;", 8240 },
+ { @"&lsaquo;", 8249 },
+ { @"&rsaquo;", 8250 },
+ { @"&euro;", 8364 },
+};
+
+
+// Utility function for Bsearching table above
+static int EscapeMapCompare(const void *ucharVoid, const void *mapVoid) {
+ const unichar *uchar = (const unichar*)ucharVoid;
+ const HTMLEscapeMap *map = (const HTMLEscapeMap*)mapVoid;
+ int val;
+ if (*uchar > map->uchar) {
+ val = 1;
+ } else if (*uchar < map->uchar) {
+ val = -1;
+ } else {
+ val = 0;
+ }
+ return val;
+}
+
+@implementation NSString (GTMNSStringHTMLAdditions)
+
+- (NSString *)gtm_stringByEscapingHTMLUsingTable:(HTMLEscapeMap*)table
+ ofSize:(NSUInteger)size
+ escapingUnicode:(BOOL)escapeUnicode {
+ NSUInteger length = [self length];
+ if (!length) {
+ return self;
+ }
+
+ NSMutableString *finalString = [NSMutableString string];
+ NSMutableData *data2 = [NSMutableData dataWithCapacity:sizeof(unichar) * length];
+
+ // this block is common between GTMNSString+HTML and GTMNSString+XML but
+ // it's so short that it isn't really worth trying to share.
+ const unichar *buffer = CFStringGetCharactersPtr((CFStringRef)self);
+ if (!buffer) {
+ // We want this buffer to be autoreleased.
+ NSMutableData *data = [NSMutableData dataWithLength:length * sizeof(UniChar)];
+ if (!data) {
+ // COV_NF_START - Memory fail case
+// _GTMDevLog(@"couldn't alloc buffer");
+ return nil;
+ // COV_NF_END
+ }
+ [self getCharacters:[data mutableBytes]];
+ buffer = [data bytes];
+ }
+
+ if (!buffer || !data2) {
+ // COV_NF_START
+// _GTMDevLog(@"Unable to allocate buffer or data2");
+ return nil;
+ // COV_NF_END
+ }
+
+ unichar *buffer2 = (unichar *)[data2 mutableBytes];
+
+ NSUInteger buffer2Length = 0;
+
+ for (NSUInteger i = 0; i < length; ++i) {
+ HTMLEscapeMap *val = bsearch(&buffer[i], table,
+ size / sizeof(HTMLEscapeMap),
+ sizeof(HTMLEscapeMap), EscapeMapCompare);
+ if (val || (escapeUnicode && buffer[i] > 127)) {
+ if (buffer2Length) {
+ CFStringAppendCharacters((CFMutableStringRef)finalString,
+ buffer2,
+ buffer2Length);
+ buffer2Length = 0;
+ }
+ if (val) {
+ [finalString appendString:val->escapeSequence];
+ }
+ else {
+// _GTMDevAssert(escapeUnicode && buffer[i] > 127, @"Illegal Character");
+ [finalString appendFormat:@"&#%d;", buffer[i]];
+ }
+ } else {
+ buffer2[buffer2Length] = buffer[i];
+ buffer2Length += 1;
+ }
+ }
+ if (buffer2Length) {
+ CFStringAppendCharacters((CFMutableStringRef)finalString,
+ buffer2,
+ buffer2Length);
+ }
+ return finalString;
+}
+
+- (NSString *)gtm_stringByEscapingForHTML {
+ return [self gtm_stringByEscapingHTMLUsingTable:gUnicodeHTMLEscapeMap
+ ofSize:sizeof(gUnicodeHTMLEscapeMap)
+ escapingUnicode:NO];
+} // gtm_stringByEscapingHTML
+
+- (NSString *)gtm_stringByEscapingForAsciiHTML {
+ return [self gtm_stringByEscapingHTMLUsingTable:gAsciiHTMLEscapeMap
+ ofSize:sizeof(gAsciiHTMLEscapeMap)
+ escapingUnicode:YES];
+} // gtm_stringByEscapingAsciiHTML
+
+- (NSString *)gtm_stringByUnescapingFromHTML {
+ NSRange range = NSMakeRange(0, [self length]);
+ NSRange subrange = [self rangeOfString:@"&" options:NSBackwardsSearch range:range];
+
+ // if no ampersands, we've got a quick way out
+ if (subrange.length == 0) return self;
+ NSMutableString *finalString = [NSMutableString stringWithString:self];
+ do {
+ NSRange semiColonRange = NSMakeRange(subrange.location, NSMaxRange(range) - subrange.location);
+ semiColonRange = [self rangeOfString:@";" options:0 range:semiColonRange];
+ range = NSMakeRange(0, subrange.location);
+ // if we don't find a semicolon in the range, we don't have a sequence
+ if (semiColonRange.location == NSNotFound) {
+ continue;
+ }
+ NSRange escapeRange = NSMakeRange(subrange.location, semiColonRange.location - subrange.location + 1);
+ NSString *escapeString = [self substringWithRange:escapeRange];
+ NSUInteger length = [escapeString length];
+ // a squence must be longer than 3 (&lt;) and less than 11 (&thetasym;)
+ if (length > 3 && length < 11) {
+ if ([escapeString characterAtIndex:1] == '#') {
+ unichar char2 = [escapeString characterAtIndex:2];
+ if (char2 == 'x' || char2 == 'X') {
+ // Hex escape squences &#xa3;
+ NSString *hexSequence = [escapeString substringWithRange:NSMakeRange(3, length - 4)];
+ NSScanner *scanner = [NSScanner scannerWithString:hexSequence];
+ unsigned value;
+ if ([scanner scanHexInt:&value] &&
+ value < USHRT_MAX &&
+ value > 0
+ && [scanner scanLocation] == length - 4) {
+ unichar uchar = value;
+ NSString *charString = [NSString stringWithCharacters:&uchar length:1];
+ [finalString replaceCharactersInRange:escapeRange withString:charString];
+ }
+
+ } else {
+ // Decimal Sequences &#123;
+ NSString *numberSequence = [escapeString substringWithRange:NSMakeRange(2, length - 3)];
+ NSScanner *scanner = [NSScanner scannerWithString:numberSequence];
+ int value;
+ if ([scanner scanInt:&value] &&
+ value < USHRT_MAX &&
+ value > 0
+ && [scanner scanLocation] == length - 3) {
+ unichar uchar = value;
+ NSString *charString = [NSString stringWithCharacters:&uchar length:1];
+ [finalString replaceCharactersInRange:escapeRange withString:charString];
+ }
+ }
+ } else {
+ // "standard" sequences
+ for (unsigned i = 0; i < sizeof(gAsciiHTMLEscapeMap) / sizeof(HTMLEscapeMap); ++i) {
+ if ([escapeString isEqualToString:gAsciiHTMLEscapeMap[i].escapeSequence]) {
+ [finalString replaceCharactersInRange:escapeRange withString:[NSString stringWithCharacters:&gAsciiHTMLEscapeMap[i].uchar length:1]];
+ break;
+ }
+ }
+ }
+ }
+ } while ((subrange = [self rangeOfString:@"&" options:NSBackwardsSearch range:range]).length != 0);
+ return finalString;
+} // gtm_stringByUnescapingHTML
+
+
+
+@end \ No newline at end of file
diff --git a/Volta/Additions/KGJSON/KGJSON.h b/Volta/Additions/KGJSON/KGJSON.h
new file mode 100644
index 0000000..e2bc2c8
--- /dev/null
+++ b/Volta/Additions/KGJSON/KGJSON.h
@@ -0,0 +1,31 @@
+//
+// NSString+KGJSON.h
+// KGJSON
+//
+// Created by David Keegan on 10/16/12.
+// Copyright (c) 2012 David Keegan. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@interface NSString(KGJSON)
+
+- (id)JSONObject;
++ (NSString *)JSONString:(id)object;
++ (NSString *)prettyJSONString:(id)object;
+
+@end
+
+@interface NSDictionary(KGJSON)
+
+- (NSString *)JSONString;
+- (NSString *)prettyJSONString;
+
+@end
+
+@interface NSArray(KGJSON)
+
+- (NSString *)JSONString;
+- (NSString *)prettyJSONString;
+
+@end
diff --git a/Volta/Additions/KGJSON/KGJSON.m b/Volta/Additions/KGJSON/KGJSON.m
new file mode 100644
index 0000000..e6f2f98
--- /dev/null
+++ b/Volta/Additions/KGJSON/KGJSON.m
@@ -0,0 +1,61 @@
+//
+// NSString+KGJSON.m
+// KGJSON
+//
+// Created by David Keegan on 10/16/12.
+// Copyright (c) 2012 David Keegan. All rights reserved.
+//
+
+#import "KGJSON.h"
+
+@implementation NSString(KGJSON)
+
+- (id)JSONObject{
+ if(self == nil){
+ return self;
+ }
+ NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding];
+ return [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
+}
+
++ (NSString *)JSONString:(id)object{
+ if(object == nil){
+ return nil;
+ }
+ NSData *json = [NSJSONSerialization dataWithJSONObject:object options:0 error:nil];
+ return [[NSString alloc] initWithData:json encoding:NSUTF8StringEncoding];
+}
+
++ (NSString *)prettyJSONString:(id)object{
+ if(object == nil){
+ return nil;
+ }
+ NSData *json = [NSJSONSerialization dataWithJSONObject:object options:NSJSONWritingPrettyPrinted error:nil];
+ return [[NSString alloc] initWithData:json encoding:NSUTF8StringEncoding];
+}
+
+@end
+
+@implementation NSDictionary(KGJSON)
+
+- (NSString *)JSONString{
+ return [NSString JSONString:self];
+}
+
+- (NSString *)prettyJSONString{
+ return [NSString prettyJSONString:self];
+}
+
+@end
+
+@implementation NSArray(KGJSON)
+
+- (NSString *)JSONString{
+ return [NSString JSONString:self];
+}
+
+- (NSString *)prettyJSONString{
+ return [NSString prettyJSONString:self];
+}
+
+@end
diff --git a/Volta/Additions/KGJSON/readme.md b/Volta/Additions/KGJSON/readme.md
new file mode 100644
index 0000000..9e96c7b
--- /dev/null
+++ b/Volta/Additions/KGJSON/readme.md
@@ -0,0 +1,23 @@
+``` obj-c
+@interface NSString(KGJSON)
+
+- (id)JSONObject;
++ (NSString *)JSONString:(id)object;
++ (NSString *)prettyJSONString:(id)object;
+
+@end
+
+@interface NSDictionary(KGJSON)
+
+- (NSString *)JSONString;
+- (NSString *)prettyJSONString;
+
+@end
+
+@interface NSArray(KGJSON)
+
+- (NSString *)JSONString;
+- (NSString *)prettyJSONString;
+
+@end
+``` \ No newline at end of file
diff --git a/Volta/Additions/NSDictionary+Additions.h b/Volta/Additions/NSDictionary+Additions.h
new file mode 100644
index 0000000..456359b
--- /dev/null
+++ b/Volta/Additions/NSDictionary+Additions.h
@@ -0,0 +1,13 @@
+//
+// NSDictionary+NSDictionary_Additions.h
+// fastcab-driver
+//
+// Created by Rick Cotter on 12-03-20.
+// Copyright (c) 2012 Assn. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@interface NSDictionary (Additions)
+-(id) objectForKey:(NSString *)key defaultValue:(id)defaultValue;
+@end
diff --git a/Volta/Additions/NSDictionary+Additions.m b/Volta/Additions/NSDictionary+Additions.m
new file mode 100644
index 0000000..01f3569
--- /dev/null
+++ b/Volta/Additions/NSDictionary+Additions.m
@@ -0,0 +1,26 @@
+//
+// NSDictionary+NSDictionary_Additions.m
+// fastcab-driver
+//
+// Created by Rick Cotter on 12-03-20.
+// Copyright (c) 2012 Assn. All rights reserved.
+//
+
+#import "NSDictionary+Additions.h"
+
+@implementation NSDictionary (Additions)
+
+-(id) objectForKey:(NSString *)key defaultValue:(id)defaultValue {
+ id value = [self objectForKey:key];
+ if (!value) {
+ return defaultValue;
+ }
+
+ if (value == [NSNull null]) {
+ return defaultValue;
+ }
+
+ return value;
+}
+
+@end
diff --git a/Volta/Additions/NSMutableArray+Additions.h b/Volta/Additions/NSMutableArray+Additions.h
new file mode 100644
index 0000000..8525146
--- /dev/null
+++ b/Volta/Additions/NSMutableArray+Additions.h
@@ -0,0 +1,17 @@
+//
+// NSArray+Additions.h
+// popquizshow
+//
+// Created by Ronny Fenrich on 2012-11-14.
+// Copyright (c) 2012 Kyle Langille. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+// This category enhances NSMutableArray by providing
+// methods to randomly shuffle the elements.
+@interface NSMutableArray (Additions)
+
+- (void)shuffle;
+
+@end
diff --git a/Volta/Additions/NSMutableArray.m b/Volta/Additions/NSMutableArray.m
new file mode 100644
index 0000000..0d7214b
--- /dev/null
+++ b/Volta/Additions/NSMutableArray.m
@@ -0,0 +1,27 @@
+//
+// NSMutableArray+Additions.m
+// popquizshow
+//
+// Created by Ronny Fenrich on 2012-11-14.
+// Copyright (c) 2012 Kyle Langille. All rights reserved.
+//
+
+#import "NSMutableArray+Additions.h"
+
+
+
+
+@implementation NSMutableArray (Shuffling)
+
+- (void)shuffle
+{
+ NSUInteger count = [self count];
+ for (NSUInteger i = 0; i < count; ++i) {
+ // Select a random element between i and end of array to swap with.
+ NSInteger nElements = count - i;
+ NSInteger n = (arc4random() % nElements) + i;
+ [self exchangeObjectAtIndex:i withObjectAtIndex:n];
+ }
+}
+
+@end \ No newline at end of file
diff --git a/Volta/Additions/NSString+Additions.h b/Volta/Additions/NSString+Additions.h
new file mode 100644
index 0000000..a7f8a75
--- /dev/null
+++ b/Volta/Additions/NSString+Additions.h
@@ -0,0 +1,33 @@
+//
+// NSString+Additions.h
+// Cardinal
+//
+// Created by Cory Smith on 10-03-28.
+// Copyright 2010 Assn. All rights reserved.
+//
+
+@interface NSString (md5)
+
++ (NSString *) md5:(NSString *)str;
+
+@end
+
+@interface NSString (Assn)
+- (NSString *)trim;
+- (BOOL)isEmpty;
+- (BOOL)startsWith:(NSString *)starting;
+- (BOOL)endsWith:(NSString *)ending;
+- (BOOL)contains:(NSString *)text;
+- (NSString *)urlEncode;
+- (NSString *)replace:(NSString *)find with:(NSString *)replacement;
+- (NSString *)replaceAll:(NSArray *)keys with:(NSArray *)values;
+
+// Replace newlines with <br /> tags.
+- (NSString *)stringWithNewLinesAsBRs;
+
+- (NSString *)sanitizeForHTMLOutput;
+
++ (NSString *)generateUUID;
+
+@end
+
diff --git a/Volta/Additions/NSString+Additions.m b/Volta/Additions/NSString+Additions.m
new file mode 100644
index 0000000..57c782c
--- /dev/null
+++ b/Volta/Additions/NSString+Additions.m
@@ -0,0 +1,159 @@
+//
+// NSString+Additions.m
+// Cardinal
+//
+// Created by Cory Smith on 10-03-28.
+// Copyright 2010 Assn. All rights reserved.
+//
+
+#import "NSString+Additions.h"
+
+
+#import <CommonCrypto/CommonDigest.h>
+
+@implementation NSString (md5)
+
++ (NSString *) md5:(NSString *)str {
+ const char *cStr = [str UTF8String];
+ unsigned char result[16];
+ CC_MD5( cStr, strlen(cStr), result );
+ return [NSString stringWithFormat:
+ @"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
+ result[0], result[1], result[2], result[3],
+ result[4], result[5], result[6], result[7],
+ result[8], result[9], result[10], result[11],
+ result[12], result[13], result[14], result[15]
+ ];
+}
+
+@end
+
+@implementation NSString (Assn)
+
+- (NSString *)trim {
+ return [self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
+}
+
+- (BOOL)isEmpty {
+ return [[self trim] isEqualToString:@""];
+}
+
+- (BOOL)endsWith:(NSString *)ending {
+
+ int indexToCheck = [self length] - [ending length];
+
+ if(indexToCheck >= 0)
+ return [[self substringFromIndex:indexToCheck] isEqualToString:ending];
+
+ return NO;
+}
+
+- (BOOL)startsWith:(NSString *)starting {
+ if([starting isEmpty] || [starting length] > self.length)
+ return NO;
+
+ return [[self substringToIndex:[starting length]] isEqualToString:starting];
+}
+
+- (NSString *)replace:(NSString *)find with:(NSString *)replacement {
+ return [self stringByReplacingOccurrencesOfString:find withString:replacement];
+}
+
+
+- (NSString *)replaceAll:(NSArray *)keys with:(NSArray *)values {
+
+ NSMutableString *s = [NSMutableString stringWithString:self];
+
+ for (int i = 0; i < keys.count; i++) {
+ [s replaceOccurrencesOfString:[keys objectAtIndex:i]
+ withString:[values objectAtIndex:i]
+ options:NSLiteralSearch
+ range:NSMakeRange(0, [s length])];
+ }
+
+ return s;
+}
+
+
+- (BOOL)contains:(NSString *)text {
+ NSRange range = [[self lowercaseString] rangeOfString:[text lowercaseString]];
+ return range.location != NSNotFound;
+}
+
+- (NSString *)urlEncode
+{
+ NSString *result = (__bridge NSString *) CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)self, NULL, CFSTR(":/?#[]@!$&’()*+,;="), kCFStringEncodingUTF8);
+ return result;
+}
+
+- (NSString *)stringWithNewLinesAsBRs {
+
+ // Strange New lines:
+ // Next Line, U+0085
+ // Form Feed, U+000C
+ // Line Separator, U+2028
+ // Paragraph Separator, U+2029
+
+ // Scanner
+ NSScanner *scanner = [[NSScanner alloc] initWithString:self];
+ [scanner setCharactersToBeSkipped:nil];
+ NSMutableString *result = [[NSMutableString alloc] init];
+ NSString *temp;
+ NSCharacterSet *newLineCharacters = [NSCharacterSet characterSetWithCharactersInString:
+ [NSString stringWithFormat:@"\n\r"]];
+ // Scan
+ do {
+
+ // Get non new line characters
+ temp = nil;
+ [scanner scanUpToCharactersFromSet:newLineCharacters intoString:&temp];
+ if (temp) [result appendString:temp];
+ temp = nil;
+
+ // Add <br /> s
+ if ([scanner scanString:@"\r\n" intoString:nil]) {
+
+ // Combine \r\n into just 1 <br />
+ [result appendString:@"<br />"];
+
+ } else if ([scanner scanCharactersFromSet:newLineCharacters intoString:&temp]) {
+
+ // Scan other new line characters and add <br /> s
+ if (temp) {
+ for (NSUInteger i = 0; i < temp.length; i++) {
+ [result appendString:@"<br />"];
+ }
+ }
+
+ }
+
+ } while (![scanner isAtEnd]);
+
+ // Cleanup & return
+ NSString *retString = [NSString stringWithString:result];
+
+ // Return
+ return retString;
+
+}
+
+
+- (NSString *)sanitizeForHTMLOutput
+{
+ NSString *result = self;
+ if (!result) { result = @""; }
+ result = [result trim];
+ result = [result stringWithNewLinesAsBRs];
+ return result;
+}
+
++ (NSString *)generateUUID
+{
+ CFUUIDRef newUniqueId = CFUUIDCreate(kCFAllocatorDefault);
+ NSString * uuidString = (__bridge_transfer NSString*)CFUUIDCreateString(kCFAllocatorDefault, newUniqueId);
+ CFRelease(newUniqueId);
+
+ return uuidString;
+}
+
+@end
diff --git a/Volta/Additions/NSString+HTML.h b/Volta/Additions/NSString+HTML.h
new file mode 100755
index 0000000..334f27b
--- /dev/null
+++ b/Volta/Additions/NSString+HTML.h
@@ -0,0 +1,67 @@
+//
+// NSString+HTML.h
+// MWFeedParser
+//
+// Copyright (c) 2010 Michael Waterfall
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// 1. The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// 2. This Software cannot be used to archive or collect data such as (but not
+// limited to) that of events, news, experiences and activities, for the
+// purpose of any concept relating to diary/journal keeping.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#import <Foundation/Foundation.h>
+
+// Dependant upon GTMNSString+HTML
+
+@interface NSString (HTML)
+
+// Strips HTML tags & comments, removes extra whitespace and decodes HTML character entities.
+- (NSString *)stringByConvertingHTMLToPlainText;
+
+// Decode all HTML entities using GTM.
+- (NSString *)stringByDecodingHTMLEntities;
+
+// Encode all HTML entities using GTM.
+- (NSString *)stringByEncodingHTMLEntities;
+
+// Minimal unicode encoding will only cover characters from table
+// A.2.2 of http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_Special_characters
+// which is what you want for a unicode encoded webpage.
+- (NSString *)stringByEncodingHTMLEntities:(BOOL)isUnicode;
+
+// Replace newlines with <br /> tags.
+- (NSString *)stringWithNewLinesAsBRs;
+
+// Remove newlines and white space from string.
+- (NSString *)stringByRemovingNewLinesAndWhitespace;
+
+// Wrap plain URLs in <a href="..." class="linkified">...</a>
+// - Ignores URLs inside tags (any URL beginning with =")
+// - HTTP & HTTPS schemes only
+// - Only works in iOS 4+ as we use NSRegularExpression (returns self if not supported so be careful with NSMutableStrings)
+// - Expression: (?<!=")\b((http|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?)
+// - Adapted from http://regexlib.com/REDetails.aspx?regexp_id=96
+- (NSString *)stringByLinkifyingURLs;
+
+// DEPRECIATED - Please use NSString stringByConvertingHTMLToPlainText
+- (NSString *)stringByStrippingTags __attribute__((deprecated));
+
+@end \ No newline at end of file
diff --git a/Volta/Additions/NSString+HTML.m b/Volta/Additions/NSString+HTML.m
new file mode 100755
index 0000000..7e59221
--- /dev/null
+++ b/Volta/Additions/NSString+HTML.m
@@ -0,0 +1,344 @@
+//
+// NSString+HTML.m
+// MWFeedParser
+//
+// Copyright (c) 2010 Michael Waterfall
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// 1. The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// 2. This Software cannot be used to archive or collect data such as (but not
+// limited to) that of events, news, experiences and activities, for the
+// purpose of any concept relating to diary/journal keeping.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#import "NSString+HTML.h"
+#import "GTMNSString+HTML.h"
+
+@implementation NSString (HTML)
+
+#pragma mark - Instance Methods
+
+- (NSString *)stringByConvertingHTMLToPlainText {
+
+ // Pool
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ // Character sets
+ NSCharacterSet *stopCharacters = [NSCharacterSet characterSetWithCharactersInString:[NSString stringWithFormat:@"< \t\n\r%C%C%C%C", (unichar)0x0085, (unichar)0x000C, (unichar)0x2028, (unichar)0x2029]];
+ NSCharacterSet *newLineAndWhitespaceCharacters = [NSCharacterSet characterSetWithCharactersInString:[NSString stringWithFormat:@" \t\n\r%C%C%C%C", (unichar)0x0085, (unichar)0x000C, (unichar)0x2028, (unichar)0x2029]];
+ NSCharacterSet *tagNameCharacters = [NSCharacterSet characterSetWithCharactersInString:@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"];
+
+ // Scan and find all tags
+ NSMutableString *result = [[NSMutableString alloc] initWithCapacity:self.length];
+ NSScanner *scanner = [[NSScanner alloc] initWithString:self];
+ [scanner setCharactersToBeSkipped:nil];
+ [scanner setCaseSensitive:YES];
+ NSString *str = nil, *tagName = nil;
+ BOOL dontReplaceTagWithSpace = NO;
+ do {
+
+ // Scan up to the start of a tag or whitespace
+ if ([scanner scanUpToCharactersFromSet:stopCharacters intoString:&str]) {
+ [result appendString:str];
+ str = nil; // reset
+ }
+
+ // Check if we've stopped at a tag/comment or whitespace
+ if ([scanner scanString:@"<" intoString:NULL]) {
+
+ // Stopped at a comment or tag
+ if ([scanner scanString:@"!--" intoString:NULL]) {
+
+ // Comment
+ [scanner scanUpToString:@"-->" intoString:NULL];
+ [scanner scanString:@"-->" intoString:NULL];
+
+ } else {
+
+ // Tag - remove and replace with space unless it's
+ // a closing inline tag then dont replace with a space
+ if ([scanner scanString:@"/" intoString:NULL]) {
+
+ // Closing tag - replace with space unless it's inline
+ tagName = nil; dontReplaceTagWithSpace = NO;
+ if ([scanner scanCharactersFromSet:tagNameCharacters intoString:&tagName]) {
+ tagName = [tagName lowercaseString];
+ dontReplaceTagWithSpace = ([tagName isEqualToString:@"a"] ||
+ [tagName isEqualToString:@"b"] ||
+ [tagName isEqualToString:@"i"] ||
+ [tagName isEqualToString:@"q"] ||
+ [tagName isEqualToString:@"span"] ||
+ [tagName isEqualToString:@"em"] ||
+ [tagName isEqualToString:@"strong"] ||
+ [tagName isEqualToString:@"cite"] ||
+ [tagName isEqualToString:@"abbr"] ||
+ [tagName isEqualToString:@"acronym"] ||
+ [tagName isEqualToString:@"label"]);
+ }
+
+ // Replace tag with string unless it was an inline
+ if (!dontReplaceTagWithSpace && result.length > 0 && ![scanner isAtEnd]) [result appendString:@" "];
+
+ }
+
+ // Scan past tag
+ [scanner scanUpToString:@">" intoString:NULL];
+ [scanner scanString:@">" intoString:NULL];
+
+ }
+
+ } else {
+
+ // Stopped at whitespace - replace all whitespace and newlines with a space
+ if ([scanner scanCharactersFromSet:newLineAndWhitespaceCharacters intoString:NULL]) {
+ if (result.length > 0 && ![scanner isAtEnd]) [result appendString:@" "]; // Dont append space to beginning or end of result
+ }
+
+ }
+
+ } while (![scanner isAtEnd]);
+
+ // Cleanup
+ [scanner release];
+
+ // Decode HTML entities and return
+ NSString *retString = [[result stringByDecodingHTMLEntities] retain];
+ [result release];
+
+ // Drain
+ [pool drain];
+
+ // Return
+ return [retString autorelease];
+
+}
+
+- (NSString *)stringByDecodingHTMLEntities {
+ // Can return self so create new string if we're a mutable string
+ return [NSString stringWithString:[self gtm_stringByUnescapingFromHTML]];
+}
+
+
+- (NSString *)stringByEncodingHTMLEntities {
+ // Can return self so create new string if we're a mutable string
+ return [NSString stringWithString:[self gtm_stringByEscapingForAsciiHTML]];
+}
+
+- (NSString *)stringByEncodingHTMLEntities:(BOOL)isUnicode {
+ // Can return self so create new string if we're a mutable string
+ return [NSString stringWithString:(isUnicode ? [self gtm_stringByEscapingForHTML] : [self gtm_stringByEscapingForAsciiHTML])];
+}
+
+- (NSString *)stringWithNewLinesAsBRs {
+
+ // Pool
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ // Strange New lines:
+ // Next Line, U+0085
+ // Form Feed, U+000C
+ // Line Separator, U+2028
+ // Paragraph Separator, U+2029
+
+ // Scanner
+ NSScanner *scanner = [[NSScanner alloc] initWithString:self];
+ [scanner setCharactersToBeSkipped:nil];
+ NSMutableString *result = [[NSMutableString alloc] init];
+ NSString *temp;
+
+ NSCharacterSet *newLineCharacters = [NSCharacterSet characterSetWithCharactersInString:
+ [NSString stringWithFormat:@"\n\r%C%C%C%C", (unichar)0x0085, (unichar)0x000C, (unichar)0x2028, (unichar)0x2029]];
+ // Scan
+ do {
+
+ // Get non new line characters
+ temp = nil;
+ [scanner scanUpToCharactersFromSet:newLineCharacters intoString:&temp];
+ if (temp) [result appendString:temp];
+ temp = nil;
+
+ // Add <br /> s
+ if ([scanner scanString:@"\r\n" intoString:nil]) {
+
+ // Combine \r\n into just 1 <br />
+ [result appendString:@"<br />"];
+
+ } else if ([scanner scanCharactersFromSet:newLineCharacters intoString:&temp]) {
+
+ // Scan other new line characters and add <br /> s
+ if (temp) {
+ for (NSUInteger i = 0; i < temp.length; i++) {
+ [result appendString:@"<br />"];
+ }
+ }
+
+ }
+
+ } while (![scanner isAtEnd]);
+
+ // Cleanup & return
+ [scanner release];
+ NSString *retString = [[NSString stringWithString:result] retain];
+ [result release];
+
+ // Drain
+ [pool drain];
+
+ // Return
+ return [retString autorelease];
+
+}
+
+- (NSString *)stringByRemovingNewLinesAndWhitespace {
+
+ // Pool
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ // Strange New lines:
+ // Next Line, U+0085
+ // Form Feed, U+000C
+ // Line Separator, U+2028
+ // Paragraph Separator, U+2029
+
+ // Scanner
+ NSScanner *scanner = [[NSScanner alloc] initWithString:self];
+ [scanner setCharactersToBeSkipped:nil];
+ NSMutableString *result = [[NSMutableString alloc] init];
+ NSString *temp;
+ NSCharacterSet *newLineAndWhitespaceCharacters = [NSCharacterSet characterSetWithCharactersInString:
+ [NSString stringWithFormat:@" \t\n\r%C%C%C%C", (unichar)0x0085, (unichar)0x000C, (unichar)0x2028, (unichar)0x2029]];
+
+ // Scan
+ while (![scanner isAtEnd]) {
+
+ // Get non new line or whitespace characters
+ temp = nil;
+ [scanner scanUpToCharactersFromSet:newLineAndWhitespaceCharacters intoString:&temp];
+ if (temp) [result appendString:temp];
+
+ // Replace with a space
+ if ([scanner scanCharactersFromSet:newLineAndWhitespaceCharacters intoString:NULL]) {
+ if (result.length > 0 && ![scanner isAtEnd]) // Dont append space to beginning or end of result
+ [result appendString:@" "];
+ }
+
+ }
+
+ // Cleanup
+ [scanner release];
+
+ // Return
+ NSString *retString = [[NSString stringWithString:result] retain];
+ [result release];
+
+ // Drain
+ [pool drain];
+
+ // Return
+ return [retString autorelease];
+
+}
+
+- (NSString *)stringByLinkifyingURLs {
+ if (!NSClassFromString(@"NSRegularExpression")) return self;
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ NSString *pattern = @"(?<!=\")\\b((http|https):\\/\\/[\\w\\-_]+(\\.[\\w\\-_]+)+([\\w\\-\\.,@?^=%%&amp;:/~\\+#]*[\\w\\-\\@?^=%%&amp;/~\\+#])?)";
+ NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:nil];
+ NSString *modifiedString = [[regex stringByReplacingMatchesInString:self options:0 range:NSMakeRange(0, [self length])
+ withTemplate:@"<a href=\"$1\" class=\"linkified\">$1</a>"] retain];
+ [pool drain];
+ return [modifiedString autorelease];
+}
+
+- (NSString *)stringByStrippingTags {
+
+ // Pool
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ // Find first & and short-cut if we can
+ NSUInteger ampIndex = [self rangeOfString:@"<" options:NSLiteralSearch].location;
+ if (ampIndex == NSNotFound) {
+ return [NSString stringWithString:self]; // return copy of string as no tags found
+ }
+
+ // Scan and find all tags
+ NSScanner *scanner = [NSScanner scannerWithString:self];
+ [scanner setCharactersToBeSkipped:nil];
+ NSMutableSet *tags = [[NSMutableSet alloc] init];
+ NSString *tag;
+ do {
+
+ // Scan up to <
+ tag = nil;
+ [scanner scanUpToString:@"<" intoString:NULL];
+ [scanner scanUpToString:@">" intoString:&tag];
+
+ // Add to set
+ if (tag) {
+ NSString *t = [[NSString alloc] initWithFormat:@"%@>", tag];
+ [tags addObject:t];
+ [t release];
+ }
+
+ } while (![scanner isAtEnd]);
+
+ // Strings
+ NSMutableString *result = [[NSMutableString alloc] initWithString:self];
+ NSString *finalString;
+
+ // Replace tags
+ NSString *replacement;
+ for (NSString *t in tags) {
+
+ // Replace tag with space unless it's an inline element
+ replacement = @" ";
+ if ([t isEqualToString:@"<a>"] ||
+ [t isEqualToString:@"</a>"] ||
+ [t isEqualToString:@"<span>"] ||
+ [t isEqualToString:@"</span>"] ||
+ [t isEqualToString:@"<strong>"] ||
+ [t isEqualToString:@"</strong>"] ||
+ [t isEqualToString:@"<em>"] ||
+ [t isEqualToString:@"</em>"]) {
+ replacement = @"";
+ }
+
+ // Replace
+ [result replaceOccurrencesOfString:t
+ withString:replacement
+ options:NSLiteralSearch
+ range:NSMakeRange(0, result.length)];
+ }
+
+ // Remove multi-spaces and line breaks
+ finalString = [[result stringByRemovingNewLinesAndWhitespace] retain];
+
+ // Cleanup
+ [result release];
+ [tags release];
+
+ // Drain
+ [pool drain];
+
+ // Return
+ return [finalString autorelease];
+
+}
+
+@end
diff --git a/Volta/Additions/UIImage+Additions.h b/Volta/Additions/UIImage+Additions.h
new file mode 100644
index 0000000..428a0c2
--- /dev/null
+++ b/Volta/Additions/UIImage+Additions.h
@@ -0,0 +1,18 @@
+//
+// UIImage_Additions.h
+// FlushD
+//
+// Created by Ronny Fenrich on 12-07-27.
+//
+//
+
+#import <UIKit/UIKit.h>
+
+@interface UIImage (Additions)
+
++ (UIImage *)imageFromColor:(UIColor *)color;
++ (UIImage *)imageFromColor:(UIColor *)color width:(CGFloat) width height:(CGFloat) height;
++ (UIImage *)retina4ImageNamed:(NSString *)imageName;
++ (UIImage *)imageWithImage:(UIImage *)image convertToSize:(CGSize)size;
+
+@end
diff --git a/Volta/Additions/UIImage+Additions.m b/Volta/Additions/UIImage+Additions.m
new file mode 100644
index 0000000..41ad79e
--- /dev/null
+++ b/Volta/Additions/UIImage+Additions.m
@@ -0,0 +1,68 @@
+//
+// UIImage_Additions.m
+// FlushD
+//
+// Created by Ronny Fenrich on 12-07-27.
+//
+//
+
+#import "UIImage+Additions.h"
+
+@implementation UIImage (Additions)
+
++ (UIImage *) imageFromColor:(UIColor *)color
+{
+ UIImage *img = [UIImage imageFromColor:color width:1 height:1];
+ return img;
+}
+
+
++ (UIImage *) imageFromColor:(UIColor *)color width:(CGFloat) width height:(CGFloat) height
+{
+ CGRect rect = CGRectMake(0, 0, width, height);
+ UIGraphicsBeginImageContext(rect.size);
+ CGContextRef context = UIGraphicsGetCurrentContext();
+ CGContextSetFillColorWithColor(context, [color CGColor]);
+ CGContextFillRect(context, rect);
+ UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
+ UIGraphicsEndImageContext();
+ return img;
+}
+
+
+// helper method for iPhone5, loads tall image with fallback to old imageNamed method based on current device height
++ (UIImage *)retina4ImageNamed:(NSString *)imageName
+{
+ NSMutableString *imageNameMutable = [imageName mutableCopy];
+ NSRange retinaAtSymbol = [imageName rangeOfString:@"@"];
+ if (retinaAtSymbol.location != NSNotFound) {
+ [imageNameMutable insertString:@"-568h" atIndex:retinaAtSymbol.location];
+ } else {
+ CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height;
+ if ([UIScreen mainScreen].scale == 2.f && screenHeight == 568.0f) {
+ NSRange dot = [imageName rangeOfString:@"."];
+ if (dot.location != NSNotFound) {
+ [imageNameMutable insertString:@"-568h@2x" atIndex:dot.location];
+ } else {
+ [imageNameMutable appendString:@"-568h@2x"];
+ }
+ }
+ }
+
+ UIImage *image = [UIImage imageNamed:imageNameMutable];
+ if (!image) {
+ image = [UIImage imageNamed:imageName];
+ }
+ return image;
+}
+
++ (UIImage *)imageWithImage:(UIImage *)image convertToSize:(CGSize)size
+{
+ UIGraphicsBeginImageContext(size);
+ [image drawInRect:CGRectMake(0, 0, size.width, size.height)];
+ UIImage *destImage = UIGraphicsGetImageFromCurrentImageContext();
+ UIGraphicsEndImageContext();
+ return destImage;
+}
+
+@end
diff --git a/Volta/Additions/UIView+Additions.h b/Volta/Additions/UIView+Additions.h
new file mode 100644
index 0000000..93b9c0f
--- /dev/null
+++ b/Volta/Additions/UIView+Additions.h
@@ -0,0 +1,18 @@
+//
+// UIView+Additions.h
+// FlushD
+//
+// Created by Ronny Fenrich on 2012-08-30.
+//
+//
+
+#import <UIKit/UIKit.h>
+
+@interface UIView (Additions)
+
+@property (nonatomic, assign) CGPoint $origin;
+@property (nonatomic, assign) CGSize $size;
+@property (nonatomic, assign) CGFloat $x, $y, $width, $height; // normal rect properties
+@property (nonatomic, assign) CGFloat $left, $top, $right, $bottom; // these will stretch/shrink the rect
+
+@end
diff --git a/Volta/Additions/UIView+Additions.m b/Volta/Additions/UIView+Additions.m
new file mode 100644
index 0000000..9faeaf9
--- /dev/null
+++ b/Volta/Additions/UIView+Additions.m
@@ -0,0 +1,44 @@
+//
+// UIView+Additions.m
+// FlushD
+//
+// Created by Ronny Fenrich on 2012-08-30.
+//
+//
+
+#import "UIView+Additions.h"
+
+@implementation UIView (Additions)
+
+- (CGPoint)$origin { return self.frame.origin; }
+- (void)set$origin:(CGPoint)origin { self.frame = (CGRect){ .origin=origin, .size=self.frame.size }; }
+
+- (CGFloat)$x { return self.frame.origin.x; }
+- (void)set$x:(CGFloat)x { self.frame = (CGRect){ .origin.x=x, .origin.y=self.frame.origin.y, .size=self.frame.size }; }
+
+- (CGFloat)$y { return self.frame.origin.y; }
+- (void)set$y:(CGFloat)y { self.frame = (CGRect){ .origin.x=self.frame.origin.x, .origin.y=y, .size=self.frame.size }; }
+
+- (CGSize)$size { return self.frame.size; }
+- (void)set$size:(CGSize)size { self.frame = (CGRect){ .origin=self.frame.origin, .size=size }; }
+
+- (CGFloat)$width { return self.frame.size.width; }
+- (void)set$width:(CGFloat)width { self.frame = (CGRect){ .origin=self.frame.origin, .size.width=width, .size.height=self.frame.size.height }; }
+
+- (CGFloat)$height { return self.frame.size.height; }
+- (void)set$height:(CGFloat)height { self.frame = (CGRect){ .origin=self.frame.origin, .size.width=self.frame.size.width, .size.height=height }; }
+
+- (CGFloat)$left { return self.frame.origin.x; }
+- (void)set$left:(CGFloat)left { self.frame = (CGRect){ .origin.x=left, .origin.y=self.frame.origin.y, .size.width=fmaxf(self.frame.origin.x+self.frame.size.width-left,0), .size.height=self.frame.size.height }; }
+
+- (CGFloat)$top { return self.frame.origin.y; }
+- (void)set$top:(CGFloat)top { self.frame = (CGRect){ .origin.x=self.frame.origin.x, .origin.y=top, .size.width=self.frame.size.width, .size.height=fmaxf(self.frame.origin.y+self.frame.size.height-top,0) }; }
+
+- (CGFloat)$right { return self.frame.origin.x + self.frame.size.width; }
+- (void)set$right:(CGFloat)right { self.frame = (CGRect){ .origin=self.frame.origin, .size.width=fmaxf(right-self.frame.origin.x,0), .size.height=self.frame.size.height }; }
+
+- (CGFloat)$bottom { return self.frame.origin.y + self.frame.size.height; }
+- (void)set$bottom:(CGFloat)bottom { self.frame = (CGRect){ .origin=self.frame.origin, .size.width=self.frame.size.width, .size.height=fmaxf(bottom-self.frame.origin.y,0) }; }
+
+
+@end
diff --git a/Volta/Additions/UIView+Decoder.h b/Volta/Additions/UIView+Decoder.h
new file mode 100644
index 0000000..64ff6ef
--- /dev/null
+++ b/Volta/Additions/UIView+Decoder.h
@@ -0,0 +1,28 @@
+//
+// UIView+Decoder.h
+//
+//
+
+#import <UIKit/UIKit.h>
+
+@interface UIView(Background)
+- (void)setBackgroundImage;
+@end
+
+
+@interface UIView (Remixes)
+- (void) changeFrame:(CGRect)frame overTimeInterval:(double)timeInterval;
+- (void) fadeIn;
+- (void) fadeOut;
+- (void) fadeOutThenCallSelector:(SEL)selector delegate:(id)delegate;
+- (void) removeSubviewWithTagIfExists:(int)theTag;
+- (NSMutableDictionary *)fullDescription;
+- (UIViewController *) firstAvailableUIViewController;
+- (id) traverseResponderChainForUIViewController;
+@end
+
+@interface UISearchBar (iAutomation)
+- (void) search;
+@end
+
+
diff --git a/Volta/Additions/UIView+Decoder.m b/Volta/Additions/UIView+Decoder.m
new file mode 100644
index 0000000..0ff029b
--- /dev/null
+++ b/Volta/Additions/UIView+Decoder.m
@@ -0,0 +1,135 @@
+//
+// UIView+Decoder.m
+//
+
+#import "UIView+Decoder.h"
+
+
+@implementation UIView(Background)
+
+- (void)setBackgroundImage {
+ self.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"mainbg.png"]];
+// self.backgroundColor = [UIColor scrollViewTexturedBackgroundColor];
+}
+
+@end
+
+
+@implementation UIView (Remixes)
+
+
+- (void) changeFrame:(CGRect)frame overTimeInterval:(double)timeInterval {
+ [UIView beginAnimations:nil context:NULL];
+ [UIView setAnimationDuration:timeInterval];
+ [self setFrame:frame];
+ [UIView commitAnimations];
+}
+
+- (void)changeFrame:(CGRect)theFrame
+ overTimeInterval:(double)timeInterval
+ animationCurve:(UIViewAnimationCurve)animationCurve {
+
+
+ [UIView beginAnimations:nil context:NULL];
+ [UIView setAnimationDuration:timeInterval];
+ [UIView setAnimationCurve:animationCurve];
+ [self setFrame:theFrame];
+ [UIView commitAnimations];
+}
+
+- (void) fadeIn {
+ self.alpha = 0.0;
+ [UIView beginAnimations:nil context:NULL];
+ [UIView setAnimationDuration:1.0];
+ self.alpha = 1.0;
+ [UIView commitAnimations];
+}
+
+- (void) fadeOut {
+ [UIView beginAnimations:nil context:NULL];
+ [UIView setAnimationDuration:1.0];
+ self.alpha = 0.0;
+ [UIView commitAnimations];
+}
+
+- (void) fadeFrom:(float)from to:(float)to over:(float)seconds {
+ self.alpha = from;
+ [UIView beginAnimations:@"Sweet!" context:NULL];
+ [UIView setAnimationDuration:seconds];
+ self.alpha = to;
+ [UIView commitAnimations];
+}
+
+- (void) fadeOutThenCallSelector:(SEL)selector delegate:(id)delegate {
+ [UIView beginAnimations:nil context:NULL];
+ [UIView setAnimationDuration:1.0];
+ [UIView setAnimationDelegate:delegate];
+ [UIView setAnimationDidStopSelector:selector];
+ self.alpha = 0.0;
+ [UIView commitAnimations];
+}
+
+- (void) removeSubviewWithTagIfExists:(int)theTag
+{
+ if([self viewWithTag:theTag])
+ [[self viewWithTag:theTag] removeFromSuperview];
+}
+
+- (NSMutableDictionary *)fullDescription {
+ NSDictionary *frame =
+ [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithFloat:self.frame.origin.x], @"x",
+ [NSNumber numberWithFloat:self.frame.origin.y], @"y",
+ [NSNumber numberWithFloat:self.frame.size.width], @"width",
+ [NSNumber numberWithFloat:self.frame.size.height], @"height",
+ nil];
+
+ NSMutableDictionary *description =
+ [NSMutableDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithInteger:(NSInteger)self], @"address",
+ NSStringFromClass([self class]), @"className",
+ frame, @"frame",
+ [NSNumber numberWithInteger:[self tag]], @"tag",
+ [self valueForKeyPath:@"subviews.fullDescription"], @"subviews", nil];
+
+ if ([self respondsToSelector:@selector(text)])
+ {
+ [description setValue:[self performSelector:@selector(text)]
+ forKey:@"text"];
+ }
+
+ if ([self respondsToSelector:@selector(title)])
+ {
+ [description setValue:[self performSelector:@selector(title)]
+ forKey:@"title"];
+ }
+
+ if ([self respondsToSelector:@selector(currentTitle)])
+ {
+ [description setValue:[self performSelector:@selector(currentTitle)]
+ forKey:@"currentTitle"];
+ }
+
+ return description;
+}
+
+- (UIViewController *) firstAvailableUIViewController {
+ // convenience function for casting and to "mask" the recursive function
+ return (UIViewController *)[self traverseResponderChainForUIViewController];
+}
+
+- (id) traverseResponderChainForUIViewController {
+ id nextResponder = [self nextResponder];
+ if ([nextResponder isKindOfClass:[UIViewController class]]) {
+ return nextResponder;
+ } else if ([nextResponder isKindOfClass:[UIView class]]) {
+ return [nextResponder traverseResponderChainForUIViewController];
+ } else {
+ return nil;
+ }
+}
+
+@end
+
+
+
diff --git a/Volta/AppDelegate.h b/Volta/AppDelegate.h
new file mode 100644
index 0000000..80b560c
--- /dev/null
+++ b/Volta/AppDelegate.h
@@ -0,0 +1,15 @@
+//
+// AppDelegate.h
+// Volta
+//
+// Created by Ronny Fenrich on 2013-06-13.
+// Copyright (c) 2013 Decoder. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface AppDelegate : UIResponder <UIApplicationDelegate>
+
+@property (strong, nonatomic) UIWindow *window;
+
+@end
diff --git a/Volta/AppDelegate.m b/Volta/AppDelegate.m
new file mode 100644
index 0000000..83c0745
--- /dev/null
+++ b/Volta/AppDelegate.m
@@ -0,0 +1,46 @@
+//
+// AppDelegate.m
+// Volta
+//
+// Created by Ronny Fenrich on 2013-06-13.
+// Copyright (c) 2013 Decoder. All rights reserved.
+//
+
+#import "AppDelegate.h"
+
+@implementation AppDelegate
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
+{
+ // Override point for customization after application launch.
+ return YES;
+}
+
+- (void)applicationWillResignActive:(UIApplication *)application
+{
+ // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
+ // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
+}
+
+- (void)applicationDidEnterBackground:(UIApplication *)application
+{
+ // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
+ // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
+}
+
+- (void)applicationWillEnterForeground:(UIApplication *)application
+{
+ // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
+}
+
+- (void)applicationDidBecomeActive:(UIApplication *)application
+{
+ // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
+}
+
+- (void)applicationWillTerminate:(UIApplication *)application
+{
+ // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
+}
+
+@end
diff --git a/Volta/Default-568h@2x.png b/Volta/Default-568h@2x.png
new file mode 100644
index 0000000..0891b7a
--- /dev/null
+++ b/Volta/Default-568h@2x.png
Binary files differ
diff --git a/Volta/Default.png b/Volta/Default.png
new file mode 100644
index 0000000..4c8ca6f
--- /dev/null
+++ b/Volta/Default.png
Binary files differ
diff --git a/Volta/Default@2x.png b/Volta/Default@2x.png
new file mode 100644
index 0000000..35b84cf
--- /dev/null
+++ b/Volta/Default@2x.png
Binary files differ
diff --git a/Volta/Libraries/OrderedDictionary/MGOrderedDictionary.h b/Volta/Libraries/OrderedDictionary/MGOrderedDictionary.h
new file mode 100644
index 0000000..7aecef8
--- /dev/null
+++ b/Volta/Libraries/OrderedDictionary/MGOrderedDictionary.h
@@ -0,0 +1,56 @@
+//
+// MGOrderedDictionary.h
+// MGOrderedDictionary
+//
+// Created by Matt Gallagher on 19/12/08.
+// Modified by Gwynne Raskind on 31/12/12.
+// Copyright 2008 Matt Gallagher. All rights reserved.
+// Parts Copyright 2012 Gwynne Raskind. All rights reserved.
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software. Permission is granted to anyone to
+// use this software for any purpose, including commercial applications, and to
+// alter it and redistribute it freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would be
+// appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be
+// misrepresented as being the original software.
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+
+#import <Foundation/Foundation.h>
+
+@interface MGOrderedDictionary : NSMutableDictionary
+{
+ NSMutableDictionary *dictionary;
+ NSMutableArray *array;
+}
+
+- (void)insertObject:(id)anObject forKey:(id<NSCopying>)aKey atIndex:(NSUInteger)anIndex;
+- (id)keyAtIndex:(NSUInteger)anIndex;
+- (NSEnumerator *)reverseKeyEnumerator;
+
+- (id)objectAtIndexedSubscript:(NSUInteger)idx;
+
+- (id)objectForKeyedSubscript:(id)key;
+- (void)setObject:(id)obj forKeyedSubscript:(id<NSCopying>)key;
+
+- (NSUInteger)indexOfKey:(id)anObject;
+- (NSUInteger)indexOfKey:(id)anObject inRange:(NSRange)range;
+- (NSUInteger)indexOfKeyIdenticalTo:(id)anObject;
+- (NSUInteger)indexOfKeyIdenticalTo:(id)anObject inRange:(NSRange)range;
+- (id)lastKey;
+
+- (void)sortUsingFunction:(NSInteger (*)(id, id, void *))compare context:(void *)context;
+- (void)sortUsingSelector:(SEL)comparator;
+#if NS_BLOCKS_AVAILABLE
+- (void)sortUsingComparator:(NSComparator)cmptr;
+- (void)sortWithOptions:(NSSortOptions)opts usingComparator:(NSComparator)cmptr;
+#endif
+
+@end \ No newline at end of file
diff --git a/Volta/Libraries/OrderedDictionary/MGOrderedDictionary.m b/Volta/Libraries/OrderedDictionary/MGOrderedDictionary.m
new file mode 100644
index 0000000..2bda77c
--- /dev/null
+++ b/Volta/Libraries/OrderedDictionary/MGOrderedDictionary.m
@@ -0,0 +1,194 @@
+//
+// MGOrderedDictionary.m
+// MGOrderedDictionary
+//
+// Created by Matt Gallagher on 19/12/08.
+// Modified by Gwynne Raskind on 31/12/12.
+// Copyright 2008 Matt Gallagher. All rights reserved.
+// Parts Copyright 2012 Gwynne Raskind. All rights reserved.
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software. Permission is granted to anyone to
+// use this software for any purpose, including commercial applications, and to
+// alter it and redistribute it freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would be
+// appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be
+// misrepresented as being the original software.
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+
+#import "MGOrderedDictionary.h"
+
+static NSString *DescriptionForObject(id object, id locale, NSUInteger indent)
+{
+ if ([object respondsToSelector:@selector(descriptionWithLocale:indent:)])
+ return [object descriptionWithLocale:locale indent:indent];
+ else if ([object respondsToSelector:@selector(descriptionWithLocale:)])
+ return [object descriptionWithLocale:locale];
+ return [object description];
+}
+
+@implementation MGOrderedDictionary
+
+- (instancetype)init
+{
+ return [self initWithCapacity:0];
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)capacity
+{
+ self = [super init];
+ if (self != nil)
+ {
+ dictionary = [[NSMutableDictionary alloc] initWithCapacity:capacity];
+ array = [[NSMutableArray alloc] initWithCapacity:capacity];
+ }
+ return self;
+}
+
+- (instancetype)copy
+{
+ return [self mutableCopy];
+}
+
+- (void)setObject:(id)anObject forKey:(id<NSCopying>)aKey
+{
+ if (![dictionary objectForKey:aKey])
+ [array addObject:aKey];
+ [dictionary setObject:anObject forKey:aKey];
+}
+
+- (void)removeObjectForKey:(id)aKey
+{
+ [dictionary removeObjectForKey:aKey];
+ [array removeObject:aKey];
+}
+
+- (NSUInteger)count
+{
+ return [dictionary count];
+}
+
+- (id)objectForKey:(id)aKey
+{
+ return [dictionary objectForKey:aKey];
+}
+
+- (NSEnumerator *)keyEnumerator
+{
+ return [array objectEnumerator];
+}
+
+- (NSEnumerator *)reverseKeyEnumerator
+{
+ return [array reverseObjectEnumerator];
+}
+
+- (void)insertObject:(id)anObject forKey:(id<NSCopying>)aKey atIndex:(NSUInteger)anIndex
+{
+ [array insertObject:aKey atIndex:anIndex];
+ [dictionary setObject:anObject forKey:aKey];
+}
+
+- (id)keyAtIndex:(NSUInteger)anIndex
+{
+ return [array objectAtIndex:anIndex];
+}
+
+- (id)objectAtIndexedSubscript:(NSUInteger)idx
+{
+ return [self keyAtIndex:idx];
+}
+
+- (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx __attribute__((noreturn))
+{
+ @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"Can't set indexed object on ordered dictionary" userInfo:nil];
+}
+
+- (id)objectForKeyedSubscript:(id)key
+{
+ return [self objectForKey:key];
+}
+
+- (void)setObject:(id)obj forKeyedSubscript:(id<NSCopying>)key
+{
+ [self setObject:obj forKey:key];
+}
+
+- (NSUInteger)indexOfKey:(id)anObject
+{
+ return [array indexOfObject:anObject];
+}
+
+- (NSUInteger)indexOfKey:(id)anObject inRange:(NSRange)range
+{
+ return [array indexOfObject:anObject inRange:range];
+}
+
+- (NSUInteger)indexOfKeyIdenticalTo:(id)anObject
+{
+ return [array indexOfObjectIdenticalTo:anObject];
+}
+
+- (NSUInteger)indexOfKeyIdenticalTo:(id)anObject inRange:(NSRange)range
+{
+ return [array indexOfObjectIdenticalTo:anObject inRange:range];
+}
+
+- (id)lastKey
+{
+ return [array lastObject];
+}
+
+- (void)sortUsingFunction:(NSInteger (*)(id, id, void *))compare context:(void *)context
+{
+ [array sortUsingFunction:compare context:context];
+}
+
+- (void)sortUsingSelector:(SEL)comparator
+{
+ [array sortUsingSelector:comparator];
+}
+
+#if NS_BLOCKS_AVAILABLE
+- (void)sortUsingComparator:(NSComparator)cmptr
+{
+ [array sortUsingComparator:cmptr];
+}
+
+- (void)sortWithOptions:(NSSortOptions)opts usingComparator:(NSComparator)cmptr
+{
+ [array sortWithOptions:opts usingComparator:cmptr];
+}
+#endif
+
+- (NSString *)descriptionWithLocale:(id)locale
+{
+ return [self descriptionWithLocale:locale indent:0];
+}
+
+- (NSString *)descriptionWithLocale:(id)locale indent:(NSUInteger)level
+{
+ NSMutableString *indentString = [NSMutableString string];
+
+ for (NSUInteger i = 0; i < level; i++)
+ [indentString appendString:@"\t"];
+
+ NSMutableString *description = [NSMutableString stringWithFormat:@"%@{\n", indentString];
+
+ for (id key in array)
+ {
+ [description appendFormat:@"%@\t%@ = %@;\n",
+ indentString, DescriptionForObject(key, locale, level), DescriptionForObject(self[key], locale, level)];
+ }
+ [description appendFormat:@"%@}\n", indentString];
+ return description;
+}
+
+@end \ No newline at end of file
diff --git a/Volta/Libraries/SSKeychain/SSKeychain.h b/Volta/Libraries/SSKeychain/SSKeychain.h
new file mode 100755
index 0000000..6e92123
--- /dev/null
+++ b/Volta/Libraries/SSKeychain/SSKeychain.h
@@ -0,0 +1,333 @@
+//
+// 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 code specific to SSKeychain that can be returned in NSError objects.
+ For codes returned by the operating system, refer to SecBase.h for your platform.
+ */
+typedef enum {
+
+ /** Some of the arguments were invalid. */
+ SSKeychainErrorBadArguments = -1001,
+
+} 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
diff --git a/Volta/Libraries/SSKeychain/SSKeychain.m b/Volta/Libraries/SSKeychain/SSKeychain.m
new file mode 100755
index 0000000..5af4b87
--- /dev/null
+++ b/Volta/Libraries/SSKeychain/SSKeychain.m
@@ -0,0 +1,312 @@
+//
+// 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;
++ (NSError *)_errorWithCode:(OSStatus) code;
+@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 != errSecSuccess && error != NULL) {
+ *error = [self _errorWithCode:status];
+ 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 = [self _errorWithCode:status];
+ }
+ 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 != errSecSuccess && error != NULL) {
+ *error = [self _errorWithCode:status];
+ 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 TARGET_OS_IPHONE && __has_feature(objc_arc)
+ status = SecItemDelete((__bridge CFDictionaryRef)query);
+#elif TARGET_OS_IPHONE
+ status = SecItemDelete((CFDictionaryRef)query);
+#else
+ CFTypeRef result;
+ #if __has_feature(objc_arc)
+ [query setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnRef];
+ status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result);
+ #else
+ [query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnRef];
+ status = SecItemCopyMatching((CFDictionaryRef)query, &result);
+ #endif
+ if (errSecSuccess == status) {
+ status = SecKeychainItemDelete((SecKeychainItemRef) result);
+ CFRelease(result);
+ }
+#endif
+ }
+ if (status != errSecSuccess && error != NULL) {
+ *error = [self _errorWithCode:status];
+ }
+ return (status == errSecSuccess);
+
+}
+
+
+#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 != errSecSuccess && error != NULL) {
+ *error = [self _errorWithCode:status];
+ }
+ return (status == errSecSuccess);
+}
+
+
+#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;
+}
+
+
++ (NSError *)_errorWithCode:(OSStatus) code {
+ NSString *message = nil;
+ switch (code) {
+ case errSecSuccess: return nil;
+ case SSKeychainErrorBadArguments: message = @"Some of the arguments were invalid"; break;
+
+#if TARGET_OS_IPHONE
+ case errSecUnimplemented: message = @"Function or operation not implemented"; break;
+ case errSecParam: message = @"One or more parameters passed to a function were not valid"; break;
+ case errSecAllocate: message = @"Failed to allocate memory"; break;
+ case errSecNotAvailable: message = @"No keychain is available. You may need to restart your computer"; break;
+ case errSecDuplicateItem: message = @"The specified item already exists in the keychain"; break;
+ case errSecItemNotFound: message = @"The specified item could not be found in the keychain"; break;
+ case errSecInteractionNotAllowed: message = @"User interaction is not allowed"; break;
+ case errSecDecode: message = @"Unable to decode the provided data"; break;
+ case errSecAuthFailed: message = @"The user name or passphrase you entered is not correct"; break;
+ default: message = @"Refer to SecBase.h for description";
+#elif __has_feature(objc_arc)
+ default:
+ message = (__bridge_transfer NSString *)SecCopyErrorMessageString(code, NULL);
+#else
+ default:
+ message = [(id) SecCopyErrorMessageString(code, NULL) autorelease];
+#endif
+ }
+
+ NSDictionary *userInfo = nil;
+ if (message != nil) {
+ userInfo = @{ NSLocalizedDescriptionKey : message };
+ }
+ return [NSError errorWithDomain:kSSKeychainErrorDomain
+ code:code
+ userInfo:userInfo];
+}
+
+@end
diff --git a/Volta/Volta-Info.plist b/Volta/Volta-Info.plist
new file mode 100644
index 0000000..da0a045
--- /dev/null
+++ b/Volta/Volta-Info.plist
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleDisplayName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.decoder.${PRODUCT_NAME:rfc1034identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>LSRequiresIPhoneOS</key>
+ <true/>
+ <key>UIMainStoryboardFile</key>
+ <string>MainStoryboard</string>
+ <key>UIRequiredDeviceCapabilities</key>
+ <array>
+ <string>armv7</string>
+ </array>
+ <key>UISupportedInterfaceOrientations</key>
+ <array>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ </array>
+</dict>
+</plist>
diff --git a/Volta/Volta-Prefix.pch b/Volta/Volta-Prefix.pch
new file mode 100644
index 0000000..6bed816
--- /dev/null
+++ b/Volta/Volta-Prefix.pch
@@ -0,0 +1,28 @@
+//
+// Prefix header for all source files of the 'Volta' target in the 'Volta' project
+//
+
+#import <Availability.h>
+
+#ifndef __IPHONE_5_0
+#warning "This project uses features only available in iOS SDK 5.0 and later."
+#endif
+
+#ifdef __OBJC__
+
+#import <UIKit/UIKit.h>
+#import <Foundation/Foundation.h>
+#import <BlocksKit/BlocksKit.h>
+#import "NSString+Additions.h"
+#import "NSDictionary+Additions.h"
+#import "MBProgressHUD.h"
+#import "BlockAlertView.h"
+#import "AppDelegate.h"
+#import "UIView+Additions.h"
+#import "UIImage+Additions.h"
+#import "UIView+Decoder.h"
+#import "SSKeychain.h"
+#import "UIImageView+AFNetworking.h"
+#import "AFNetworking.h"
+
+#endif
diff --git a/Volta/en.lproj/InfoPlist.strings b/Volta/en.lproj/InfoPlist.strings
new file mode 100644
index 0000000..477b28f
--- /dev/null
+++ b/Volta/en.lproj/InfoPlist.strings
@@ -0,0 +1,2 @@
+/* Localized versions of Info.plist keys */
+
diff --git a/Volta/en.lproj/MainStoryboard.storyboard b/Volta/en.lproj/MainStoryboard.storyboard
new file mode 100644
index 0000000..cb068f5
--- /dev/null
+++ b/Volta/en.lproj/MainStoryboard.storyboard
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="2.0" toolsVersion="3084" systemVersion="12E55" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="2">
+ <dependencies>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="2083"/>
+ </dependencies>
+ <scenes>
+ <!--View Controller-->
+ <scene sceneID="5">
+ <objects>
+ <viewController id="2" customClass="ViewController" sceneMemberID="viewController">
+ <view key="view" contentMode="scaleToFill" id="3">
+ <rect key="frame" x="0.0" y="20" width="320" height="548"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+ <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
+ </view>
+ </viewController>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="4" sceneMemberID="firstResponder"/>
+ </objects>
+ </scene>
+ </scenes>
+ <simulatedMetricsContainer key="defaultSimulatedMetrics">
+ <simulatedStatusBarMetrics key="statusBar"/>
+ <simulatedOrientationMetrics key="orientation"/>
+ <simulatedScreenMetrics key="destination" type="retina4"/>
+ </simulatedMetricsContainer>
+</document> \ No newline at end of file
diff --git a/Volta/main.m b/Volta/main.m
new file mode 100644
index 0000000..800b38d
--- /dev/null
+++ b/Volta/main.m
@@ -0,0 +1,18 @@
+//
+// main.m
+// Volta
+//
+// Created by Ronny Fenrich on 2013-06-13.
+// Copyright (c) 2013 Decoder. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+#import "AppDelegate.h"
+
+int main(int argc, char *argv[])
+{
+ @autoreleasepool {
+ return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
+ }
+}