├── .gitignore ├── ImageHosting.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── ImageHosting ├── Addition │ ├── NSColor+IHAddition.h │ ├── NSColor+IHAddition.m │ ├── NSString+IHAddition.h │ ├── NSString+IHAddition.m │ ├── NSString+IHURL.h │ └── NSString+IHURL.m ├── Application │ ├── AppDelegate.h │ ├── AppDelegate.m │ └── IHCommon.h ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── icon128.png │ │ ├── icon128@2x.png │ │ ├── icon16.png │ │ ├── icon16@2x.png │ │ ├── icon256.png │ │ ├── icon256@2x.png │ │ ├── icon32.png │ │ ├── icon32@2x.png │ │ ├── icon512.png │ │ └── icon512@2x.png │ ├── Contents.json │ ├── about.imageset │ │ ├── Contents.json │ │ ├── icon128.png │ │ └── icon128@2x.png │ ├── fail.imageset │ │ ├── Contents.json │ │ └── fail.png │ ├── failure.imageset │ │ ├── Contents.json │ │ ├── Failure.png │ │ ├── Failure@2x.png │ │ └── Failure@3x.png │ ├── line.imageset │ │ ├── Contents.json │ │ └── line.png │ ├── logo.imageset │ │ ├── Contents.json │ │ ├── logo.png │ │ ├── logo@2x.png │ │ └── logo@3x.png │ ├── success.imageset │ │ ├── Contents.json │ │ └── success.png │ └── successful.imageset │ │ ├── Contents.json │ │ ├── success.png │ │ ├── success@2x.png │ │ └── success@3x.png ├── Base.lproj │ └── Main.storyboard ├── Controller │ ├── View │ │ ├── IHPreferencesAccountsViewController.h │ │ ├── IHPreferencesAccountsViewController.m │ │ ├── IHPreferencesAccountsViewController.xib │ │ ├── IHPreferencesFeedbackViewController.h │ │ ├── IHPreferencesFeedbackViewController.m │ │ ├── IHPreferencesFeedbackViewController.xib │ │ ├── IHPreferencesGeneralViewController.h │ │ ├── IHPreferencesGeneralViewController.m │ │ ├── IHPreferencesGeneralViewController.xib │ │ ├── IHViewController.h │ │ └── IHViewController.m │ └── Window │ │ ├── IHAboutWindowController.h │ │ ├── IHAboutWindowController.m │ │ ├── IHAboutWindowController.xib │ │ ├── IHPreferencesWindowController.h │ │ ├── IHPreferencesWindowController.m │ │ ├── IHPreferencesWindowController.xib │ │ ├── IHUploadWindowController.h │ │ ├── IHUploadWindowController.m │ │ ├── IHUploadWindowController.xib │ │ ├── IHWindowController.h │ │ └── IHWindowController.m ├── External │ ├── AFNetworking │ │ ├── AFHTTPSessionManager.h │ │ ├── AFHTTPSessionManager.m │ │ ├── AFNetworkReachabilityManager.h │ │ ├── AFNetworkReachabilityManager.m │ │ ├── AFNetworking.h │ │ ├── AFSecurityPolicy.h │ │ ├── AFSecurityPolicy.m │ │ ├── AFURLRequestSerialization.h │ │ ├── AFURLRequestSerialization.m │ │ ├── AFURLResponseSerialization.h │ │ ├── AFURLResponseSerialization.m │ │ ├── AFURLSessionManager.h │ │ └── AFURLSessionManager.m │ ├── AGAsyncTestHelper │ │ └── AGAsyncTestHelper.h │ ├── BRLinkLabel │ │ ├── BRLinkLabel.h │ │ └── BRLinkLabel.m │ ├── HappyDNS │ │ ├── Common │ │ │ ├── QNDnsManager.h │ │ │ ├── QNDnsManager.m │ │ │ ├── QNDomain.h │ │ │ ├── QNDomain.m │ │ │ ├── QNLruCache.h │ │ │ ├── QNLruCache.m │ │ │ ├── QNNetworkInfo.h │ │ │ ├── QNNetworkInfo.m │ │ │ ├── QNRecord.h │ │ │ ├── QNRecord.m │ │ │ └── QNResolverDelegate.h │ │ ├── HappyDNS.h │ │ ├── Http │ │ │ ├── QNDnspodEnterprise.h │ │ │ ├── QNDnspodEnterprise.m │ │ │ ├── QNDnspodFree.h │ │ │ └── QNDnspodFree.m │ │ ├── Local │ │ │ ├── QNHijackingDetectWrapper.h │ │ │ ├── QNHijackingDetectWrapper.m │ │ │ ├── QNHosts.h │ │ │ ├── QNHosts.m │ │ │ ├── QNResolvUtil.h │ │ │ ├── QNResolvUtil.m │ │ │ ├── QNResolver.h │ │ │ ├── QNResolver.m │ │ │ ├── QNTxtResolver.h │ │ │ └── QNTxtResolver.m │ │ └── Util │ │ │ ├── QNDes.h │ │ │ ├── QNDes.m │ │ │ ├── QNGetAddrInfo.h │ │ │ ├── QNGetAddrInfo.m │ │ │ ├── QNHex.h │ │ │ ├── QNHex.m │ │ │ ├── QNIP.h │ │ │ └── QNIP.m │ ├── JSONKit │ │ ├── JSONKit.h │ │ └── JSONKit.m │ ├── QiniuSDK │ │ ├── Common │ │ │ ├── QNALAssetFile.h │ │ │ ├── QNALAssetFile.m │ │ │ ├── QNAsyncRun.h │ │ │ ├── QNAsyncRun.m │ │ │ ├── QNCrc32.h │ │ │ ├── QNCrc32.m │ │ │ ├── QNEtag.h │ │ │ ├── QNEtag.m │ │ │ ├── QNFile.h │ │ │ ├── QNFile.m │ │ │ ├── QNFileDelegate.h │ │ │ ├── QNPHAssetFile.h │ │ │ ├── QNPHAssetFile.m │ │ │ ├── QNPHAssetResource.h │ │ │ ├── QNPHAssetResource.m │ │ │ ├── QNSystem.h │ │ │ ├── QNSystem.m │ │ │ ├── QNUrlSafeBase64.h │ │ │ ├── QNUrlSafeBase64.m │ │ │ ├── QNVersion.h │ │ │ ├── QN_GTM_Base64.h │ │ │ └── QN_GTM_Base64.m │ │ ├── Http │ │ │ ├── QNHttpDelegate.h │ │ │ ├── QNResponseInfo.h │ │ │ ├── QNResponseInfo.m │ │ │ ├── QNSessionManager.h │ │ │ ├── QNSessionManager.m │ │ │ ├── QNUserAgent.h │ │ │ └── QNUserAgent.m │ │ ├── QiniuSDK.h │ │ ├── Recorder │ │ │ ├── QNFileRecorder.h │ │ │ ├── QNFileRecorder.m │ │ │ └── QNRecorderDelegate.h │ │ └── Storage │ │ │ ├── QNConfiguration.h │ │ │ ├── QNConfiguration.m │ │ │ ├── QNFormUpload.h │ │ │ ├── QNFormUpload.m │ │ │ ├── QNResumeUpload.h │ │ │ ├── QNResumeUpload.m │ │ │ ├── QNUpToken.h │ │ │ ├── QNUpToken.m │ │ │ ├── QNUploadManager.h │ │ │ ├── QNUploadManager.m │ │ │ ├── QNUploadOption+Private.h │ │ │ ├── QNUploadOption.h │ │ │ └── QNUploadOption.m │ └── UIKit+AFNetworking │ │ ├── AFAutoPurgingImageCache.h │ │ ├── AFAutoPurgingImageCache.m │ │ ├── AFImageDownloader.h │ │ ├── AFImageDownloader.m │ │ ├── AFNetworkActivityIndicatorManager.h │ │ ├── AFNetworkActivityIndicatorManager.m │ │ ├── UIActivityIndicatorView+AFNetworking.h │ │ ├── UIActivityIndicatorView+AFNetworking.m │ │ ├── UIButton+AFNetworking.h │ │ ├── UIButton+AFNetworking.m │ │ ├── UIImage+AFNetworking.h │ │ ├── UIImageView+AFNetworking.h │ │ ├── UIImageView+AFNetworking.m │ │ ├── UIKit+AFNetworking.h │ │ ├── UIProgressView+AFNetworking.h │ │ ├── UIProgressView+AFNetworking.m │ │ ├── UIRefreshControl+AFNetworking.h │ │ ├── UIRefreshControl+AFNetworking.m │ │ ├── UIWebView+AFNetworking.h │ │ └── UIWebView+AFNetworking.m ├── ImageHosting-Prefix.pch ├── ImageHosting.entitlements ├── Info.plist ├── Model │ ├── IHAccount.h │ ├── IHAccount.m │ ├── IHCache.h │ ├── IHCache.m │ ├── IHGeneral.h │ ├── IHGeneral.m │ └── const.h ├── Util │ ├── IHAccountManager.h │ ├── IHAccountManager.m │ ├── IHGeneralManager.h │ ├── IHGeneralManager.m │ ├── IHPreferencesManager.h │ ├── IHPreferencesManager.m │ ├── IHQiniuTokenManager.h │ ├── IHQiniuTokenManager.m │ ├── IHQiniuUploadManager.h │ └── IHQiniuUploadManager.m ├── View │ ├── IHProgressIndicator.h │ ├── IHProgressIndicator.m │ ├── IHTableView.h │ ├── IHTableView.m │ ├── IHUploadFileCell.h │ ├── IHUploadFileCell.m │ └── IHUploadFileCell.xib └── main.m ├── ImageHostingHelper ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Base.lproj │ └── Main.storyboard ├── ImageHostingHelper.entitlements ├── Info.plist ├── ViewController.h ├── ViewController.m └── main.m ├── ImageHostingHelperTests ├── ImageHostingHelperTests.m └── Info.plist ├── ImageHostingHelperUITests ├── ImageHostingHelperUITests.m └── Info.plist ├── ImageHostingTests ├── ImageHostingTests.m └── Info.plist ├── ImageHostingUITests ├── ImageHostingUITests.m └── Info.plist ├── LICENSE ├── README.md ├── SRC ├── archive │ └── Applications └── image │ ├── background.tif │ ├── icon.png │ ├── upload.png │ ├── upload_1.png │ ├── upload_2.png │ └── upload_3.png └── uncrustify.cfg /.gitignore: -------------------------------------------------------------------------------- 1 | tignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 2 | 3 | ## Build generated 4 | build/ 5 | DerivedData/ 6 | 7 | ## Various settings 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata/ 17 | 18 | ## Other 19 | *.moved-aside 20 | *.xcuserstate 21 | *.DS_Store 22 | 23 | ## Obj-C/Swift specific 24 | *.hmap 25 | *.ipa 26 | *.dSYM.zip 27 | *.dSYM 28 | 29 | # CocoaPods 30 | # 31 | # We recommend against adding the Pods directory to your .gitignore. However 32 | # you should judge for yourself, the pros and cons are mentioned at: 33 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 34 | # 35 | # Pods/ 36 | 37 | # Carthage 38 | # 39 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 40 | # Carthage/Checkouts 41 | 42 | Carthage/Build 43 | 44 | # fastlane 45 | # 46 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 47 | # screenshots whenever they are needed. 48 | # For more information about the recommended setup visit: 49 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 50 | 51 | fastlane/report.xml 52 | fastlane/screenshots 53 | 54 | #Code Injection 55 | # 56 | # After new code Injection tools there's a generated folder /iOSInjectionProject 57 | # https://github.com/johnno1962/injectionforxcode 58 | 59 | iOSInjectionProject/ 60 | 61 | -------------------------------------------------------------------------------- /ImageHosting.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ImageHosting/Addition/NSColor+IHAddition.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSColor+IHAddition.h 3 | // ImageHosting 4 | // 5 | // Created by chars on 16/9/2. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSColor (IHAddition) 12 | 13 | + (NSColor *)ih_colorWithRGBString:(NSString *)string; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ImageHosting/Addition/NSColor+IHAddition.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSColor+IHAddition.m 3 | // ImageHosting 4 | // 5 | // Created by chars on 16/9/2. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import "NSColor+IHAddition.h" 10 | 11 | @implementation NSColor (IHAddition) 12 | 13 | + (NSColor *)ih_colorWithRGBString:(NSString *)string 14 | { 15 | return [[self class] ih_colorWithRGBString:string alpha:1.0f]; 16 | } 17 | 18 | + (NSColor *)ih_colorWithRGBString:(NSString *)string alpha:(CGFloat)alpha 19 | { 20 | if (!string || [string length] < 6) { 21 | return nil; 22 | } 23 | 24 | const char *cStr = [string cStringUsingEncoding:NSASCIIStringEncoding]; 25 | long hex; 26 | if ([string length] <= 6) { 27 | hex = strtol(cStr, NULL, 16); 28 | } else { 29 | hex = strtol(cStr + 1, NULL, 16); 30 | } 31 | return [self ih_colorWithRGBHex:(NSUInteger)hex alpha:alpha]; 32 | } 33 | 34 | + (NSColor *)ih_colorWithRGBHex:(NSUInteger)hex 35 | { 36 | return [self ih_colorWithRGBHex:hex alpha:1.0f]; 37 | } 38 | 39 | + (NSColor *)ih_colorWithRGBHex:(NSUInteger)hex alpha:(CGFloat)alpha 40 | { 41 | unsigned char red = (hex >> 16) & 0xFF; 42 | unsigned char green = (hex >> 8) & 0xFF; 43 | unsigned char blue = hex & 0xFF; 44 | 45 | return [NSColor colorWithRed:(CGFloat)red / 255.0f 46 | green:(CGFloat)green / 255.0f 47 | blue:(CGFloat)blue / 255.0f 48 | alpha:alpha]; 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /ImageHosting/Addition/NSString+IHAddition.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+IHAddition.h 3 | // ImageHosting 4 | // 5 | // Created by dengw on 16/8/20. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSString (IHAddition) 12 | 13 | /** 加密 */ 14 | - (NSString *)ih_encode; 15 | 16 | /** 解密 */ 17 | - (NSString *)ih_decode; 18 | 19 | /** 是否有效字符串 */ 20 | - (BOOL)ih_isValid; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /ImageHosting/Addition/NSString+IHAddition.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+IHAddition.m 3 | // ImageHosting 4 | // 5 | // Created by dengw on 16/8/20. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import "NSString+IHAddition.h" 10 | #import "QN_GTM_Base64.h" 11 | 12 | @implementation NSString (IHAddition) 13 | 14 | - (NSString *)ih_encode 15 | { 16 | NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding]; 17 | return [QN_GTM_Base64 stringByEncodingData:data]; 18 | } 19 | 20 | - (NSString *)ih_decode 21 | { 22 | NSData *data = [QN_GTM_Base64 decodeString:self]; 23 | return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 24 | } 25 | 26 | - (BOOL)ih_isValid 27 | { 28 | if (self.length > 0) { 29 | return YES; 30 | } 31 | return NO; 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /ImageHosting/Addition/NSString+IHURL.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+IHURL.h 3 | // ImageHosting 4 | // 5 | // Created by chars on 16/9/2. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSString (IHURL) 12 | 13 | /** 14 | * URLEncode 15 | */ 16 | - (NSString *)URLEncodedString; 17 | 18 | /** 19 | * URLDecode 20 | */ 21 | -(NSString *)URLDecodedString; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /ImageHosting/Addition/NSString+IHURL.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+IHURL.m 3 | // ImageHosting 4 | // 5 | // Created by chars on 16/9/2. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import "NSString+IHURL.h" 10 | 11 | @implementation NSString (IHURL) 12 | 13 | /** 14 | * URLEncode 15 | */ 16 | - (NSString *)URLEncodedString 17 | { 18 | // CharactersToBeEscaped = @":/?&=;+!@#$()~',*"; 19 | // CharactersToLeaveUnescaped = @"[]."; 20 | 21 | NSString *unencodedString = self; 22 | NSString *encodedString = (NSString *) 23 | CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)unencodedString, NULL, (CFStringRef)@"!*'();:@&=+$,/?%#[]", kCFStringEncodingUTF8)); 24 | return encodedString; 25 | } 26 | 27 | /** 28 | * URLDecode 29 | */ 30 | - (NSString *)URLDecodedString 31 | { 32 | //NSString *decodedString = [encodedString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding ]; 33 | 34 | NSString *encodedString = self; 35 | NSString *decodedString = (__bridge_transfer NSString *)CFURLCreateStringByReplacingPercentEscapesUsingEncoding(NULL, (__bridge CFStringRef)encodedString, CFSTR(""), CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding)); 36 | return decodedString; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /ImageHosting/Application/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // ImageHosting 4 | // 5 | // Created by chars on 16/8/16. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : NSObject 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /ImageHosting/Application/IHCommon.h: -------------------------------------------------------------------------------- 1 | // 2 | // IHCommon.h 3 | // ImageHosting 4 | // 5 | // Created by chars on 16/9/7. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #ifndef IHCommon_h 10 | #define IHCommon_h 11 | 12 | //自定义日志输出 13 | #ifdef DEBUG 14 | //调试状态 15 | #define IHLog(...) NSLog(@"%s line:%d\n %@ \n\n", __func__, __LINE__, [NSString stringWithFormat:__VA_ARGS__]) 16 | #else 17 | //发布状态 18 | #define IHLog(...) 19 | #endif 20 | 21 | 22 | #endif /* IHCommon_h */ 23 | -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "icon16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "icon16@2x.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "icon32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "icon32@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "icon128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "icon128@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "icon256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "icon256@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "icon512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "icon512@2x.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/AppIcon.appiconset/icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charsdavy/ImageHosting/048e49b60b0f5212d8ae110d51cd83c387d982c4/ImageHosting/Assets.xcassets/AppIcon.appiconset/icon128.png -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/AppIcon.appiconset/icon128@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charsdavy/ImageHosting/048e49b60b0f5212d8ae110d51cd83c387d982c4/ImageHosting/Assets.xcassets/AppIcon.appiconset/icon128@2x.png -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/AppIcon.appiconset/icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charsdavy/ImageHosting/048e49b60b0f5212d8ae110d51cd83c387d982c4/ImageHosting/Assets.xcassets/AppIcon.appiconset/icon16.png -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/AppIcon.appiconset/icon16@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charsdavy/ImageHosting/048e49b60b0f5212d8ae110d51cd83c387d982c4/ImageHosting/Assets.xcassets/AppIcon.appiconset/icon16@2x.png -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/AppIcon.appiconset/icon256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charsdavy/ImageHosting/048e49b60b0f5212d8ae110d51cd83c387d982c4/ImageHosting/Assets.xcassets/AppIcon.appiconset/icon256.png -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/AppIcon.appiconset/icon256@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charsdavy/ImageHosting/048e49b60b0f5212d8ae110d51cd83c387d982c4/ImageHosting/Assets.xcassets/AppIcon.appiconset/icon256@2x.png -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/AppIcon.appiconset/icon32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charsdavy/ImageHosting/048e49b60b0f5212d8ae110d51cd83c387d982c4/ImageHosting/Assets.xcassets/AppIcon.appiconset/icon32.png -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/AppIcon.appiconset/icon32@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charsdavy/ImageHosting/048e49b60b0f5212d8ae110d51cd83c387d982c4/ImageHosting/Assets.xcassets/AppIcon.appiconset/icon32@2x.png -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/AppIcon.appiconset/icon512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charsdavy/ImageHosting/048e49b60b0f5212d8ae110d51cd83c387d982c4/ImageHosting/Assets.xcassets/AppIcon.appiconset/icon512.png -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/AppIcon.appiconset/icon512@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charsdavy/ImageHosting/048e49b60b0f5212d8ae110d51cd83c387d982c4/ImageHosting/Assets.xcassets/AppIcon.appiconset/icon512@2x.png -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/about.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon128.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "icon128@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/about.imageset/icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charsdavy/ImageHosting/048e49b60b0f5212d8ae110d51cd83c387d982c4/ImageHosting/Assets.xcassets/about.imageset/icon128.png -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/about.imageset/icon128@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charsdavy/ImageHosting/048e49b60b0f5212d8ae110d51cd83c387d982c4/ImageHosting/Assets.xcassets/about.imageset/icon128@2x.png -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/fail.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "fail.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/fail.imageset/fail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charsdavy/ImageHosting/048e49b60b0f5212d8ae110d51cd83c387d982c4/ImageHosting/Assets.xcassets/fail.imageset/fail.png -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/failure.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Failure.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Failure@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Failure@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/failure.imageset/Failure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charsdavy/ImageHosting/048e49b60b0f5212d8ae110d51cd83c387d982c4/ImageHosting/Assets.xcassets/failure.imageset/Failure.png -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/failure.imageset/Failure@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charsdavy/ImageHosting/048e49b60b0f5212d8ae110d51cd83c387d982c4/ImageHosting/Assets.xcassets/failure.imageset/Failure@2x.png -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/failure.imageset/Failure@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charsdavy/ImageHosting/048e49b60b0f5212d8ae110d51cd83c387d982c4/ImageHosting/Assets.xcassets/failure.imageset/Failure@3x.png -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/line.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "line.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/line.imageset/line.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charsdavy/ImageHosting/048e49b60b0f5212d8ae110d51cd83c387d982c4/ImageHosting/Assets.xcassets/line.imageset/line.png -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/logo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "logo.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "logo@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "logo@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/logo.imageset/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charsdavy/ImageHosting/048e49b60b0f5212d8ae110d51cd83c387d982c4/ImageHosting/Assets.xcassets/logo.imageset/logo.png -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/logo.imageset/logo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charsdavy/ImageHosting/048e49b60b0f5212d8ae110d51cd83c387d982c4/ImageHosting/Assets.xcassets/logo.imageset/logo@2x.png -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/logo.imageset/logo@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charsdavy/ImageHosting/048e49b60b0f5212d8ae110d51cd83c387d982c4/ImageHosting/Assets.xcassets/logo.imageset/logo@3x.png -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/success.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "success.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/success.imageset/success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charsdavy/ImageHosting/048e49b60b0f5212d8ae110d51cd83c387d982c4/ImageHosting/Assets.xcassets/success.imageset/success.png -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/successful.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "success.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "success@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "success@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/successful.imageset/success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charsdavy/ImageHosting/048e49b60b0f5212d8ae110d51cd83c387d982c4/ImageHosting/Assets.xcassets/successful.imageset/success.png -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/successful.imageset/success@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charsdavy/ImageHosting/048e49b60b0f5212d8ae110d51cd83c387d982c4/ImageHosting/Assets.xcassets/successful.imageset/success@2x.png -------------------------------------------------------------------------------- /ImageHosting/Assets.xcassets/successful.imageset/success@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charsdavy/ImageHosting/048e49b60b0f5212d8ae110d51cd83c387d982c4/ImageHosting/Assets.xcassets/successful.imageset/success@3x.png -------------------------------------------------------------------------------- /ImageHosting/Controller/View/IHPreferencesAccountsViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // IHPreferencesAccountsViewController.h 3 | // ImageHosting 4 | // 5 | // Created by chars on 16/8/19. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import "IHViewController.h" 10 | 11 | @interface IHPreferencesAccountsViewController : IHViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ImageHosting/Controller/View/IHPreferencesAccountsViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // IHPreferencesAccountsViewController.m 3 | // ImageHosting 4 | // 5 | // Created by chars on 16/8/19. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import "IHPreferencesAccountsViewController.h" 10 | #import "IHAccountManager.h" 11 | #import "IHAccount.h" 12 | #import "const.h" 13 | 14 | @interface IHPreferencesAccountsViewController () 15 | 16 | @property (weak) IBOutlet NSTextField *akTextField; 17 | @property (weak) IBOutlet NSSecureTextField *skTextField; 18 | @property (weak) IBOutlet NSTextField *bucketNameTextField; 19 | @property (weak) IBOutlet NSButton *east; 20 | @property (weak) IBOutlet NSButton *north; 21 | @property (copy) NSString *region; 22 | 23 | @end 24 | 25 | @implementation IHPreferencesAccountsViewController 26 | 27 | - (void)viewDidLoad 28 | { 29 | [super viewDidLoad]; 30 | // Do view setup here. 31 | _region = REGION_EAST_CHINA; 32 | [self fillCurrentAccount]; 33 | } 34 | 35 | - (void)fillCurrentAccount 36 | { 37 | IHAccount *currentAccount = [[IHAccountManager sharedManager] currentAccount]; 38 | if (currentAccount) { 39 | _akTextField.stringValue = currentAccount.ak; 40 | _skTextField.stringValue = currentAccount.sk; 41 | _bucketNameTextField.stringValue = currentAccount.bucketName; 42 | if ([currentAccount.region isEqualToString:REGION_EAST_CHINA]) { 43 | _east.state = 1; 44 | _north.state = 0; 45 | } else if ([currentAccount.region isEqualToString:REGION_NORTH_CHINA]) { 46 | _east.state = 0; 47 | _north.state = 1; 48 | } 49 | } else { 50 | _east.state = 1; 51 | _north.state = 0; 52 | } 53 | } 54 | 55 | - (IBAction)clickedSubmit:(id)sender 56 | { 57 | IHAccount *account = [[IHAccount alloc] init]; 58 | account.accountType = IHAccountTypeQiniu; 59 | account.ak = _akTextField.stringValue; 60 | account.sk = _skTextField.stringValue; 61 | account.bucketName = _bucketNameTextField.stringValue; 62 | account.region = self.region; 63 | 64 | BOOL success = [[IHAccountManager sharedManager] archive:account key:ACCOUNTS_KEY]; 65 | if (success) { 66 | NSString *title = @"Configure Success"; 67 | NSString *msg = @"Config Account Info Success ! Please continue another operation "; 68 | [self showAlertTitle:title message:msg style:IHAlertStyleInformational]; 69 | } else { 70 | NSString *title = @"Configure Failed"; 71 | NSString *msg = @"Config Account Info Failed ! Please again "; 72 | [self showAlertTitle:title message:msg style:IHAlertStyleWarning]; 73 | [self clearAccountViewContent]; 74 | } 75 | } 76 | 77 | - (IBAction)clickedRegion:(NSButton *)sender { 78 | if (sender.tag == 1) { 79 | self.region = REGION_EAST_CHINA; 80 | } else if (sender.tag == 0) { 81 | self.region = REGION_NORTH_CHINA; 82 | } 83 | } 84 | 85 | - (void)showAlertTitle:(NSString *)title message:(NSString *)message style:(IHAlertStyle)style 86 | { 87 | NSAlertStyle alertStyle = NSInformationalAlertStyle; 88 | if (style == IHAlertStyleWarning) { 89 | alertStyle = NSWarningAlertStyle; 90 | } else if (style == IHAlertStyleCritical) { 91 | alertStyle = NSCriticalAlertStyle; 92 | } else if (style == IHAlertStyleInformational) { 93 | alertStyle = NSInformationalAlertStyle; 94 | } else { 95 | alertStyle = NSInformationalAlertStyle; 96 | } 97 | 98 | NSAlert *alert = [NSAlert alertWithMessageText:title defaultButton:@"Okay" alternateButton:nil otherButton:nil informativeTextWithFormat:@"%@", message]; 99 | alert.alertStyle = alertStyle; 100 | [alert beginSheetModalForWindow:self.preferencesWindow completionHandler:nil]; 101 | } 102 | 103 | - (void)clearAccountViewContent 104 | { 105 | _akTextField.stringValue = @""; 106 | _skTextField.stringValue = @""; 107 | _bucketNameTextField.stringValue = @""; 108 | _east.state = 1; 109 | _north.state = 0; 110 | } 111 | 112 | @end 113 | -------------------------------------------------------------------------------- /ImageHosting/Controller/View/IHPreferencesFeedbackViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // IHPreferencesFeedbackViewController.h 3 | // ImageHosting 4 | // 5 | // Created by chars on 16/8/22. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import "IHViewController.h" 10 | 11 | @interface IHPreferencesFeedbackViewController : IHViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ImageHosting/Controller/View/IHPreferencesFeedbackViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // IHPreferencesFeedbackViewController.m 3 | // ImageHosting 4 | // 5 | // Created by chars on 16/8/22. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import "IHPreferencesFeedbackViewController.h" 10 | #import "BRLinkLabel.h" 11 | 12 | #define FONT_FEED_BACK 14.0f 13 | 14 | @interface IHPreferencesFeedbackViewController () 15 | 16 | @end 17 | 18 | @implementation IHPreferencesFeedbackViewController 19 | 20 | - (void)viewDidLoad 21 | { 22 | [super viewDidLoad]; 23 | // Do view setup here. 24 | 25 | [self emailLabel]; 26 | [self githubLabel]; 27 | [self weiboLabel]; 28 | [self tiwtterLabel]; 29 | } 30 | 31 | - (void)emailLabel 32 | { 33 | NSString *title = @"chars.davy@gmail.com"; 34 | CGSize size = [title sizeWithAttributes:@{ NSFontAttributeName: [NSFont systemFontOfSize:FONT_FEED_BACK] }]; 35 | NSRect frame = NSMakeRect(144, 220, size.width, 20); 36 | NSString *email = @"mailto:chars.davy@gmail.com";; 37 | email = [email stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]; 38 | BRLinkLabel *linkLabel = [self linkLabel:title link:email frame:frame]; 39 | linkLabel.accessibilitySelected = YES; 40 | [self.view addSubview:linkLabel]; 41 | } 42 | 43 | - (void)githubLabel 44 | { 45 | NSString *title = @"@charsdavy"; 46 | CGSize size = [title sizeWithAttributes:@{ NSFontAttributeName: [NSFont systemFontOfSize:FONT_FEED_BACK] }]; 47 | NSRect frame = NSMakeRect(144, 167, size.width, 20); 48 | NSString *link = @"https://github.com/charsdavy"; 49 | BRLinkLabel *linkLabel = [self linkLabel:title link:link frame:frame]; 50 | [self.view addSubview:linkLabel]; 51 | } 52 | 53 | - (void)weiboLabel 54 | { 55 | NSString *title = @"@Chars-D"; 56 | CGSize size = [title sizeWithAttributes:@{ NSFontAttributeName: [NSFont systemFontOfSize:FONT_FEED_BACK] }]; 57 | NSRect frame = NSMakeRect(144, 115, size.width, 20); 58 | NSString *link = @"http://weibo.com/u/3875245858"; 59 | BRLinkLabel *linkLabel = [self linkLabel:title link:link frame:frame]; 60 | [self.view addSubview:linkLabel]; 61 | } 62 | 63 | - (void)tiwtterLabel 64 | { 65 | NSString *title = @"@charsdavy"; 66 | CGSize size = [title sizeWithAttributes:@{ NSFontAttributeName: [NSFont systemFontOfSize:FONT_FEED_BACK] }]; 67 | NSRect frame = NSMakeRect(144, 65, size.width, 20); 68 | NSString *link = @"https://twitter.com/charsdavy"; 69 | BRLinkLabel *linkLabel = [self linkLabel:title link:link frame:frame]; 70 | [self.view addSubview:linkLabel]; 71 | } 72 | 73 | - (BRLinkLabel *)linkLabel:(NSString *)title link:(NSString *)link frame:(CGRect)frame 74 | { 75 | NSAttributedString *attString = [[NSAttributedString alloc] initWithString:title attributes:@{ NSLinkAttributeName:link, NSForegroundColorAttributeName: [NSColor colorWithRed:16 / 255.0 green:64 / 255.0 blue:251 / 255.0 alpha:1.0f] }]; 76 | BRLinkLabel *linkLabel = [[BRLinkLabel alloc] initWithFrame:frame attibutedString:attString]; 77 | linkLabel.showBackground = NO; 78 | return linkLabel; 79 | } 80 | 81 | @end 82 | -------------------------------------------------------------------------------- /ImageHosting/Controller/View/IHPreferencesFeedbackViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /ImageHosting/Controller/View/IHPreferencesGeneralViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // IHPreferencesGeneralViewController.h 3 | // ImageHosting 4 | // 5 | // Created by chars on 16/8/19. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import "IHViewController.h" 10 | 11 | @interface IHPreferencesGeneralViewController : IHViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ImageHosting/Controller/View/IHPreferencesGeneralViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // IHPreferencesGeneralViewController.m 3 | // ImageHosting 4 | // 5 | // Created by chars on 16/8/19. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import "IHPreferencesGeneralViewController.h" 10 | #import "IHGeneralManager.h" 11 | #import "IHGeneral.h" 12 | #import "const.h" 13 | 14 | @interface IHPreferencesGeneralViewController () 15 | 16 | @property (weak) IBOutlet NSButton *launch; 17 | @property (weak) IBOutlet NSButton *systemNotification; 18 | 19 | @end 20 | 21 | @implementation IHPreferencesGeneralViewController 22 | 23 | - (void)viewDidLoad { 24 | [super viewDidLoad]; 25 | // Do view setup here. 26 | 27 | [self initSubViews]; 28 | } 29 | 30 | - (void)initSubViews 31 | { 32 | IHGeneral *general = [[IHGeneral alloc] init]; 33 | general = [[IHGeneralManager sharedManager] unarchiveForKey:SYSTEM_NOTIFICATION_KEY]; 34 | 35 | if ([general.launchStartUp isEqualToString:@"YES"]) { 36 | _launch.state = 1; 37 | [[IHGeneralManager sharedManager] startupAppWhenLogin:YES]; 38 | } else { 39 | _launch.state = 0; 40 | [[IHGeneralManager sharedManager] startupAppWhenLogin:NO]; 41 | } 42 | 43 | if ([general.userNotification isEqualToString:@"YES"]) { 44 | _systemNotification.state = 1; 45 | } else { 46 | _systemNotification.state = 0; 47 | } 48 | } 49 | 50 | - (IBAction)launchStartUp:(NSButton *)sender { 51 | IHLog(@"state:%zi", sender.state); 52 | NSString *launch = sender.state ? @"YES" : @"NO"; 53 | 54 | if (sender.state) { 55 | [[IHGeneralManager sharedManager] startupAppWhenLogin:YES]; 56 | } else { 57 | [[IHGeneralManager sharedManager] startupAppWhenLogin:NO]; 58 | } 59 | 60 | IHGeneral *general = [[IHGeneral alloc] init]; 61 | general = [[IHGeneralManager sharedManager] unarchiveForKey:SYSTEM_NOTIFICATION_KEY]; 62 | general.launchStartUp = launch; 63 | 64 | [[IHGeneralManager sharedManager] archive:general key:SYSTEM_NOTIFICATION_KEY]; 65 | } 66 | 67 | - (IBAction)systemNotification:(NSButton *)sender { 68 | IHLog(@"state:%zi", sender.state); 69 | NSString *noti = sender.state ? @"YES" : @"NO"; 70 | IHGeneral *general = [[IHGeneral alloc] init]; 71 | general = [[IHGeneralManager sharedManager] unarchiveForKey:SYSTEM_NOTIFICATION_KEY]; 72 | general.userNotification = noti; 73 | 74 | [[IHGeneralManager sharedManager] archive:general key:SYSTEM_NOTIFICATION_KEY]; 75 | } 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /ImageHosting/Controller/View/IHViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // IHViewController.h 3 | // ImageHosting 4 | // 5 | // Created by chars on 16/8/19. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface IHViewController : NSViewController 12 | 13 | @property (nullable, strong) NSWindow *preferencesWindow; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ImageHosting/Controller/View/IHViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // IHViewController.m 3 | // ImageHosting 4 | // 5 | // Created by chars on 16/8/19. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import "IHViewController.h" 10 | 11 | @interface IHViewController () 12 | 13 | @end 14 | 15 | @implementation IHViewController 16 | 17 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 18 | { 19 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 20 | if (self) { 21 | // Initialization code here. 22 | } 23 | 24 | return self; 25 | } 26 | 27 | - (void)viewDidLoad { 28 | [super viewDidLoad]; 29 | // Do view setup here. 30 | } 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /ImageHosting/Controller/Window/IHAboutWindowController.h: -------------------------------------------------------------------------------- 1 | // 2 | // IHAboutWindowController.h 3 | // ImageHosting 4 | // 5 | // Created by dengw on 16/8/28. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import "IHWindowController.h" 10 | 11 | @interface IHAboutWindowController : IHWindowController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ImageHosting/Controller/Window/IHAboutWindowController.m: -------------------------------------------------------------------------------- 1 | // 2 | // IHAboutWindowController.m 3 | // ImageHosting 4 | // 5 | // Created by dengw on 16/8/28. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import "IHAboutWindowController.h" 10 | 11 | #define VERSION @"1.1.3" 12 | #define BUILD @"10" 13 | 14 | @interface IHAboutWindowController () 15 | 16 | @property (weak) IBOutlet NSTextField *versionTextField; 17 | @property (weak) IBOutlet NSTextField *copyrightTextField; 18 | 19 | @end 20 | 21 | @implementation IHAboutWindowController 22 | 23 | - (instancetype)init 24 | { 25 | self = [super initWithWindowNibName:@"IHAboutWindowController"]; 26 | if (self) { 27 | } 28 | return self; 29 | } 30 | 31 | - (void)windowDidLoad 32 | { 33 | [super windowDidLoad]; 34 | 35 | // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file. 36 | 37 | self.versionTextField.stringValue = [self version]; 38 | } 39 | 40 | - (NSString *)version 41 | { 42 | NSString *version = [NSString stringWithFormat:@"Version %@ (%@)", VERSION, BUILD]; 43 | return version; 44 | } 45 | 46 | #pragma mark - Showing the Preferences Window 47 | 48 | - (void)showWithCompletionHandler:(IHWindowControllerCompletionHandler)handler 49 | { 50 | self.completionHandler = handler; 51 | [self showWindow:self]; 52 | } 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /ImageHosting/Controller/Window/IHPreferencesWindowController.h: -------------------------------------------------------------------------------- 1 | // 2 | // IHPreferencesWindowController.h 3 | // ImageHosting 4 | // 5 | // Created by chars on 16/8/19. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import "IHWindowController.h" 10 | 11 | @interface IHPreferencesWindowController : IHWindowController 12 | 13 | - (IBAction)showPreferencesFor:(id)sender; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ImageHosting/Controller/Window/IHPreferencesWindowController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /ImageHosting/Controller/Window/IHUploadWindowController.h: -------------------------------------------------------------------------------- 1 | // 2 | // IHUploadWindowController.h 3 | // ImageHosting 4 | // 5 | // Created by chars on 16/8/19. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import "IHWindowController.h" 10 | 11 | @interface IHUploadWindowController : IHWindowController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ImageHosting/Controller/Window/IHWindowController.h: -------------------------------------------------------------------------------- 1 | // 2 | // IHWindowController.h 3 | // ImageHosting 4 | // 5 | // Created by chars on 16/8/16. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef void(^IHWindowControllerCompletionHandler)(void); 12 | 13 | @interface IHWindowController : NSWindowController 14 | 15 | @property (nonatomic, copy) IHWindowControllerCompletionHandler completionHandler; 16 | 17 | - (void)showWithCompletionHandler:(IHWindowControllerCompletionHandler)handler; 18 | 19 | @end 20 | 21 | -------------------------------------------------------------------------------- /ImageHosting/Controller/Window/IHWindowController.m: -------------------------------------------------------------------------------- 1 | // 2 | // IHWindowController.m 3 | // ImageHosting 4 | // 5 | // Created by chars on 16/8/16. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import "IHWindowController.h" 10 | 11 | @interface IHWindowController () 12 | 13 | @end 14 | 15 | @implementation IHWindowController 16 | 17 | - (void)showWithCompletionHandler:(IHWindowControllerCompletionHandler)handler { 18 | } 19 | 20 | - (void)windowWillClose:(NSNotification *)notification { 21 | self.completionHandler ? self.completionHandler() : nil; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /ImageHosting/External/AFNetworking/AFNetworking.h: -------------------------------------------------------------------------------- 1 | // AFNetworking.h 2 | // 3 | // Copyright (c) 2013 AFNetworking (http://afnetworking.com/) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | #import 25 | #import 26 | 27 | #ifndef _AFNETWORKING_ 28 | #define _AFNETWORKING_ 29 | 30 | #import "AFURLRequestSerialization.h" 31 | #import "AFURLResponseSerialization.h" 32 | #import "AFSecurityPolicy.h" 33 | 34 | #if !TARGET_OS_WATCH 35 | #import "AFNetworkReachabilityManager.h" 36 | #endif 37 | 38 | #import "AFURLSessionManager.h" 39 | #import "AFHTTPSessionManager.h" 40 | 41 | #endif /* _AFNETWORKING_ */ 42 | -------------------------------------------------------------------------------- /ImageHosting/External/BRLinkLabel/BRLinkLabel.h: -------------------------------------------------------------------------------- 1 | // 2 | // BRLinkLabel.h 3 | // BRLinkLabel 4 | // 5 | // Created by Yang on 16/2/29. 6 | // Copyright © 2016年 sgyang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | IB_DESIGNABLE 12 | 13 | @interface BRLinkLabel : NSView 14 | 15 | @property (nonatomic, copy) NSAttributedString *displayString; 16 | 17 | //方便直接设置attibute 18 | @property (nonatomic, copy) IBInspectable NSString *textString; 19 | @property (nonatomic, copy) IBInspectable NSString *linkString; 20 | @property (nonatomic, retain) IBInspectable NSColor *textColor; 21 | 22 | //背景相关 23 | @property (nonatomic) BOOL IBInspectable showBackground; 24 | @property (nonatomic, retain) IBInspectable NSColor *backgroundColor; 25 | 26 | - (instancetype)initWithFrame:(NSRect)frameRect attibutedString:(NSAttributedString *)displayString; 27 | //也可以用- (instancetype)initWithFrame:(NSRect)frameRect来创建 28 | 29 | @end -------------------------------------------------------------------------------- /ImageHosting/External/HappyDNS/Common/QNDnsManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNDnsManager.h 3 | // HappyDNS 4 | // 5 | // Created by bailong on 15/6/23. 6 | // Copyright (c) 2015年 Qiniu Cloud Storage. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class QNNetworkInfo; 12 | @class QNDomain; 13 | 14 | /** 15 | * 上传进度回调函数 16 | * 17 | * @param key 上传时指定的存储key 18 | * @param percent 进度百分比 19 | */ 20 | typedef NSArray * (^QNGetAddrInfoCallback)(NSString *host); 21 | 22 | @protocol QNIpSorter 23 | - (NSArray *)sort:(NSArray *)ips; 24 | @end 25 | 26 | @interface QNDnsManager : NSObject 27 | - (NSArray *)query:(NSString *)domain; 28 | - (NSArray *)queryWithDomain:(QNDomain *)domain; 29 | - (void)onNetworkChange:(QNNetworkInfo *)netInfo; 30 | - (instancetype)init:(NSArray *)resolvers networkInfo:(QNNetworkInfo *)netInfo; 31 | - (instancetype)init:(NSArray *)resolvers networkInfo:(QNNetworkInfo *)netInfo sorter:(id)sorter; 32 | - (instancetype)putHosts:(NSString *)domain ip:(NSString *)ip; 33 | - (instancetype)putHosts:(NSString *)domain ip:(NSString *)ip provider:(int)provider; 34 | + (void)setGetAddrInfoBlock:(QNGetAddrInfoCallback)block; 35 | @end 36 | 37 | @interface QNDnsManager (NSURL) 38 | - (NSURL *)queryAndReplaceWithIP:(NSURL *)url; 39 | @end -------------------------------------------------------------------------------- /ImageHosting/External/HappyDNS/Common/QNDomain.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNDomain.h 3 | // HappyDNS 4 | // 5 | // Created by bailong on 15/6/23. 6 | // Copyright (c) 2015年 Qiniu Cloud Storage. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface QNDomain : NSObject 12 | @property (nonatomic, strong, readonly) NSString *domain; 13 | 14 | // 用来判断劫持 15 | @property (nonatomic, readonly) BOOL hasCname; 16 | // 用来判断劫持 17 | @property (nonatomic, readonly) int maxTtl; 18 | 19 | @property (nonatomic, readonly) BOOL hostsFirst; 20 | 21 | - (instancetype)init:(NSString *)domain; 22 | 23 | - (instancetype)init:(NSString *)domain hostsFirst:(BOOL)hostsFirst hasCname:(BOOL)hasCname; 24 | 25 | - (instancetype)init:(NSString *)domain hostsFirst:(BOOL)hostsFirst hasCname:(BOOL)hasCname maxTtl:(int)maxTtl; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /ImageHosting/External/HappyDNS/Common/QNDomain.m: -------------------------------------------------------------------------------- 1 | // 2 | // QNDomain.m 3 | // HappyDNS 4 | // 5 | // Created by bailong on 15/6/23. 6 | // Copyright (c) 2015年 Qiniu Cloud Storage. All rights reserved. 7 | // 8 | 9 | #import "QNDomain.h" 10 | 11 | @implementation QNDomain 12 | - (instancetype)init:(NSString *)domain { 13 | return [self init:domain hostsFirst:NO hasCname:NO maxTtl:0]; 14 | } 15 | 16 | - (instancetype)init:(NSString *)domain hostsFirst:(BOOL)hostsFirst hasCname:(BOOL)hasCname { 17 | return [self init:domain hostsFirst:hostsFirst hasCname:hasCname maxTtl:0]; 18 | } 19 | 20 | - (instancetype)init:(NSString *)domain hostsFirst:(BOOL)hostsFirst hasCname:(BOOL)hasCname maxTtl:(int)maxTtl { 21 | if (self = [super init]) { 22 | _domain = domain; 23 | _hasCname = hasCname; 24 | _maxTtl = maxTtl; 25 | _hostsFirst = hostsFirst; 26 | } 27 | return self; 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /ImageHosting/External/HappyDNS/Common/QNLruCache.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNLruCache.h 3 | // HappyDNS 4 | // 5 | // Created by bailong on 16/7/5. 6 | // Copyright © 2016年 Qiniu Cloud Storage. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface QNLruCache : NSObject 12 | 13 | - (instancetype)init:(NSUInteger)limit; 14 | 15 | - (void)removeAllObjects; 16 | 17 | - (void)removeObjectForKey:(NSString *)key; 18 | 19 | - (id)objectForKey:(NSString *)key; 20 | 21 | - (void)setObject:(id)obj forKey:(NSString *)key; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /ImageHosting/External/HappyDNS/Common/QNLruCache.m: -------------------------------------------------------------------------------- 1 | // 2 | // QNLruCache.m 3 | // HappyDNS 4 | // 5 | // Created by bailong on 16/7/5. 6 | // Copyright © 2016年 Qiniu Cloud Storage. All rights reserved. 7 | // 8 | 9 | #import "QNLruCache.h" 10 | 11 | @interface QNLruCache () 12 | 13 | @property (nonatomic, readonly) NSUInteger limit; 14 | 15 | @property (nonatomic, readonly) NSMutableDictionary* cache; 16 | 17 | @property (nonatomic, readonly) NSMutableArray* list; 18 | 19 | @end 20 | 21 | @interface _QNElement : NSObject 22 | @property (nonatomic, readonly, strong) NSString* key; 23 | @property (nonatomic, strong) id obj; 24 | - (instancetype)initObject:(id)obj forKey:(NSString*)key; 25 | @end 26 | 27 | @implementation _QNElement 28 | 29 | - (instancetype)initObject:(id)obj forKey:(NSString*)key { 30 | if (self = [super init]) { 31 | _key = key; 32 | _obj = obj; 33 | } 34 | return self; 35 | } 36 | 37 | @end 38 | 39 | @implementation QNLruCache 40 | 41 | - (instancetype)init:(NSUInteger)limit { 42 | if (self = [super init]) { 43 | _limit = limit; 44 | _cache = [NSMutableDictionary new]; 45 | _list = [NSMutableArray new]; 46 | } 47 | return self; 48 | } 49 | 50 | - (void)removeAllObjects { 51 | [_cache removeAllObjects]; 52 | [_list removeAllObjects]; 53 | } 54 | 55 | - (void)removeObjectForKey:(NSString*)key { 56 | _QNElement* obj = [_cache objectForKey:key]; 57 | if (obj == nil) { 58 | return; 59 | } 60 | [_cache removeObjectForKey:key]; 61 | [_list removeObjectIdenticalTo:obj]; 62 | } 63 | 64 | - (id)objectForKey:(NSString*)key { 65 | _QNElement* obj = [_cache objectForKey:key]; 66 | if (obj != nil) { 67 | [_list removeObjectIdenticalTo:obj]; 68 | [_list insertObject:obj atIndex:0]; 69 | } 70 | return obj.obj; 71 | } 72 | 73 | - (void)setObject:(id)obj forKey:(NSString*)key { 74 | _QNElement* old = [_cache objectForKey:key]; 75 | if (old) { 76 | old.obj = obj; 77 | [_list removeObjectIdenticalTo:old]; 78 | [_list insertObject:old atIndex:0]; 79 | return; 80 | } else if (_list.count == _limit) { 81 | old = [_list lastObject]; 82 | [_list removeLastObject]; 83 | [_cache removeObjectForKey:old.key]; 84 | } 85 | _QNElement* newElement = [[_QNElement alloc] initObject:obj forKey:key]; 86 | [_cache setObject:newElement forKey:key]; 87 | [_list insertObject:newElement atIndex:0]; 88 | } 89 | 90 | @end 91 | -------------------------------------------------------------------------------- /ImageHosting/External/HappyDNS/Common/QNNetworkInfo.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNNetworkInfo.h 3 | // HappyDNS 4 | // 5 | // Created by bailong on 15/6/25. 6 | // Copyright (c) 2015年 Qiniu Cloud Storage. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | extern const int kQNNO_NETWORK; 12 | extern const int kQNWIFI; 13 | extern const int kQNMOBILE; 14 | 15 | extern const int kQNISP_GENERAL; 16 | extern const int kQNISP_CTC; 17 | extern const int kQNISP_DIANXIN; 18 | extern const int kQNISP_CNC; 19 | extern const int kQNISP_LIANTONG; 20 | extern const int kQNISP_CMCC; 21 | extern const int kQNISP_YIDONG; 22 | extern const int kQNISP_OTHER; 23 | 24 | @interface QNNetworkInfo : NSObject 25 | 26 | @property (nonatomic, readonly) int networkConnection; 27 | @property (nonatomic, readonly) int provider; 28 | 29 | - (instancetype)init:(int)connecton provider:(int)provider; 30 | 31 | - (BOOL)isEqual:(id)other; 32 | - (BOOL)isEqualToInfo:(QNNetworkInfo *)info; 33 | 34 | + (instancetype)noNet; 35 | 36 | + (instancetype)normal; 37 | 38 | + (BOOL)isNetworkChanged; 39 | 40 | + (NSString *)getIp; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /ImageHosting/External/HappyDNS/Common/QNNetworkInfo.m: -------------------------------------------------------------------------------- 1 | // 2 | // QNNetworkInfo.m 3 | // HappyDNS 4 | // 5 | // Created by bailong on 15/6/25. 6 | // Copyright (c) 2015年 Qiniu Cloud Storage. All rights reserved. 7 | // 8 | 9 | #import 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #import "QNIP.h" 16 | #import "QNNetworkInfo.h" 17 | 18 | const int kQNNO_NETWORK = -1; 19 | const int kQNWIFI = 1; 20 | const int kQNMOBILE = 2; 21 | 22 | const int kQNISP_GENERAL = 0; 23 | const int kQNISP_CTC = 1; 24 | const int kQNISP_DIANXIN = kQNISP_CTC; 25 | const int kQNISP_CNC = 2; 26 | const int kQNISP_LIANTONG = kQNISP_CNC; 27 | const int kQNISP_CMCC = 3; 28 | const int kQNISP_YIDONG = kQNISP_CMCC; 29 | const int kQNISP_OTHER = 999; 30 | 31 | #define IPLength 64 32 | 33 | static char previousIp[IPLength] = {0}; 34 | static NSString *lock = @""; 35 | 36 | @implementation QNNetworkInfo 37 | 38 | - (instancetype)init:(int)connecton provider:(int)provider { 39 | if (self = [super init]) { 40 | _networkConnection = connecton; 41 | _provider = provider; 42 | } 43 | return self; 44 | } 45 | 46 | + (instancetype)noNet { 47 | return [[QNNetworkInfo alloc] init:kQNNO_NETWORK provider:kQNISP_GENERAL]; 48 | } 49 | 50 | + (instancetype)normal { 51 | return [[QNNetworkInfo alloc] init:kQNISP_GENERAL provider:kQNISP_GENERAL]; 52 | } 53 | 54 | - (BOOL)isEqualToInfo:(QNNetworkInfo *)info { 55 | if (self == info) 56 | return YES; 57 | return self.provider == info.provider && self.networkConnection == info.networkConnection; 58 | } 59 | 60 | - (BOOL)isEqual:(id)other { 61 | if (other == self) 62 | return YES; 63 | if (!other || ![other isKindOfClass:[self class]]) 64 | return NO; 65 | return [self isEqualToInfo:other]; 66 | } 67 | 68 | + (BOOL)isNetworkChanged { 69 | @synchronized(lock) { 70 | char local[IPLength] = {0}; 71 | int err = qn_localIp(local, sizeof(local)); 72 | if (err != 0) { 73 | return YES; 74 | } 75 | if (memcmp(previousIp, local, sizeof(local)) != 0) { 76 | memcpy(previousIp, local, sizeof(local)); 77 | return YES; 78 | } 79 | return NO; 80 | } 81 | } 82 | 83 | + (NSString *)getIp { 84 | return [QNIP local]; 85 | } 86 | @end 87 | -------------------------------------------------------------------------------- /ImageHosting/External/HappyDNS/Common/QNRecord.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNRecord.h 3 | // HappyDNS 4 | // 5 | // Created by bailong on 15/6/23. 6 | // Copyright (c) 2015年 Qiniu Cloud Storage. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /** 12 | * A 记录 13 | */ 14 | extern const int kQNTypeA; 15 | 16 | /** 17 | * AAAA 记录 18 | */ 19 | extern const int kQNTypeAAAA; 20 | 21 | /** 22 | * Cname 记录 23 | */ 24 | extern const int kQNTypeCname; 25 | 26 | /** 27 | * Txt 记录 28 | */ 29 | extern const int kQNTypeTXT; 30 | 31 | @interface QNRecord : NSObject 32 | @property (nonatomic, strong, readonly) NSString *value; 33 | @property (nonatomic, readonly) int ttl; 34 | @property (nonatomic, readonly) int type; 35 | @property (nonatomic, readonly) long long timeStamp; 36 | 37 | - (instancetype)init:(NSString *)value 38 | ttl:(int)ttl 39 | type:(int)type; 40 | 41 | - (BOOL)expired:(long long)time; 42 | @end 43 | -------------------------------------------------------------------------------- /ImageHosting/External/HappyDNS/Common/QNRecord.m: -------------------------------------------------------------------------------- 1 | // 2 | // QNRecord.m 3 | // HappyDNS 4 | // 5 | // Created by bailong on 15/6/23. 6 | // Copyright (c) 2015年 Qiniu Cloud Storage. All rights reserved. 7 | // 8 | 9 | #import "QNRecord.h" 10 | 11 | const int kQNTypeA = 1; 12 | const int kQNTypeAAAA = 28; 13 | const int kQNTypeCname = 5; 14 | const int kQNTypeTXT = 16; 15 | 16 | @implementation QNRecord 17 | - (instancetype)init:(NSString *)value 18 | ttl:(int)ttl 19 | type:(int)type { 20 | if (self = [super init]) { 21 | _value = value; 22 | _type = type; 23 | _ttl = ttl; 24 | _timeStamp = [[NSDate date] timeIntervalSince1970]; 25 | } 26 | return self; 27 | } 28 | 29 | - (BOOL)expired:(long long)time { 30 | return time > _timeStamp + _ttl; 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /ImageHosting/External/HappyDNS/Common/QNResolverDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNResolverDelegate.h 3 | // HappyDNS 4 | // 5 | // Created by bailong on 15/6/23. 6 | // Copyright (c) 2015年 Qiniu Cloud Storage. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | extern const int kQNDomainHijackingCode; 12 | extern const int kQNDomainNotOwnCode; 13 | extern const int kQNDomainSeverError; 14 | 15 | #define QN_DNS_DEFAULT_TIMEOUT 20 //seconds 16 | 17 | @class QNDomain; 18 | @class QNNetworkInfo; 19 | @protocol QNResolverDelegate 20 | - (NSArray *)query:(QNDomain *)domain networkInfo:(QNNetworkInfo *)netInfo error:(NSError **)error; 21 | @end 22 | -------------------------------------------------------------------------------- /ImageHosting/External/HappyDNS/HappyDNS.h: -------------------------------------------------------------------------------- 1 | // 2 | // HappyDNS.h 3 | // HappyDNS 4 | // 5 | // Created by bailong on 15/6/24. 6 | // Copyright (c) 2015年 Qiniu Cloud Storage. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "QNDnsManager.h" 12 | #import "QNDnspodEnterprise.h" 13 | #import "QNDnspodFree.h" 14 | #import "QNDomain.h" 15 | #import "QNHijackingDetectWrapper.h" 16 | #import "QNIP.h" 17 | #import "QNNetworkInfo.h" 18 | #import "QNRecord.h" 19 | #import "QNResolver.h" 20 | #import "QNResolverDelegate.h" 21 | 22 | #import "QNGetAddrInfo.h" -------------------------------------------------------------------------------- /ImageHosting/External/HappyDNS/Http/QNDnspodEnterprise.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNDnspodEnterprise.h 3 | // HappyDNS 4 | // 5 | // Created by bailong on 15/7/31. 6 | // Copyright (c) 2015年 Qiniu Cloud Storage. All rights reserved. 7 | // 8 | 9 | #import "QNResolverDelegate.h" 10 | #import 11 | 12 | extern const int kQN_ENCRYPT_FAILED; 13 | extern const int kQN_DECRYPT_FAILED; 14 | 15 | @interface QNDnspodEnterprise : NSObject 16 | 17 | - (instancetype)initWithId:(NSString *)userId 18 | key:(NSString *)key; 19 | 20 | - (instancetype)initWithId:(NSString *)userId 21 | key:(NSString *)key 22 | server:(NSString *)server; 23 | 24 | - (instancetype)initWithId:(NSString *)userId 25 | key:(NSString *)key 26 | server:(NSString *)server 27 | timeout:(NSUInteger)time; 28 | 29 | - (NSArray *)query:(QNDomain *)domain networkInfo:(QNNetworkInfo *)netInfo error:(NSError *__autoreleasing *)error; 30 | @end 31 | -------------------------------------------------------------------------------- /ImageHosting/External/HappyDNS/Http/QNDnspodEnterprise.m: -------------------------------------------------------------------------------- 1 | // 2 | // QNDnspodFree.m 3 | // HappyDNS 4 | // 5 | // Created by bailong on 15/6/23. 6 | // Copyright (c) 2015年 Qiniu Cloud Storage. All rights reserved. 7 | // 8 | 9 | #import "QNDnspodEnterprise.h" 10 | #import 11 | 12 | #import "QNDes.h" 13 | #import "QNDomain.h" 14 | #import "QNHex.h" 15 | #import "QNIP.h" 16 | #import "QNRecord.h" 17 | 18 | const int kQN_ENCRYPT_FAILED = -10001; 19 | const int kQN_DECRYPT_FAILED = -10002; 20 | 21 | @interface QNDnspodEnterprise () 22 | @property (readonly, strong) NSString *server; 23 | @property (nonatomic, strong) NSString *userId; 24 | @property (nonatomic, strong) QNDes *des; 25 | @property (nonatomic) NSUInteger timeout; 26 | 27 | @end 28 | 29 | @implementation QNDnspodEnterprise 30 | 31 | - (instancetype)initWithId:(NSString *)userId 32 | key:(NSString *)key { 33 | return [self initWithId:userId key:key server:@"119.29.29.29"]; 34 | } 35 | 36 | - (instancetype)initWithId:(NSString *)userId 37 | key:(NSString *)key 38 | server:(NSString *)server { 39 | return [self initWithId:userId key:key server:@"119.29.29.29" timeout:QN_DNS_DEFAULT_TIMEOUT]; 40 | } 41 | 42 | - (instancetype)initWithId:(NSString *)userId 43 | key:(NSString *)key 44 | server:(NSString *)server 45 | timeout:(NSUInteger)time { 46 | if (self = [super init]) { 47 | _server = server; 48 | _userId = userId; 49 | _des = [[QNDes alloc] init:[key dataUsingEncoding:NSUTF8StringEncoding]]; 50 | _timeout = time; 51 | } 52 | return self; 53 | } 54 | 55 | - (NSString *)encrypt:(NSString *)domain { 56 | NSData *data = [_des encrypt:[domain dataUsingEncoding:NSUTF8StringEncoding]]; 57 | if (data == nil) { 58 | return nil; 59 | } 60 | NSString *str = [QNHex encodeHexData:data]; 61 | return str; 62 | } 63 | 64 | - (NSString *)decrypt:(NSData *)raw { 65 | NSData *enc = [QNHex decodeHexString:[[NSString alloc] initWithData:raw 66 | encoding:NSUTF8StringEncoding]]; 67 | if (enc == nil) { 68 | return nil; 69 | } 70 | NSData *data = [_des decrpyt:enc]; 71 | if (data == nil) { 72 | return nil; 73 | } 74 | return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 75 | } 76 | 77 | - (NSArray *)query:(QNDomain *)domain networkInfo:(QNNetworkInfo *)netInfo error:(NSError *__autoreleasing *)error { 78 | NSString *encrypt = [self encrypt:domain.domain]; 79 | if (encrypt == nil) { 80 | if (error != nil) { 81 | *error = [[NSError alloc] initWithDomain:domain.domain code:kQN_ENCRYPT_FAILED userInfo:nil]; 82 | } 83 | return nil; 84 | } 85 | NSString *url = [NSString stringWithFormat:@"http://%@/d?ttl=1&dn=%@&id=%@", [QNIP ipHost:_server], encrypt, _userId]; 86 | NSURLRequest *urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:_timeout]; 87 | NSHTTPURLResponse *response = nil; 88 | NSError *httpError = nil; 89 | NSData *data = [NSURLConnection sendSynchronousRequest:urlRequest 90 | returningResponse:&response 91 | error:&httpError]; 92 | 93 | if (httpError != nil) { 94 | if (error != nil) { 95 | *error = httpError; 96 | } 97 | return nil; 98 | } 99 | if (response.statusCode != 200) { 100 | return nil; 101 | } 102 | 103 | NSString *raw = [self decrypt:data]; 104 | if (raw == nil) { 105 | if (error != nil) { 106 | *error = [[NSError alloc] initWithDomain:domain.domain code:kQN_DECRYPT_FAILED userInfo:nil]; 107 | } 108 | return nil; 109 | } 110 | NSArray *ip1 = [raw componentsSeparatedByString:@","]; 111 | if (ip1.count != 2) { 112 | return nil; 113 | } 114 | NSString *ttlStr = [ip1 objectAtIndex:1]; 115 | int ttl = [ttlStr intValue]; 116 | if (ttl <= 0) { 117 | return nil; 118 | } 119 | NSString *ips = [ip1 objectAtIndex:0]; 120 | NSArray *ipArray = [ips componentsSeparatedByString:@";"]; 121 | NSMutableArray *ret = [[NSMutableArray alloc] initWithCapacity:ipArray.count]; 122 | for (int i = 0; i < ipArray.count; i++) { 123 | QNRecord *record = [[QNRecord alloc] init:[ipArray objectAtIndex:i] ttl:ttl type:kQNTypeA]; 124 | [ret addObject:record]; 125 | } 126 | return ret; 127 | } 128 | 129 | @end 130 | -------------------------------------------------------------------------------- /ImageHosting/External/HappyDNS/Http/QNDnspodFree.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNDnspodFree.h 3 | // HappyDNS 4 | // 5 | // Created by bailong on 15/6/23. 6 | // Copyright (c) 2015年 Qiniu Cloud Storage. All rights reserved. 7 | // 8 | 9 | #import "QNResolverDelegate.h" 10 | #import 11 | 12 | @interface QNDnspodFree : NSObject 13 | - (NSArray *)query:(QNDomain *)domain networkInfo:(QNNetworkInfo *)netInfo error:(NSError *__autoreleasing *)error; 14 | 15 | - (instancetype)init; 16 | - (instancetype)initWithServer:(NSString *)server; 17 | - (instancetype)initWithServer:(NSString *)server 18 | timeout:(NSUInteger)time; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /ImageHosting/External/HappyDNS/Http/QNDnspodFree.m: -------------------------------------------------------------------------------- 1 | // 2 | // QNDnspodFree.m 3 | // HappyDNS 4 | // 5 | // Created by bailong on 15/6/23. 6 | // Copyright (c) 2015年 Qiniu Cloud Storage. All rights reserved. 7 | // 8 | 9 | #import "QNDnspodFree.h" 10 | #import "QNDomain.h" 11 | #import "QNIP.h" 12 | #import "QNRecord.h" 13 | 14 | @interface QNDnspodFree () 15 | @property (readonly, nonatomic, strong) NSString *server; 16 | @property (readonly, nonatomic) NSUInteger timeout; 17 | @end 18 | 19 | @implementation QNDnspodFree 20 | 21 | - (instancetype)init { 22 | return [self initWithServer:@"119.29.29.29"]; 23 | } 24 | - (instancetype)initWithServer:(NSString *)server { 25 | return [self initWithServer:@"119.29.29.29" timeout:QN_DNS_DEFAULT_TIMEOUT]; 26 | } 27 | 28 | - (instancetype)initWithServer:(NSString *)server 29 | timeout:(NSUInteger)time { 30 | if (self = [super init]) { 31 | _server = server; 32 | _timeout = time; 33 | } 34 | return self; 35 | } 36 | 37 | - (NSArray *)query:(QNDomain *)domain networkInfo:(QNNetworkInfo *)netInfo error:(NSError *__autoreleasing *)error { 38 | NSString *url = [NSString stringWithFormat:@"http://%@/d?ttl=1&dn=%@", [QNIP ipHost:_server], domain.domain]; 39 | NSURLRequest *urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:_timeout]; 40 | NSHTTPURLResponse *response = nil; 41 | NSError *httpError = nil; 42 | NSData *data = [NSURLConnection sendSynchronousRequest:urlRequest 43 | returningResponse:&response 44 | error:&httpError]; 45 | 46 | if (httpError != nil) { 47 | if (error != nil) { 48 | *error = httpError; 49 | } 50 | return nil; 51 | } 52 | if (response.statusCode != 200) { 53 | return nil; 54 | } 55 | NSString *raw = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 56 | NSArray *ip1 = [raw componentsSeparatedByString:@","]; 57 | if (ip1.count != 2) { 58 | return nil; 59 | } 60 | NSString *ttlStr = [ip1 objectAtIndex:1]; 61 | int ttl = [ttlStr intValue]; 62 | if (ttl <= 0) { 63 | return nil; 64 | } 65 | NSString *ips = [ip1 objectAtIndex:0]; 66 | NSArray *ipArray = [ips componentsSeparatedByString:@";"]; 67 | NSMutableArray *ret = [[NSMutableArray alloc] initWithCapacity:ipArray.count]; 68 | for (int i = 0; i < ipArray.count; i++) { 69 | QNRecord *record = [[QNRecord alloc] init:[ipArray objectAtIndex:i] ttl:ttl type:kQNTypeA]; 70 | [ret addObject:record]; 71 | } 72 | return ret; 73 | } 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /ImageHosting/External/HappyDNS/Local/QNHijackingDetectWrapper.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNHijackingDetectWrapper.h 3 | // HappyDNS 4 | // 5 | // Created by bailong on 15/7/16. 6 | // Copyright (c) 2015年 Qiniu Cloud Storage. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "QNResolverDelegate.h" 12 | 13 | @class QNResolver; 14 | @interface QNHijackingDetectWrapper : NSObject 15 | - (NSArray *)query:(QNDomain *)domain networkInfo:(QNNetworkInfo *)netInfo error:(NSError *__autoreleasing *)error; 16 | - (instancetype)initWithResolver:(QNResolver *)resolver; 17 | @end 18 | -------------------------------------------------------------------------------- /ImageHosting/External/HappyDNS/Local/QNHijackingDetectWrapper.m: -------------------------------------------------------------------------------- 1 | // 2 | // QNHijackingDetectWrapper.m 3 | // HappyDNS 4 | // 5 | // Created by bailong on 15/7/16. 6 | // Copyright (c) 2015年 Qiniu Cloud Storage. All rights reserved. 7 | // 8 | 9 | #import "QNHijackingDetectWrapper.h" 10 | #import "QNDomain.h" 11 | #import "QNRecord.h" 12 | #import "QNResolver.h" 13 | 14 | @interface QNHijackingDetectWrapper () 15 | @property (nonatomic, readonly) QNResolver *resolver; 16 | @end 17 | 18 | @implementation QNHijackingDetectWrapper 19 | 20 | - (NSArray *)query:(QNDomain *)domain networkInfo:(QNNetworkInfo *)netInfo error:(NSError *__autoreleasing *)error { 21 | NSArray *result = [_resolver query:domain networkInfo:netInfo error:error]; 22 | if (((!domain.hasCname) && domain.maxTtl == 0) || result == nil || result.count == 0) { 23 | return result; 24 | } 25 | BOOL hasCname = NO; 26 | BOOL outOfTtl = NO; 27 | for (int i = 0; i < result.count; i++) { 28 | QNRecord *record = [result objectAtIndex:i]; 29 | if (record.type == kQNTypeCname) { 30 | hasCname = YES; 31 | } 32 | if (domain.maxTtl > 0 && record.type == kQNTypeA && record.ttl > domain.maxTtl) { 33 | outOfTtl = YES; 34 | } 35 | } 36 | if ((domain.hasCname && !hasCname) || outOfTtl) { 37 | if (error != nil) { 38 | *error = [[NSError alloc] initWithDomain:domain.domain code:kQNDomainHijackingCode userInfo:nil]; 39 | } 40 | return nil; 41 | } 42 | return result; 43 | } 44 | - (instancetype)initWithResolver:(QNResolver *)resolver { 45 | if (self = [super init]) { 46 | _resolver = resolver; 47 | } 48 | return self; 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /ImageHosting/External/HappyDNS/Local/QNHosts.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNHosts.h 3 | // HappyDNS 4 | // 5 | // Created by bailong on 15/6/23. 6 | // Copyright (c) 2015年 Qiniu Cloud Storage. All rights reserved. 7 | // 8 | 9 | #import "QNResolverDelegate.h" 10 | #import 11 | 12 | @interface QNHosts : NSObject 13 | 14 | - (NSArray *)query:(QNDomain *)domain networkInfo:(QNNetworkInfo *)netInfo; 15 | - (void)put:(NSString *)domain ip:(NSString *)ip; 16 | - (void)put:(NSString *)domain ip:(NSString *)ip provider:(int)provider; 17 | - (instancetype)init; 18 | @end 19 | -------------------------------------------------------------------------------- /ImageHosting/External/HappyDNS/Local/QNHosts.m: -------------------------------------------------------------------------------- 1 | // 2 | // QNHosts.m 3 | // HappyDNS 4 | // 5 | // Created by bailong on 15/6/23. 6 | // Copyright (c) 2015年 Qiniu Cloud Storage. All rights reserved. 7 | // 8 | 9 | #import "QNHosts.h" 10 | #import "QNDomain.h" 11 | //#import "QNIP.h" 12 | #import "QNNetworkInfo.h" 13 | 14 | @interface QNHosts () 15 | @property (nonatomic) NSMutableDictionary *dict; 16 | @end 17 | 18 | @interface QNHostsValue : NSObject 19 | @property (nonatomic, copy, readonly) NSString *ip; 20 | @property (readonly) int provider; 21 | @end 22 | 23 | @implementation QNHostsValue 24 | 25 | - (instancetype)init:(NSString *)ip provider:(int)provider { 26 | if (self = [super init]) { 27 | _ip = ip; 28 | _provider = provider; 29 | } 30 | return self; 31 | } 32 | 33 | @end 34 | 35 | static NSArray *filter(NSArray *input, int provider) { 36 | NSMutableArray *normal = [[NSMutableArray alloc] initWithCapacity:input.count]; 37 | NSMutableArray *special = [[NSMutableArray alloc] init]; 38 | for (QNHostsValue *v in input) { 39 | NSString *ip = v.ip; 40 | if (v.provider == kQNISP_GENERAL) { 41 | [normal addObject:ip]; 42 | } 43 | if (provider == v.provider && provider != kQNISP_GENERAL) { 44 | [special addObject:ip]; 45 | } 46 | } 47 | if (special.count != 0) { 48 | return special; 49 | } 50 | return normal; 51 | } 52 | 53 | @implementation QNHosts 54 | - (NSArray *)query:(QNDomain *)domain networkInfo:(QNNetworkInfo *)netInfo { 55 | NSMutableArray *x; 56 | @synchronized(_dict) { 57 | x = [_dict objectForKey:domain.domain]; 58 | } 59 | 60 | if (x == nil || x.count == 0) { 61 | return nil; 62 | } 63 | if (x.count >= 2) { 64 | QNHostsValue *first = [x firstObject]; 65 | [x removeObjectAtIndex:0]; 66 | [x addObject:first]; 67 | } 68 | return filter(x, netInfo.provider); 69 | } 70 | 71 | - (void)put:(NSString *)domain ip:(NSString *)ip { 72 | [self put:domain ip:ip provider:kQNISP_GENERAL]; 73 | } 74 | 75 | - (void)put:(NSString *)domain ip:(NSString *)ip provider:(int)provider { 76 | QNHostsValue *v = [[QNHostsValue alloc] init:ip provider:provider]; 77 | @synchronized(_dict) { 78 | NSMutableArray *x = [_dict objectForKey:domain]; 79 | if (x == nil) { 80 | x = [[NSMutableArray alloc] init]; 81 | } 82 | [x addObject:v]; 83 | [_dict setObject:x forKey:domain]; 84 | } 85 | } 86 | 87 | - (instancetype)init { 88 | if (self = [super init]) { 89 | _dict = [[NSMutableDictionary alloc] init]; 90 | } 91 | return self; 92 | } 93 | 94 | @end 95 | -------------------------------------------------------------------------------- /ImageHosting/External/HappyDNS/Local/QNResolvUtil.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNResolv.h 3 | // HappyDNS 4 | // 5 | // Created by bailong on 16/5/28. 6 | // Copyright © 2016年 Qiniu Cloud Storage. All rights reserved. 7 | // 8 | 9 | #ifndef QNResolv_h 10 | #define QNResolv_h 11 | 12 | extern BOOL isV6(NSString *address); 13 | 14 | extern int setup_dns_server(void *res, NSString *dns_server, NSUInteger timeout); 15 | 16 | #endif /* QNResolv_h */ 17 | -------------------------------------------------------------------------------- /ImageHosting/External/HappyDNS/Local/QNResolvUtil.m: -------------------------------------------------------------------------------- 1 | // 2 | // QNResolvUtil.m 3 | // HappyDNS 4 | // 5 | // Created by bailong on 16/5/28. 6 | // Copyright © 2016年 Qiniu Cloud Storage. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #import "QNIP.h" 22 | 23 | #if __IPHONE_OS_VERSION_MIN_REQUIRED 24 | #import 25 | #import 26 | #endif 27 | 28 | BOOL isV6(NSString *address) { 29 | return strchr(address.UTF8String, ':') != NULL; 30 | } 31 | 32 | int setup_dns_server(void *_res_state, NSString *dns_server, NSUInteger timeout) { 33 | res_state res = (res_state)_res_state; 34 | int r = res_ninit(res); 35 | if (r != 0) { 36 | return r; 37 | } 38 | res->retrans = (int)timeout; 39 | res->retry = 1; 40 | if (dns_server == nil) { 41 | return 0; 42 | } 43 | res->options |= RES_IGNTC; 44 | 45 | union res_sockaddr_union server = {0}; 46 | 47 | struct addrinfo hints = {0}, *ai = NULL; 48 | hints.ai_family = AF_UNSPEC; 49 | hints.ai_socktype = SOCK_STREAM; 50 | int ret = getaddrinfo(dns_server.UTF8String, "53", &hints, &ai); 51 | if (ret != 0) { 52 | return ret; 53 | } 54 | int family = ai->ai_family; 55 | 56 | if (family == AF_INET6) { 57 | ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = htons(53); 58 | server.sin6 = *((struct sockaddr_in6 *)ai->ai_addr); 59 | } else { 60 | server.sin = *((struct sockaddr_in *)ai->ai_addr); 61 | } 62 | 63 | if (![QNIP isIpV6FullySupported] && family == AF_INET) { 64 | if ([QNIP isV6]) { 65 | freeaddrinfo(ai); 66 | ai = NULL; 67 | bzero(&hints, 0); 68 | hints.ai_family = AF_UNSPEC; 69 | hints.ai_socktype = SOCK_STREAM; 70 | char buf[64] = {0}; 71 | qn_nat64(buf, sizeof(buf), (uint32_t)server.sin.sin_addr.s_addr); 72 | int ret = getaddrinfo(buf, "53", &hints, &ai); 73 | if (ret != 0) { 74 | return -1; 75 | } 76 | ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = htons(53); 77 | server.sin6 = *((struct sockaddr_in6 *)ai->ai_addr); 78 | } 79 | } 80 | 81 | freeaddrinfo(ai); 82 | res_setservers(res, &server, 1); 83 | return 0; 84 | } -------------------------------------------------------------------------------- /ImageHosting/External/HappyDNS/Local/QNResolver.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNResolver.h 3 | // HappyDNS 4 | // 5 | // Created by bailong on 15/6/23. 6 | // Copyright (c) 2015年 Qiniu Cloud Storage. All rights reserved. 7 | // 8 | 9 | #import "QNResolverDelegate.h" 10 | #import 11 | 12 | @interface QNResolver : NSObject 13 | - (NSArray *)query:(QNDomain *)domain networkInfo:(QNNetworkInfo *)netInfo error:(NSError *__autoreleasing *)error; 14 | 15 | // @deprecated typo 16 | - (instancetype)initWithAddres:(NSString *)address DEPRECATED_ATTRIBUTE; 17 | 18 | - (instancetype)initWithAddress:(NSString *)address; 19 | 20 | - (instancetype)initWithAddress:(NSString *)address 21 | timeout:(NSUInteger)time; 22 | 23 | + (instancetype)systemResolver; 24 | + (NSString *)systemDnsServer; 25 | @end 26 | -------------------------------------------------------------------------------- /ImageHosting/External/HappyDNS/Local/QNTxtResolver.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNTxtResolver.h 3 | // HappyDNS 4 | // 5 | // Created by bailong on 16/1/5. 6 | // Copyright © 2016年 Qiniu Cloud Storage. All rights reserved. 7 | // 8 | 9 | #import "QNResolverDelegate.h" 10 | #import 11 | 12 | @interface QNTxtResolver : NSObject 13 | - (NSArray *)query:(QNDomain *)domain networkInfo:(QNNetworkInfo *)netInfo error:(NSError *__autoreleasing *)error; 14 | 15 | /** 16 | * 根据服务器地址进行初始化 17 | * 18 | * @param address DNS 服务器地址,nil 表示系统的 19 | */ 20 | - (instancetype)initWithAddress:(NSString *)address; 21 | 22 | - (instancetype)initWithAddress:(NSString *)address timeout:(NSUInteger)time; 23 | @end 24 | -------------------------------------------------------------------------------- /ImageHosting/External/HappyDNS/Local/QNTxtResolver.m: -------------------------------------------------------------------------------- 1 | // 2 | // QNTxtResolver.m 3 | // HappyDNS 4 | // 5 | // Created by bailong on 16/1/5. 6 | // Copyright © 2016年 Qiniu Cloud Storage. All rights reserved. 7 | // 8 | 9 | #import "QNTxtResolver.h" 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #import "QNDomain.h" 22 | #import "QNRecord.h" 23 | #import "QNResolvUtil.h" 24 | #import "QNResolver.h" 25 | 26 | @interface QNTxtResolver () 27 | @property (nonatomic, readonly, strong) NSString *address; 28 | @property (nonatomic, readonly) NSUInteger timeout; 29 | @end 30 | 31 | static NSArray *query_ip(res_state res, const char *host) { 32 | u_char answer[1500]; 33 | int len = res_nquery(res, host, ns_c_in, ns_t_txt, answer, sizeof(answer)); 34 | 35 | ns_msg handle; 36 | ns_initparse(answer, len, &handle); 37 | 38 | int count = ns_msg_count(handle, ns_s_an); 39 | if (count != 1) { 40 | res_ndestroy(res); 41 | return nil; 42 | } 43 | 44 | char txtbuf[256]; 45 | memset(txtbuf, 0, sizeof(txtbuf)); 46 | 47 | ns_rr rr; 48 | if (ns_parserr(&handle, ns_s_an, 0, &rr) != 0) { 49 | res_ndestroy(res); 50 | return nil; 51 | } 52 | int t = ns_rr_type(rr); 53 | int ttl = ns_rr_ttl(rr); 54 | int rdlen = ns_rr_rdlen(rr); 55 | if (rdlen <= 1 + 7) { 56 | res_ndestroy(res); 57 | return nil; 58 | } 59 | NSString *val; 60 | if (t == ns_t_txt) { 61 | memcpy(txtbuf, ns_rr_rdata(rr) + 1, rdlen - 1); 62 | val = [NSString stringWithUTF8String:txtbuf]; 63 | } else { 64 | res_ndestroy(res); 65 | return nil; 66 | } 67 | NSArray *ipArray = [val componentsSeparatedByString:@","]; 68 | NSMutableArray *ret = [[NSMutableArray alloc] initWithCapacity:ipArray.count]; 69 | for (int i = 0; i < ipArray.count; i++) { 70 | QNRecord *record = [[QNRecord alloc] init:[ipArray objectAtIndex:i] ttl:ttl type:kQNTypeA]; 71 | [ret addObject:record]; 72 | } 73 | 74 | res_ndestroy(res); 75 | return ret; 76 | } 77 | 78 | @implementation QNTxtResolver 79 | - (instancetype)initWithAddress:(NSString *)address { 80 | return [self initWithAddress:address timeout:QN_DNS_DEFAULT_TIMEOUT]; 81 | } 82 | 83 | - (instancetype)initWithAddress:(NSString *)address timeout:(NSUInteger)time { 84 | if (self = [super init]) { 85 | _address = address; 86 | _timeout = time; 87 | } 88 | return self; 89 | } 90 | 91 | - (NSArray *)query:(QNDomain *)domain networkInfo:(QNNetworkInfo *)netInfo error:(NSError *__autoreleasing *)error { 92 | struct __res_state res; 93 | 94 | int r = setup_dns_server(&res, _address, _timeout); 95 | if (r != 0) { 96 | if (error != nil) { 97 | *error = [[NSError alloc] initWithDomain:@"qiniu.dns" code:kQNDomainSeverError userInfo:nil]; 98 | } 99 | return nil; 100 | } 101 | 102 | NSArray *ret = query_ip(&res, [domain.domain cStringUsingEncoding:NSUTF8StringEncoding]); 103 | if (ret == nil && error != nil) { 104 | *error = [[NSError alloc] initWithDomain:@"qiniu.dns" code:NSURLErrorDNSLookupFailed userInfo:nil]; 105 | } 106 | return ret; 107 | } 108 | 109 | @end 110 | -------------------------------------------------------------------------------- /ImageHosting/External/HappyDNS/Util/QNDes.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNDes.h 3 | // HappyDNS 4 | // 5 | // Created by bailong on 15/8/1. 6 | // Copyright (c) 2015年 Qiniu Cloud Storage. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | extern const int kQN_ENCRYPT_FAILED; 12 | extern const int kQN_DECRYPT_FAILED; 13 | 14 | @interface QNDes : NSObject 15 | 16 | - (NSData *)encrypt:(NSData *)input; 17 | 18 | - (NSData *)decrpyt:(NSData *)input; 19 | 20 | - (instancetype)init:(NSData *)key; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /ImageHosting/External/HappyDNS/Util/QNDes.m: -------------------------------------------------------------------------------- 1 | // 2 | // QNDes.m 3 | // HappyDNS 4 | // 5 | // Created by bailong on 15/8/1. 6 | // Copyright (c) 2015年 Qiniu Cloud Storage. All rights reserved. 7 | // 8 | 9 | #import "QNDes.h" 10 | 11 | #import 12 | 13 | @interface QNDes () 14 | @property (nonatomic, strong) NSData *key; 15 | @end 16 | 17 | @implementation QNDes 18 | 19 | - (NSData *)encrypt:(NSData *)data { 20 | const void *input = data.bytes; 21 | size_t inputSize = data.length; 22 | 23 | size_t bufferSize = (inputSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1); 24 | uint8_t *buffer = malloc(bufferSize * sizeof(uint8_t)); 25 | memset((void *)buffer, 0x0, bufferSize); 26 | size_t movedBytes = 0; 27 | 28 | const void *vkey = _key.bytes; 29 | 30 | CCCryptorStatus ccStatus = CCCrypt(kCCEncrypt, 31 | kCCAlgorithmDES, 32 | kCCOptionECBMode | kCCOptionPKCS7Padding, 33 | vkey, 34 | kCCKeySizeDES, 35 | NULL, 36 | input, 37 | inputSize, 38 | (void *)buffer, 39 | bufferSize, 40 | &movedBytes); 41 | if (ccStatus != kCCSuccess) { 42 | NSLog(@"error code %d", ccStatus); 43 | free(buffer); 44 | return nil; 45 | } 46 | NSData *encrypted = [NSData dataWithBytes:(const void *)buffer length:(NSUInteger)movedBytes]; 47 | free(buffer); 48 | return encrypted; 49 | } 50 | 51 | - (NSData *)decrpyt:(NSData *)raw { 52 | const void *input = raw.bytes; 53 | size_t inputSize = raw.length; 54 | 55 | size_t bufferSize = 1024; 56 | uint8_t *buffer = malloc(bufferSize * sizeof(uint8_t)); 57 | memset((void *)buffer, 0x0, bufferSize); 58 | size_t movedBytes = 0; 59 | 60 | const void *vkey = _key.bytes; 61 | 62 | CCCryptorStatus ccStatus = CCCrypt(kCCDecrypt, 63 | kCCAlgorithmDES, 64 | kCCOptionECBMode | kCCOptionPKCS7Padding, 65 | vkey, 66 | kCCKeySizeDES, 67 | NULL, 68 | input, 69 | inputSize, 70 | (void *)buffer, 71 | bufferSize, 72 | &movedBytes); 73 | 74 | if (ccStatus != kCCSuccess) { 75 | NSLog(@"error code %d", ccStatus); 76 | free(buffer); 77 | return nil; 78 | } 79 | 80 | NSData *decrypted = [NSData dataWithBytes:(const void *)buffer length:(NSUInteger)movedBytes]; 81 | free(buffer); 82 | return decrypted; 83 | } 84 | 85 | - (instancetype)init:(NSData *)key { 86 | if (self = [super init]) { 87 | _key = key; 88 | } 89 | return self; 90 | } 91 | 92 | @end 93 | -------------------------------------------------------------------------------- /ImageHosting/External/HappyDNS/Util/QNGetAddrInfo.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNGetAddrInfo.h 3 | // HappyDNS 4 | // 5 | // Created by bailong on 16/7/19. 6 | // Copyright © 2016年 Qiniu Cloud Storage. All rights reserved. 7 | // 8 | 9 | #ifndef QNGetAddrInfo_h 10 | #define QNGetAddrInfo_h 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | typedef struct qn_ips_ret { 17 | char *ips[1]; 18 | } qn_ips_ret; 19 | 20 | typedef qn_ips_ret *(*qn_dns_callback)(const char *host); 21 | 22 | extern void qn_free_ips_ret(qn_ips_ret *ip_list); 23 | 24 | extern int qn_getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res); 25 | 26 | extern void qn_freeaddrinfo(struct addrinfo *ai); 27 | 28 | extern void qn_set_dns_callback(qn_dns_callback cb); 29 | 30 | #ifdef __cplusplus 31 | }; 32 | #endif 33 | 34 | #endif /* QNGetAddrInfo_h */ 35 | -------------------------------------------------------------------------------- /ImageHosting/External/HappyDNS/Util/QNGetAddrInfo.m: -------------------------------------------------------------------------------- 1 | // 2 | // QNGetAddrInfo.c 3 | // HappyDNS 4 | // 5 | // Created by bailong on 16/7/19. 6 | // Copyright © 2016年 Qiniu Cloud Storage. All rights reserved. 7 | // 8 | 9 | #include "string.h" 10 | #include "netdb.h" 11 | #include "stdlib.h" 12 | 13 | #include "QNGetAddrInfo.h" 14 | 15 | //fast judge domain or ip, not verify ip right. 16 | static int isIp(const char* domain) { 17 | size_t l = strlen(domain); 18 | if (l > 15 || l < 7) { 19 | return 0; 20 | } 21 | 22 | for (const char* p = domain; p < domain + l; p++) { 23 | if ((*p < '0' || *p > '9') && *p != '.') { 24 | return 0; 25 | } 26 | } 27 | return 1; 28 | } 29 | 30 | static struct addrinfo* addrinfo_clone(struct addrinfo* addr) { 31 | struct addrinfo* ai; 32 | ai = calloc(sizeof(struct addrinfo) + addr->ai_addrlen, 1); 33 | if (ai) { 34 | memcpy(ai, addr, sizeof(struct addrinfo)); 35 | ai->ai_addr = (void*)(ai + 1); 36 | memcpy(ai->ai_addr, addr->ai_addr, addr->ai_addrlen); 37 | if (addr->ai_canonname) { 38 | ai->ai_canonname = strdup(addr->ai_canonname); 39 | } 40 | ai->ai_next = NULL; 41 | } 42 | return ai; 43 | } 44 | 45 | static void append_addrinfo(struct addrinfo** head, struct addrinfo* addr) { 46 | if (*head == NULL) { 47 | *head = addr; 48 | return; 49 | } 50 | struct addrinfo* ai = *head; 51 | while (ai->ai_next != NULL) { 52 | ai = ai->ai_next; 53 | } 54 | ai->ai_next = addr; 55 | } 56 | 57 | void qn_free_ips_ret(qn_ips_ret* ip_list) { 58 | if (ip_list == NULL) { 59 | return; 60 | } 61 | char** p = ip_list->ips; 62 | while (*p != NULL) { 63 | free(*p); 64 | p++; 65 | } 66 | free(ip_list); 67 | } 68 | 69 | static qn_dns_callback dns_callback = NULL; 70 | int qn_getaddrinfo(const char* hostname, const char* servname, const struct addrinfo* hints, struct addrinfo** res) { 71 | if (dns_callback == NULL || hostname == NULL || isIp(hostname)) { 72 | return getaddrinfo(hostname, servname, hints, res); 73 | } 74 | 75 | qn_ips_ret* ret = dns_callback(hostname); 76 | if (ret == NULL) { 77 | return EAI_NODATA; 78 | } 79 | if (ret->ips[0] == NULL) { 80 | qn_free_ips_ret(ret); 81 | return EAI_NODATA; 82 | } 83 | int i; 84 | struct addrinfo* ai = NULL; 85 | struct addrinfo* store = NULL; 86 | int r = 0; 87 | for (i = 0; ret->ips[i] != NULL; i++) { 88 | r = getaddrinfo(ret->ips[i], servname, hints, &ai); 89 | if (r != 0) { 90 | break; 91 | } 92 | struct addrinfo* temp = ai; 93 | ai = addrinfo_clone(ai); 94 | append_addrinfo(&store, ai); 95 | freeaddrinfo(temp); 96 | ai = NULL; 97 | } 98 | qn_free_ips_ret(ret); 99 | if (r != 0) { 100 | qn_freeaddrinfo(store); 101 | return r; 102 | } 103 | *res = store; 104 | return 0; 105 | } 106 | 107 | void qn_freeaddrinfo(struct addrinfo* ai) { 108 | if (ai == NULL) { 109 | return; 110 | } 111 | struct addrinfo* next; 112 | do { 113 | next = ai->ai_next; 114 | if (ai->ai_canonname) 115 | free(ai->ai_canonname); 116 | /* no need to free(ai->ai_addr) */ 117 | free(ai); 118 | ai = next; 119 | } while (ai); 120 | } 121 | 122 | void qn_set_dns_callback(qn_dns_callback cb) { 123 | dns_callback = cb; 124 | } -------------------------------------------------------------------------------- /ImageHosting/External/HappyDNS/Util/QNHex.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNHex.h 3 | // HappyDNS 4 | // 5 | // Created by bailong on 15/7/31. 6 | // Copyright (c) 2015年 Qiniu Cloud Storage. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | char *qn_encodeHexData(char *output_buf, const char *data, int data_size, BOOL up); 12 | 13 | @interface QNHex : NSObject 14 | 15 | + (NSString *)encodeHexData:(NSData *)data; 16 | + (NSString *)encodeHexString:(NSString *)str; 17 | 18 | + (NSData *)decodeHexString:(NSString *)hex; 19 | + (NSString *)decodeHexToString:(NSString *)hex; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /ImageHosting/External/HappyDNS/Util/QNHex.m: -------------------------------------------------------------------------------- 1 | // 2 | // QNHex.m 3 | // HappyDNS 4 | // 5 | // Created by bailong on 15/7/31. 6 | // Copyright (c) 2015年 Qiniu Cloud Storage. All rights reserved. 7 | // 8 | 9 | #import "QNHex.h" 10 | 11 | static char DIGITS_LOWER[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; 12 | 13 | static char DIGITS_UPPER[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; 14 | 15 | static int hexDigit(char c) { 16 | int result = -1; 17 | if ('0' <= c && c <= '9') { 18 | result = c - '0'; 19 | } else if ('a' <= c && c <= 'f') { 20 | result = 10 + (c - 'a'); 21 | } else if ('A' <= c && c <= 'F') { 22 | result = 10 + (c - 'A'); 23 | } 24 | return result; 25 | } 26 | 27 | static char *decodeHex(const char *data, int size) { 28 | if ((size & 0x01) != 0) { 29 | return NULL; 30 | } 31 | char *output = malloc(size / 2); 32 | int outLimit = 0; 33 | for (int i = 0, j = 0; j < size; i++) { 34 | int f = hexDigit(data[j]); 35 | if (f < 0) { 36 | outLimit = 1; 37 | break; 38 | } 39 | j++; 40 | int f2 = hexDigit(data[j]); 41 | if (f2 < 0) { 42 | outLimit = 1; 43 | break; 44 | } 45 | f = (f << 4) | f2; 46 | j++; 47 | output[i] = (char)(f & 0xff); 48 | } 49 | if (outLimit) { 50 | free(output); 51 | return NULL; 52 | } 53 | return output; 54 | } 55 | 56 | static char *encodeHexInternal(char *output_buf, const char *data, int size, char hexTable[]) { 57 | for (int i = 0, j = 0; i < size; i++) { 58 | output_buf[j++] = hexTable[((0XF0 & data[i]) >> 4) & 0X0F]; 59 | output_buf[j++] = hexTable[((0X0F & data[i])) & 0X0F]; 60 | } 61 | return output_buf; 62 | } 63 | 64 | static char *encodeHex(const char *data, int size, char hexTable[]) { 65 | char *output = malloc(size * 2); 66 | return encodeHexInternal(output, data, size, hexTable); 67 | } 68 | 69 | char *qn_encodeHexData(char *buff, const char *data, int data_size, BOOL up) { 70 | char *hexTable = DIGITS_UPPER; 71 | if (!up) { 72 | hexTable = DIGITS_LOWER; 73 | } 74 | return encodeHexInternal(buff, data, data_size, hexTable); 75 | } 76 | 77 | @implementation QNHex 78 | 79 | + (NSString *)encodeHexData:(NSData *)data { 80 | char *e = encodeHex(data.bytes, (int)data.length, DIGITS_UPPER); 81 | NSString *str = [[NSString alloc] initWithBytes:e length:data.length * 2 encoding:NSASCIIStringEncoding]; 82 | free(e); 83 | return str; 84 | } 85 | 86 | + (NSString *)encodeHexString:(NSString *)str { 87 | return [QNHex encodeHexData:[str dataUsingEncoding:NSUTF8StringEncoding]]; 88 | } 89 | 90 | + (NSData *)decodeHexString:(NSString *)hex { 91 | char *d = decodeHex(hex.UTF8String, (int)hex.length); 92 | if (d == NULL) { 93 | return nil; 94 | } 95 | NSData *data = [NSData dataWithBytes:d length:hex.length / 2]; 96 | free(d); 97 | return data; 98 | } 99 | 100 | + (NSString *)decodeHexToString:(NSString *)hex { 101 | NSData *data = [QNHex decodeHexString:hex]; 102 | if (data == nil) { 103 | return nil; 104 | } 105 | return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 106 | } 107 | 108 | @end 109 | -------------------------------------------------------------------------------- /ImageHosting/External/HappyDNS/Util/QNIP.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNIPV6.h 3 | // HappyDNS 4 | // 5 | // Created by bailong on 16/5/25. 6 | // Copyright © 2016年 Qiniu Cloud Storage. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | extern int qn_localIp(char *buf, int buf_size); 12 | extern void qn_nat64(char *buf, int buf_size, uint32_t ipv4_addr); 13 | 14 | @interface QNIP : NSObject 15 | 16 | + (BOOL)isV6; 17 | 18 | + (NSString *)adaptiveIp:(NSString *)ipv4; 19 | 20 | + (NSString *)local; 21 | 22 | // ipv6 in url like http://[::xxx]/ 23 | + (NSString *)ipHost:(NSString *)ip; 24 | 25 | + (NSString *)nat64:(NSString *)ip; 26 | 27 | + (BOOL)isIpV6FullySupported; 28 | 29 | + (BOOL)mayBeIpV4:(NSString *)domain; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Common/QNALAssetFile.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNALAssetFile.h 3 | // QiniuSDK 4 | // 5 | // Created by bailong on 15/7/25. 6 | // Copyright (c) 2015年 Qiniu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "QNFileDelegate.h" 12 | 13 | #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) 14 | @class ALAsset; 15 | @interface QNALAssetFile : NSObject 16 | 17 | /** 18 | * 打开指定文件 19 | * 20 | * @param path 文件路径 21 | * @param error 输出的错误信息 22 | * 23 | * @return 实例 24 | */ 25 | - (instancetype)init:(ALAsset *)asset 26 | error:(NSError *__autoreleasing *)error; 27 | @end 28 | #endif -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Common/QNALAssetFile.m: -------------------------------------------------------------------------------- 1 | // 2 | // QNALAssetFile.m 3 | // QiniuSDK 4 | // 5 | // Created by bailong on 15/7/25. 6 | // Copyright (c) 2015年 Qiniu. All rights reserved. 7 | // 8 | 9 | #import "QNALAssetFile.h" 10 | 11 | #ifdef __IPHONE_OS_VERSION_MAX_ALLOWED 12 | #import 13 | 14 | #import "QNResponseInfo.h" 15 | 16 | @interface QNALAssetFile () 17 | 18 | @property (nonatomic) ALAsset *asset; 19 | 20 | @property (readonly) int64_t fileSize; 21 | 22 | @property (readonly) int64_t fileModifyTime; 23 | 24 | @end 25 | 26 | @implementation QNALAssetFile 27 | - (instancetype)init:(ALAsset *)asset 28 | error:(NSError *__autoreleasing *)error { 29 | if (self = [super init]) { 30 | NSDate *createTime = [asset valueForProperty:ALAssetPropertyDate]; 31 | int64_t t = 0; 32 | if (createTime != nil) { 33 | t = [createTime timeIntervalSince1970]; 34 | } 35 | _fileModifyTime = t; 36 | _fileSize = asset.defaultRepresentation.size; 37 | _asset = asset; 38 | } 39 | 40 | return self; 41 | } 42 | 43 | - (NSData *)read:(long)offset 44 | size:(long)size { 45 | ALAssetRepresentation *rep = [self.asset defaultRepresentation]; 46 | Byte *buffer = (Byte *)malloc(size); 47 | NSUInteger buffered = [rep getBytes:buffer fromOffset:offset length:size error:nil]; 48 | 49 | return [NSData dataWithBytesNoCopy:buffer length:buffered freeWhenDone:YES]; 50 | } 51 | 52 | - (NSData *)readAll { 53 | return [self read:0 size:(long)_fileSize]; 54 | } 55 | 56 | - (void)close { 57 | } 58 | 59 | - (NSString *)path { 60 | ALAssetRepresentation *rep = [self.asset defaultRepresentation]; 61 | return [rep url].path; 62 | } 63 | 64 | - (int64_t)modifyTime { 65 | return _fileModifyTime; 66 | } 67 | 68 | - (int64_t)size { 69 | return _fileSize; 70 | } 71 | @end 72 | #endif 73 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Common/QNAsyncRun.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNAsyncRun.h 3 | // QiniuSDK 4 | // 5 | // Created by bailong on 14/10/17. 6 | // Copyright (c) 2014年 Qiniu. All rights reserved. 7 | // 8 | 9 | typedef void (^QNRun)(void); 10 | 11 | void QNAsyncRun(QNRun run); 12 | 13 | void QNAsyncRunInMain(QNRun run); 14 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Common/QNAsyncRun.m: -------------------------------------------------------------------------------- 1 | // 2 | // QNAsyncRun.m 3 | // QiniuSDK 4 | // 5 | // Created by bailong on 14/10/17. 6 | // Copyright (c) 2014年 Qiniu. All rights reserved. 7 | // 8 | 9 | #import "QNAsyncRun.h" 10 | #import 11 | 12 | void QNAsyncRun(QNRun run) { 13 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) { 14 | run(); 15 | }); 16 | } 17 | 18 | void QNAsyncRunInMain(QNRun run) { 19 | dispatch_async(dispatch_get_main_queue(), ^(void) { 20 | run(); 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Common/QNCrc32.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNCrc.h 3 | // QiniuSDK 4 | // 5 | // Created by bailong on 14-9-29. 6 | // Copyright (c) 2014年 Qiniu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /** 12 | * 生成crc32 校验码 13 | */ 14 | @interface QNCrc32 : NSObject 15 | 16 | /** 17 | * 文件校验 18 | * 19 | * @param filePath 文件路径 20 | * @param error 文件读取错误 21 | * 22 | * @return 校验码 23 | */ 24 | + (UInt32)file:(NSString *)filePath 25 | error:(NSError **)error; 26 | 27 | /** 28 | * 二进制字节校验 29 | * 30 | * @param data 二进制数据 31 | * 32 | * @return 校验码 33 | */ 34 | + (UInt32)data:(NSData *)data; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Common/QNCrc32.m: -------------------------------------------------------------------------------- 1 | // 2 | // QNCrc.m 3 | // QiniuSDK 4 | // 5 | // Created by bailong on 14-9-29. 6 | // Copyright (c) 2014年 Qiniu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "QNConfiguration.h" 12 | #import "QNCrc32.h" 13 | 14 | @implementation QNCrc32 15 | 16 | + (UInt32)data:(NSData *)data { 17 | uLong crc = crc32(0L, Z_NULL, 0); 18 | 19 | crc = crc32(crc, [data bytes], (uInt)[data length]); 20 | return (UInt32)crc; 21 | } 22 | 23 | + (UInt32)file:(NSString *)filePath 24 | error:(NSError **)error { 25 | @autoreleasepool { 26 | NSData *data = [NSData dataWithContentsOfFile:filePath options:NSDataReadingMappedIfSafe error:error]; 27 | if (*error != nil) { 28 | return 0; 29 | } 30 | 31 | int len = (int)[data length]; 32 | int count = (len + kQNBlockSize - 1) / kQNBlockSize; 33 | 34 | uLong crc = crc32(0L, Z_NULL, 0); 35 | for (int i = 0; i < count; i++) { 36 | int offset = i * kQNBlockSize; 37 | int size = (len - offset) > kQNBlockSize ? kQNBlockSize : (len - offset); 38 | NSData *d = [data subdataWithRange:NSMakeRange(offset, (unsigned int)size)]; 39 | crc = crc32(crc, [d bytes], (uInt)[d length]); 40 | } 41 | return (UInt32)crc; 42 | } 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Common/QNEtag.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNEtag.h 3 | // QiniuSDK 4 | // 5 | // Created by bailong on 14/10/4. 6 | // Copyright (c) 2014年 Qiniu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /** 12 | * 服务器 hash etag 生成 13 | */ 14 | @interface QNEtag : NSObject 15 | 16 | /** 17 | * 文件etag 18 | * 19 | * @param filePath 文件路径 20 | * @param error 输出文件读取错误 21 | * 22 | * @return etag 23 | */ 24 | + (NSString *)file:(NSString *)filePath 25 | error:(NSError **)error; 26 | 27 | /** 28 | * 二进制数据etag 29 | * 30 | * @param data 数据 31 | * 32 | * @return etag 33 | */ 34 | + (NSString *)data:(NSData *)data; 35 | @end 36 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Common/QNEtag.m: -------------------------------------------------------------------------------- 1 | // 2 | // QNEtag.m 3 | // QiniuSDK 4 | // 5 | // Created by bailong on 14/10/4. 6 | // Copyright (c) 2014年 Qiniu. All rights reserved. 7 | // 8 | 9 | #include 10 | 11 | #import "QNConfiguration.h" 12 | #import "QNEtag.h" 13 | #import "QNUrlSafeBase64.h" 14 | 15 | @implementation QNEtag 16 | + (NSString *)file:(NSString *)filePath 17 | error:(NSError **)error { 18 | @autoreleasepool { 19 | NSData *data = [NSData dataWithContentsOfFile:filePath options:NSDataReadingMappedIfSafe error:error]; 20 | if (*error != nil) { 21 | return 0; 22 | } 23 | return [QNEtag data:data]; 24 | } 25 | } 26 | 27 | + (NSString *)data:(NSData *)data { 28 | if (data == nil || [data length] == 0) { 29 | return @"Fto5o-5ea0sNMlW_75VgGJCv2AcJ"; 30 | } 31 | int len = (int)[data length]; 32 | int count = (len + kQNBlockSize - 1) / kQNBlockSize; 33 | 34 | NSMutableData *retData = [NSMutableData dataWithLength:CC_SHA1_DIGEST_LENGTH + 1]; 35 | UInt8 *ret = [retData mutableBytes]; 36 | 37 | NSMutableData *blocksSha1 = nil; 38 | UInt8 *pblocksSha1 = ret + 1; 39 | if (count > 1) { 40 | blocksSha1 = [NSMutableData dataWithLength:CC_SHA1_DIGEST_LENGTH * count]; 41 | pblocksSha1 = [blocksSha1 mutableBytes]; 42 | } 43 | 44 | for (int i = 0; i < count; i++) { 45 | int offset = i * kQNBlockSize; 46 | int size = (len - offset) > kQNBlockSize ? kQNBlockSize : (len - offset); 47 | NSData *d = [data subdataWithRange:NSMakeRange(offset, (unsigned int)size)]; 48 | CC_SHA1([d bytes], (CC_LONG)size, pblocksSha1 + i * CC_SHA1_DIGEST_LENGTH); 49 | } 50 | if (count == 1) { 51 | ret[0] = 0x16; 52 | } else { 53 | ret[0] = 0x96; 54 | CC_SHA1(pblocksSha1, (CC_LONG)CC_SHA1_DIGEST_LENGTH * count, ret + 1); 55 | } 56 | 57 | return [QNUrlSafeBase64 encodeData:retData]; 58 | } 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Common/QNFile.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNFile.h 3 | // QiniuSDK 4 | // 5 | // Created by bailong on 15/7/25. 6 | // Copyright (c) 2015年 Qiniu. All rights reserved. 7 | // 8 | 9 | #import "QNFileDelegate.h" 10 | #import 11 | 12 | @interface QNFile : NSObject 13 | /** 14 | * 打开指定文件 15 | * 16 | * @param path 文件路径 17 | * @param error 输出的错误信息 18 | * 19 | * @return 实例 20 | */ 21 | - (instancetype)init:(NSString *)path 22 | error:(NSError *__autoreleasing *)error; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Common/QNFile.m: -------------------------------------------------------------------------------- 1 | // 2 | // QNFile.m 3 | // QiniuSDK 4 | // 5 | // Created by bailong on 15/7/25. 6 | // Copyright (c) 2015年 Qiniu. All rights reserved. 7 | // 8 | 9 | #import "QNFile.h" 10 | #import "QNResponseInfo.h" 11 | 12 | @interface QNFile () 13 | 14 | @property (nonatomic, readonly) NSString *filepath; 15 | 16 | @property (nonatomic) NSData *data; 17 | 18 | @property (readonly) int64_t fileSize; 19 | 20 | @property (readonly) int64_t fileModifyTime; 21 | 22 | @property (nonatomic) NSFileHandle *file; 23 | 24 | @end 25 | 26 | @implementation QNFile 27 | 28 | - (instancetype)init:(NSString *)path 29 | error:(NSError *__autoreleasing *)error { 30 | if (self = [super init]) { 31 | _filepath = path; 32 | NSError *error2 = nil; 33 | NSDictionary *fileAttr = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:&error2]; 34 | if (error2 != nil) { 35 | if (error != nil) { 36 | *error = error2; 37 | } 38 | return self; 39 | } 40 | _fileSize = [fileAttr fileSize]; 41 | NSDate *modifyTime = fileAttr[NSFileModificationDate]; 42 | int64_t t = 0; 43 | if (modifyTime != nil) { 44 | t = [modifyTime timeIntervalSince1970]; 45 | } 46 | _fileModifyTime = t; 47 | NSFileHandle *f = nil; 48 | NSData *d = nil; 49 | //[NSData dataWithContentsOfFile:filePath options:NSDataReadingMappedIfSafe error:&error] 不能用在大于 200M的文件上,改用filehandle 50 | // 参见 https://issues.apache.org/jira/browse/CB-5790 51 | if (_fileSize > 16 * 1024 * 1024) { 52 | f = [NSFileHandle fileHandleForReadingAtPath:path]; 53 | if (f == nil) { 54 | if (error != nil) { 55 | *error = [[NSError alloc] initWithDomain:path code:kQNFileError userInfo:nil]; 56 | } 57 | return self; 58 | } 59 | } else { 60 | d = [NSData dataWithContentsOfFile:path options:NSDataReadingMappedIfSafe error:&error2]; 61 | if (error2 != nil) { 62 | if (error != nil) { 63 | *error = error2; 64 | } 65 | return self; 66 | } 67 | } 68 | _file = f; 69 | _data = d; 70 | } 71 | 72 | return self; 73 | } 74 | 75 | - (NSData *)read:(long)offset 76 | size:(long)size { 77 | if (_data != nil) { 78 | return [_data subdataWithRange:NSMakeRange(offset, (unsigned int)size)]; 79 | } 80 | [_file seekToFileOffset:offset]; 81 | return [_file readDataOfLength:size]; 82 | } 83 | 84 | - (NSData *)readAll { 85 | return [self read:0 size:(long)_fileSize]; 86 | } 87 | 88 | - (void)close { 89 | if (_file != nil) { 90 | [_file closeFile]; 91 | } 92 | } 93 | 94 | - (NSString *)path { 95 | return _filepath; 96 | } 97 | 98 | - (int64_t)modifyTime { 99 | return _fileModifyTime; 100 | } 101 | 102 | - (int64_t)size { 103 | return _fileSize; 104 | } 105 | 106 | @end 107 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Common/QNFileDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNFileDelegate.h 3 | // QiniuSDK 4 | // 5 | // Created by bailong on 15/7/25. 6 | // Copyright (c) 2015年 Qiniu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /** 12 | * 文件处理接口,支持ALAsset, NSFileHandle, NSData 13 | */ 14 | @protocol QNFileDelegate 15 | 16 | /** 17 | * 从指定偏移读取数据 18 | * 19 | * @param offset 偏移地址 20 | * @param size 大小 21 | * 22 | * @return 数据 23 | */ 24 | - (NSData *)read:(long)offset 25 | size:(long)size; 26 | 27 | /** 28 | * 读取所有文件内容 29 | * 30 | * @return 数据 31 | */ 32 | - (NSData *)readAll; 33 | 34 | /** 35 | * 关闭文件 36 | * 37 | */ 38 | - (void)close; 39 | 40 | /** 41 | * 文件路径 42 | * 43 | * @return 文件路径 44 | */ 45 | - (NSString *)path; 46 | 47 | /** 48 | * 文件修改时间 49 | * 50 | * @return 修改时间 51 | */ 52 | - (int64_t)modifyTime; 53 | 54 | /** 55 | * 文件大小 56 | * 57 | * @return 文件大小 58 | */ 59 | - (int64_t)size; 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Common/QNPHAssetFile.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNPHAssetFile.h 3 | // Pods 4 | // 5 | // Created by 何舒 on 15/10/21. 6 | // 7 | // 8 | 9 | #import 10 | 11 | #import "QNFileDelegate.h" 12 | 13 | #if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000) 14 | @class PHAsset; 15 | @interface QNPHAssetFile : NSObject 16 | /** 17 | * 打开指定文件 18 | * 19 | * @param path 文件路径 20 | * @param error 输出的错误信息 21 | * 22 | * @return 实例 23 | */ 24 | - (instancetype)init:(PHAsset *)phAsset 25 | error:(NSError *__autoreleasing *)error; 26 | @end 27 | #endif 28 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Common/QNPHAssetResource.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNPHAssetResource.h 3 | // QiniuSDK 4 | // 5 | // Created by 何舒 on 16/2/14. 6 | // Copyright © 2016年 Qiniu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "QNFileDelegate.h" 12 | 13 | #if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 90100) 14 | 15 | @class PHAssetResource; 16 | 17 | @interface QNPHAssetResource : NSObject 18 | 19 | /** 20 | * 打开指定文件 21 | * 22 | * @param path PHLivePhoto的PHAssetResource文件 23 | * @param error 输出的错误信息 24 | * 25 | * @return 实例 26 | */ 27 | - (instancetype)init:(PHAssetResource *)phAssetResource 28 | error:(NSError *__autoreleasing *)error; 29 | 30 | @end 31 | #endif 32 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Common/QNSystem.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNSystem.h 3 | // QiniuSDK 4 | // 5 | // Created by bailong on 15/10/13. 6 | // Copyright © 2015年 Qiniu. All rights reserved. 7 | // 8 | 9 | #ifndef QNSystem_h 10 | #define QNSystem_h 11 | 12 | BOOL hasNSURLSession(); 13 | 14 | BOOL hasAts(); 15 | 16 | BOOL allowsArbitraryLoads(); 17 | 18 | BOOL isIpV6FullySupported(); 19 | 20 | #endif /* QNSystem_h */ 21 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Common/QNSystem.m: -------------------------------------------------------------------------------- 1 | // 2 | // QNSystem.m 3 | // QiniuSDK 4 | // 5 | // Created by bailong on 15/10/13. 6 | // Copyright © 2015年 Qiniu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #if __IPHONE_OS_VERSION_MIN_REQUIRED 12 | #import 13 | #import 14 | #else 15 | #import 16 | #endif 17 | 18 | BOOL hasNSURLSession() { 19 | #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) 20 | float sysVersion = [[[UIDevice currentDevice] systemVersion] floatValue]; 21 | if (sysVersion < 7.0) { 22 | return NO; 23 | } 24 | #else 25 | NSOperatingSystemVersion sysVersion = [[NSProcessInfo processInfo] operatingSystemVersion]; 26 | if (sysVersion.majorVersion < 10) { 27 | return NO; 28 | } else if (sysVersion.majorVersion == 10) { 29 | return sysVersion.minorVersion >= 9; 30 | } 31 | #endif 32 | return YES; 33 | } 34 | 35 | BOOL hasAts() { 36 | #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) 37 | float sysVersion = [[[UIDevice currentDevice] systemVersion] floatValue]; 38 | if (sysVersion < 9.0) { 39 | return NO; 40 | } 41 | #else 42 | NSOperatingSystemVersion sysVersion = [[NSProcessInfo processInfo] operatingSystemVersion]; 43 | if (sysVersion.majorVersion < 10) { 44 | return NO; 45 | } else if (sysVersion.majorVersion == 10) { 46 | return sysVersion.minorVersion >= 11; 47 | } 48 | #endif 49 | return YES; 50 | } 51 | 52 | BOOL allowsArbitraryLoads() { 53 | if (!hasAts()) { 54 | return YES; 55 | } 56 | 57 | // for unit test 58 | NSDictionary* d = [[NSBundle mainBundle] infoDictionary]; 59 | if (d == nil || d.count == 0) { 60 | return YES; 61 | } 62 | 63 | NSDictionary* sec = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSAppTransportSecurity"]; 64 | if (sec == nil) { 65 | return NO; 66 | } 67 | NSNumber* ats = [sec objectForKey:@"NSAllowsArbitraryLoads"]; 68 | if (ats == nil) { 69 | return NO; 70 | } 71 | return ats.boolValue; 72 | } 73 | 74 | BOOL isIpV6FullySupported() { 75 | #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) 76 | float sysVersion = [[[UIDevice currentDevice] systemVersion] floatValue]; 77 | if (sysVersion < 9.0) { 78 | return NO; 79 | } 80 | #else 81 | NSOperatingSystemVersion sysVersion = [[NSProcessInfo processInfo] operatingSystemVersion]; 82 | if (sysVersion.majorVersion < 10) { 83 | return NO; 84 | } else if (sysVersion.majorVersion == 10) { 85 | return sysVersion.minorVersion >= 11; 86 | } 87 | #endif 88 | return YES; 89 | } 90 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Common/QNUrlSafeBase64.h: -------------------------------------------------------------------------------- 1 | // 2 | // QiniuSDK 3 | // 4 | // Created by bailong on 14-9-28. 5 | // Copyright (c) 2014年 Qiniu. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | /** 11 | * url safe base64 编码类, 对/ 做了处理 12 | */ 13 | @interface QNUrlSafeBase64 : NSObject 14 | 15 | /** 16 | * 字符串编码 17 | * 18 | * @param source 字符串 19 | * 20 | * @return base64 字符串 21 | */ 22 | + (NSString *)encodeString:(NSString *)source; 23 | 24 | /** 25 | * 二进制数据编码 26 | * 27 | * @param source 二进制数据 28 | * 29 | * @return base64字符串 30 | */ 31 | + (NSString *)encodeData:(NSData *)source; 32 | 33 | /** 34 | * 字符串解码 35 | * 36 | * @param base64 字符串 37 | * 38 | * @return 数据 39 | */ 40 | + (NSData *)decodeString:(NSString *)data; 41 | @end 42 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Common/QNUrlSafeBase64.m: -------------------------------------------------------------------------------- 1 | // 2 | // QiniuSDK 3 | // 4 | // Created by bailong on 14-9-28. 5 | // Copyright (c) 2014年 Qiniu. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | #import "QNUrlSafeBase64.h" 11 | 12 | #import "QN_GTM_Base64.h" 13 | 14 | @implementation QNUrlSafeBase64 15 | 16 | + (NSString *)encodeString:(NSString *)sourceString { 17 | NSData *data = [NSData dataWithBytes:[sourceString UTF8String] length:[sourceString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]]; 18 | return [self encodeData:data]; 19 | } 20 | 21 | + (NSString *)encodeData:(NSData *)data { 22 | return [QN_GTM_Base64 stringByWebSafeEncodingData:data padded:YES]; 23 | } 24 | 25 | + (NSData *)decodeString:(NSString *)data { 26 | return [QN_GTM_Base64 webSafeDecodeString:data]; 27 | } 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Common/QNVersion.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNVersion.h 3 | // QiniuSDK 4 | // 5 | // Created by bailong on 14-9-29. 6 | // Copyright (c) 2014年 Qiniu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /** 12 | * sdk 版本 13 | */ 14 | static const NSString *kQiniuVersion = @"7.1.0"; 15 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Http/QNHttpDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @class QNResponseInfo; 4 | 5 | typedef void (^QNInternalProgressBlock)(long long totalBytesWritten, long long totalBytesExpectedToWrite); 6 | typedef void (^QNCompleteBlock)(QNResponseInfo *info, NSDictionary *resp); 7 | typedef BOOL (^QNCancelBlock)(void); 8 | 9 | /** 10 | * Http 客户端接口 11 | */ 12 | @protocol QNHttpDelegate 13 | 14 | - (void)multipartPost:(NSString *)url 15 | withData:(NSData *)data 16 | withParams:(NSDictionary *)params 17 | withFileName:(NSString *)key 18 | withMimeType:(NSString *)mime 19 | withCompleteBlock:(QNCompleteBlock)completeBlock 20 | withProgressBlock:(QNInternalProgressBlock)progressBlock 21 | withCancelBlock:(QNCancelBlock)cancelBlock; 22 | 23 | - (void)post:(NSString *)url 24 | withData:(NSData *)data 25 | withParams:(NSDictionary *)params 26 | withHeaders:(NSDictionary *)headers 27 | withCompleteBlock:(QNCompleteBlock)completeBlock 28 | withProgressBlock:(QNInternalProgressBlock)progressBlock 29 | withCancelBlock:(QNCancelBlock)cancelBlock; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Http/QNResponseInfo.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNResponseInfo.h 3 | // QiniuSDK 4 | // 5 | // Created by bailong on 14/10/2. 6 | // Copyright (c) 2014年 Qiniu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /** 12 | * 中途取消的状态码 13 | */ 14 | extern const int kQNRequestCancelled; 15 | 16 | /** 17 | * 网络错误状态码 18 | */ 19 | extern const int kQNNetworkError; 20 | 21 | /** 22 | * 错误参数状态码 23 | */ 24 | extern const int kQNInvalidArgument; 25 | 26 | /** 27 | * 0 字节文件或数据 28 | */ 29 | extern const int kQNZeroDataSize; 30 | 31 | /** 32 | * 错误token状态码 33 | */ 34 | extern const int kQNInvalidToken; 35 | 36 | /** 37 | * 读取文件错误状态码 38 | */ 39 | extern const int kQNFileError; 40 | 41 | /** 42 | * 上传完成后返回的状态信息 43 | */ 44 | @interface QNResponseInfo : NSObject 45 | 46 | /** 47 | * 状态码 48 | */ 49 | @property (readonly) int statusCode; 50 | 51 | /** 52 | * 七牛服务器生成的请求ID,用来跟踪请求信息,如果使用过程中出现问题,请反馈此ID 53 | */ 54 | @property (nonatomic, copy, readonly) NSString *reqId; 55 | 56 | /** 57 | * 七牛服务器内部跟踪记录 58 | */ 59 | @property (nonatomic, copy, readonly) NSString *xlog; 60 | 61 | /** 62 | * cdn服务器内部跟踪记录 63 | */ 64 | @property (nonatomic, copy, readonly) NSString *xvia; 65 | 66 | /** 67 | * 错误信息,出错时请反馈此记录 68 | */ 69 | @property (nonatomic, copy, readonly) NSError *error; 70 | 71 | /** 72 | * 服务器域名 73 | */ 74 | @property (nonatomic, copy, readonly) NSString *host; 75 | 76 | /** 77 | * 请求消耗的时间,单位 秒 78 | */ 79 | @property (nonatomic, readonly) double duration; 80 | 81 | /** 82 | * 服务器IP 83 | */ 84 | @property (nonatomic, readonly) NSString *serverIp; 85 | 86 | /** 87 | * 客户端id 88 | */ 89 | @property (nonatomic, readonly) NSString *id; 90 | 91 | /** 92 | * 时间戳 93 | */ 94 | @property (readonly) UInt64 timeStamp; 95 | 96 | /** 97 | * 网络类型 98 | */ 99 | //@property (nonatomic, readonly) NSString *networkType; 100 | 101 | /** 102 | * 是否取消 103 | */ 104 | @property (nonatomic, readonly, getter=isCancelled) BOOL canceled; 105 | 106 | /** 107 | * 成功的请求 108 | */ 109 | @property (nonatomic, readonly, getter=isOK) BOOL ok; 110 | 111 | /** 112 | * 是否网络错误 113 | */ 114 | @property (nonatomic, readonly, getter=isConnectionBroken) BOOL broken; 115 | 116 | /** 117 | * 是否需要重试,内部使用 118 | */ 119 | @property (nonatomic, readonly) BOOL couldRetry; 120 | 121 | /** 122 | * 是否需要换备用server,内部使用 123 | */ 124 | @property (nonatomic, readonly) BOOL needSwitchServer; 125 | 126 | /** 127 | * 是否为 七牛响应 128 | */ 129 | @property (nonatomic, readonly, getter=isNotQiniu) BOOL notQiniu; 130 | 131 | /** 132 | * 工厂函数,内部使用 133 | * 134 | * @return 取消的实例 135 | */ 136 | + (instancetype)cancel; 137 | 138 | /** 139 | * 工厂函数,内部使用 140 | * 141 | * @param desc 错误参数描述 142 | * 143 | * @return 错误参数实例 144 | */ 145 | + (instancetype)responseInfoWithInvalidArgument:(NSString *)desc; 146 | 147 | /** 148 | * 工厂函数,内部使用 149 | * 150 | * @param desc 错误token描述 151 | * 152 | * @return 错误token实例 153 | */ 154 | + (instancetype)responseInfoWithInvalidToken:(NSString *)desc; 155 | 156 | /** 157 | * 工厂函数,内部使用 158 | * 159 | * @param error 错误信息 160 | * @param host 服务器域名 161 | * @param duration 请求完成时间,单位秒 162 | * 163 | * @return 网络错误实例 164 | */ 165 | + (instancetype)responseInfoWithNetError:(NSError *)error 166 | host:(NSString *)host 167 | duration:(double)duration; 168 | 169 | /** 170 | * 工厂函数,内部使用 171 | * 172 | * @param error 错误信息 173 | * 174 | * @return 文件错误实例 175 | */ 176 | + (instancetype)responseInfoWithFileError:(NSError *)error; 177 | 178 | /** 179 | * 工厂函数,内部使用 180 | * 181 | * @return 文件错误实例 182 | */ 183 | + (instancetype)responseInfoOfZeroData:(NSString *)path; 184 | 185 | /** 186 | * 构造函数 187 | * 188 | * @param status 状态码 189 | * @param reqId 七牛服务器请求id 190 | * @param xlog 七牛服务器记录 191 | * @param body 服务器返回内容 192 | * @param host 服务器域名 193 | * @param duration 请求完成时间,单位秒 194 | * 195 | * @return 实例 196 | */ 197 | - (instancetype)init:(int)status 198 | withReqId:(NSString *)reqId 199 | withXLog:(NSString *)xlog 200 | withXVia:(NSString *)xvia 201 | withHost:(NSString *)host 202 | withIp:(NSString *)ip 203 | withDuration:(double)duration 204 | withBody:(NSData *)body; 205 | 206 | @end 207 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Http/QNSessionManager.h: -------------------------------------------------------------------------------- 1 | #import "QNHttpDelegate.h" 2 | #import 3 | 4 | #import "QNConfiguration.h" 5 | 6 | #if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000) || (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1090) 7 | 8 | @interface QNSessionManager : NSObject 9 | 10 | - (instancetype)initWithProxy:(NSDictionary *)proxyDict 11 | timeout:(UInt32)timeout 12 | urlConverter:(QNUrlConvert)converter 13 | dns:(QNDnsManager *)dns; 14 | 15 | - (void)multipartPost:(NSString *)url 16 | withData:(NSData *)data 17 | withParams:(NSDictionary *)params 18 | withFileName:(NSString *)key 19 | withMimeType:(NSString *)mime 20 | withCompleteBlock:(QNCompleteBlock)completeBlock 21 | withProgressBlock:(QNInternalProgressBlock)progressBlock 22 | withCancelBlock:(QNCancelBlock)cancelBlock; 23 | 24 | - (void)post:(NSString *)url 25 | withData:(NSData *)data 26 | withParams:(NSDictionary *)params 27 | withHeaders:(NSDictionary *)headers 28 | withCompleteBlock:(QNCompleteBlock)completeBlock 29 | withProgressBlock:(QNInternalProgressBlock)progressBlock 30 | withCancelBlock:(QNCancelBlock)cancelBlock; 31 | 32 | @end 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Http/QNUserAgent.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNUserAgent.h 3 | // QiniuSDK 4 | // 5 | // Created by bailong on 14-9-29. 6 | // Copyright (c) 2014年 Qiniu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /** 12 | * UserAgent 13 | * 14 | */ 15 | 16 | @interface QNUserAgent : NSObject 17 | 18 | /** 19 | * 用户id 20 | */ 21 | @property (copy, nonatomic, readonly) NSString *id; 22 | 23 | /** 24 | * UserAgent 字串 25 | */ 26 | - (NSString *)description; 27 | 28 | /** 29 | * 单例 30 | */ 31 | + (instancetype)sharedInstance; 32 | @end 33 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Http/QNUserAgent.m: -------------------------------------------------------------------------------- 1 | // 2 | // QNUserAgent.m 3 | // QiniuSDK 4 | // 5 | // Created by bailong on 14-9-29. 6 | // Copyright (c) 2014年 Qiniu. All rights reserved. 7 | // 8 | 9 | #import 10 | #if __IPHONE_OS_VERSION_MIN_REQUIRED 11 | #import 12 | #import 13 | #else 14 | #import 15 | #endif 16 | 17 | #import "QNUserAgent.h" 18 | #import "QNVersion.h" 19 | 20 | static NSString *clientId(void) { 21 | #if __IPHONE_OS_VERSION_MIN_REQUIRED 22 | NSString *s = [[[UIDevice currentDevice] identifierForVendor] UUIDString]; 23 | if (s == nil) { 24 | s = @"simulator"; 25 | } 26 | return s; 27 | #else 28 | long long now_timestamp = [[NSDate date] timeIntervalSince1970] * 1000; 29 | int r = arc4random() % 1000; 30 | return [NSString stringWithFormat:@"%lld%u", now_timestamp, r]; 31 | #endif 32 | } 33 | 34 | static NSString *userAgent(NSString *id) { 35 | #if __IPHONE_OS_VERSION_MIN_REQUIRED 36 | return [NSString stringWithFormat:@"QiniuObject-C/%@ (%@; iOS %@; %@)", kQiniuVersion, [[UIDevice currentDevice] model], [[UIDevice currentDevice] systemVersion], id]; 37 | #else 38 | return [NSString stringWithFormat:@"QiniuObject-C/%@ (Mac OS X %@; %@)", kQiniuVersion, [[NSProcessInfo processInfo] operatingSystemVersionString], id]; 39 | #endif 40 | } 41 | 42 | @interface QNUserAgent () 43 | @property (nonatomic) NSString *ua; 44 | @end 45 | 46 | @implementation QNUserAgent 47 | 48 | - (NSString *)description { 49 | return _ua; 50 | } 51 | 52 | - (instancetype)init { 53 | if (self = [super init]) { 54 | _id = clientId(); 55 | _ua = userAgent(_id); 56 | } 57 | return self; 58 | } 59 | 60 | /** 61 | * 单例 62 | */ 63 | + (instancetype)sharedInstance { 64 | static QNUserAgent *sharedInstance = nil; 65 | 66 | static dispatch_once_t onceToken; 67 | dispatch_once(&onceToken, ^{ 68 | sharedInstance = [[self alloc] init]; 69 | }); 70 | 71 | return sharedInstance; 72 | } 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/QiniuSDK.h: -------------------------------------------------------------------------------- 1 | // 2 | // QiniuSDK.h 3 | // QiniuSDK 4 | // 5 | // Created by bailong on 14-9-28. 6 | // Copyright (c) 2014年 Qiniu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "QNConfiguration.h" 12 | #import "QNFileRecorder.h" 13 | #import "QNResponseInfo.h" 14 | #import "QNUploadManager.h" 15 | #import "QNUploadOption.h" 16 | #import "QNUrlSafeBase64.h" 17 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Recorder/QNFileRecorder.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNFileRecorder.h 3 | // QiniuSDK 4 | // 5 | // Created by bailong on 14/10/5. 6 | // Copyright (c) 2014年 Qiniu. All rights reserved. 7 | // 8 | 9 | #import "QNRecorderDelegate.h" 10 | #import 11 | 12 | /** 13 | * 将上传记录保存到文件系统中 14 | */ 15 | @interface QNFileRecorder : NSObject 16 | 17 | /** 18 | * 用指定保存的目录进行初始化 19 | * 20 | * @param directory 目录 21 | * @param error 输出的错误信息 22 | * 23 | * @return 实例 24 | */ 25 | + (instancetype)fileRecorderWithFolder:(NSString *)directory 26 | error:(NSError *__autoreleasing *)error; 27 | 28 | /** 29 | * 用指定保存的目录,以及是否进行base64编码进行初始化, 30 | * 31 | * @param directory 目录 32 | * @param encode 为避免因为特殊字符或含有/,无法保存持久化记录,故用此参数指定是否要base64编码 33 | * @param error 输出错误信息 34 | * 35 | * @return 实例 36 | */ 37 | + (instancetype)fileRecorderWithFolder:(NSString *)directory 38 | encodeKey:(BOOL)encode 39 | error:(NSError *__autoreleasing *)error; 40 | 41 | /** 42 | * 从外部手动删除记录,如无特殊需求,不建议使用 43 | * 44 | * @param key 持久化记录key 45 | * @param dir 目录 46 | * @param encode 是否encode 47 | */ 48 | + (void)removeKey:(NSString *)key 49 | directory:(NSString *)dir 50 | encodeKey:(BOOL)encode; 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Recorder/QNFileRecorder.m: -------------------------------------------------------------------------------- 1 | // 2 | // QNFileRecorder.m 3 | // QiniuSDK 4 | // 5 | // Created by bailong on 14/10/5. 6 | // Copyright (c) 2014年 Qiniu. All rights reserved. 7 | // 8 | 9 | #import "QNFileRecorder.h" 10 | #import "QNUrlSafeBase64.h" 11 | 12 | @interface QNFileRecorder () 13 | 14 | @property (copy, readonly) NSString *directory; 15 | @property BOOL encode; 16 | 17 | @end 18 | 19 | @implementation QNFileRecorder 20 | 21 | - (NSString *)pathOfKey:(NSString *)key { 22 | return [QNFileRecorder pathJoin:key path:_directory]; 23 | } 24 | 25 | + (NSString *)pathJoin:(NSString *)key 26 | path:(NSString *)path { 27 | return [[NSString alloc] initWithFormat:@"%@/%@", path, key]; 28 | } 29 | 30 | + (instancetype)fileRecorderWithFolder:(NSString *)directory 31 | error:(NSError *__autoreleasing *)perror { 32 | return [QNFileRecorder fileRecorderWithFolder:directory encodeKey:false error:perror]; 33 | } 34 | 35 | + (instancetype)fileRecorderWithFolder:(NSString *)directory 36 | encodeKey:(BOOL)encode 37 | error:(NSError *__autoreleasing *)perror { 38 | NSError *error; 39 | [[NSFileManager defaultManager] createDirectoryAtPath:directory withIntermediateDirectories:YES attributes:nil error:&error]; 40 | if (error != nil) { 41 | if (perror) { 42 | *perror = error; 43 | } 44 | return nil; 45 | } 46 | 47 | return [[QNFileRecorder alloc] initWithFolder:directory encodeKey:encode]; 48 | } 49 | 50 | - (instancetype)initWithFolder:(NSString *)directory encodeKey:(BOOL)encode { 51 | if (self = [super init]) { 52 | _directory = directory; 53 | _encode = encode; 54 | } 55 | return self; 56 | } 57 | 58 | - (NSError *)set:(NSString *)key 59 | data:(NSData *)value { 60 | NSError *error; 61 | if (_encode) { 62 | key = [QNUrlSafeBase64 encodeString:key]; 63 | } 64 | [value writeToFile:[self pathOfKey:key] options:NSDataWritingAtomic error:&error]; 65 | return error; 66 | } 67 | 68 | - (NSData *)get:(NSString *)key { 69 | if (_encode) { 70 | key = [QNUrlSafeBase64 encodeString:key]; 71 | } 72 | return [NSData dataWithContentsOfFile:[self pathOfKey:key]]; 73 | } 74 | 75 | - (NSError *)del:(NSString *)key { 76 | NSError *error; 77 | if (_encode) { 78 | key = [QNUrlSafeBase64 encodeString:key]; 79 | } 80 | [[NSFileManager defaultManager] removeItemAtPath:[self pathOfKey:key] error:&error]; 81 | return error; 82 | } 83 | 84 | + (void)removeKey:(NSString *)key 85 | directory:(NSString *)dir 86 | encodeKey:(BOOL)encode { 87 | if (encode) { 88 | key = [QNUrlSafeBase64 encodeString:key]; 89 | } 90 | NSError *error; 91 | NSString *path = [QNFileRecorder pathJoin:key path:dir]; 92 | [[NSFileManager defaultManager] removeItemAtPath:path error:&error]; 93 | } 94 | 95 | - (NSString *)description { 96 | return [NSString stringWithFormat:@"<%@: %p, dir: %@>", NSStringFromClass([self class]), self, _directory]; 97 | } 98 | 99 | @end 100 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Recorder/QNRecorderDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNRecorderDelegate.h 3 | // QiniuSDK 4 | // 5 | // Created by bailong on 14/10/5. 6 | // Copyright (c) 2014年 Qiniu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /** 12 | * 为持久化上传记录,根据上传的key以及文件名 生成持久化的记录key 13 | * 14 | * @param uploadKey 上传的key 15 | * @param filePath 文件名 16 | * 17 | * @return 根据uploadKey, filepath 算出的记录key 18 | */ 19 | typedef NSString * (^QNRecorderKeyGenerator)(NSString *uploadKey, NSString *filePath); 20 | 21 | /** 22 | * 持久化记录接口,可以实现将记录持久化到文件,数据库等 23 | */ 24 | @protocol QNRecorderDelegate 25 | 26 | /** 27 | * 保存记录 28 | * 29 | * @param key 持久化记录的key 30 | * @param value 持久化记录上传状态信息 31 | * 32 | * @return 错误信息,成功为nil 33 | */ 34 | - (NSError *)set:(NSString *)key 35 | data:(NSData *)value; 36 | 37 | /** 38 | * 取出保存的持久化上传状态信息 39 | * 40 | * @param key 持久化记录key 41 | * 42 | * @return 上传中间状态信息 43 | */ 44 | - (NSData *)get:(NSString *)key; 45 | 46 | /** 47 | * 删除持久化记录,一般在上传成功后自动调用 48 | * 49 | * @param key 持久化记录key 50 | * 51 | * @return 错误信息,成功为nil 52 | */ 53 | - (NSError *)del:(NSString *)key; 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Storage/QNConfiguration.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNConfiguration.h 3 | // QiniuSDK 4 | // 5 | // Created by bailong on 15/5/21. 6 | // Copyright (c) 2015年 Qiniu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "QNRecorderDelegate.h" 12 | 13 | /** 14 | * 断点上传时的分块大小 15 | */ 16 | extern const UInt32 kQNBlockSize; 17 | 18 | /** 19 | * 转换为用户需要的url 20 | * 21 | * @param url 上传url 22 | * 23 | * @return 根据上传url算出代理url 24 | */ 25 | typedef NSString * (^QNUrlConvert)(NSString *url); 26 | 27 | @class QNConfigurationBuilder; 28 | @class QNDnsManager; 29 | @class QNServiceAddress; 30 | /** 31 | * Builder block 32 | * 33 | * @param builder builder实例 34 | */ 35 | typedef void (^QNConfigurationBuilderBlock)(QNConfigurationBuilder *builder); 36 | 37 | @interface QNConfiguration : NSObject 38 | 39 | /** 40 | * 默认上传服务器地址 41 | */ 42 | @property (copy, nonatomic, readonly) QNServiceAddress *up; 43 | 44 | /** 45 | * 备用上传服务器地址 46 | */ 47 | @property (copy, nonatomic, readonly) QNServiceAddress *upBackup; 48 | 49 | /** 50 | * 断点上传时的分片大小 51 | */ 52 | @property (readonly) UInt32 chunkSize; 53 | 54 | /** 55 | * 如果大于此值就使用断点上传,否则使用form上传 56 | */ 57 | @property (readonly) UInt32 putThreshold; 58 | 59 | /** 60 | * 上传失败的重试次数 61 | */ 62 | @property (readonly) UInt32 retryMax; 63 | 64 | /** 65 | * 超时时间 单位 秒 66 | */ 67 | @property (readonly) UInt32 timeoutInterval; 68 | 69 | @property (nonatomic, readonly) id recorder; 70 | 71 | @property (nonatomic, readonly) QNRecorderKeyGenerator recorderKeyGen; 72 | 73 | @property (nonatomic, readonly) NSDictionary *proxy; 74 | 75 | @property (nonatomic, readonly) QNUrlConvert converter; 76 | 77 | @property (nonatomic, readonly) QNDnsManager *dns; 78 | 79 | @property (readonly) BOOL disableATS; 80 | 81 | + (instancetype)build:(QNConfigurationBuilderBlock)block; 82 | 83 | @end 84 | 85 | /** 86 | * 上传服务地址 87 | */ 88 | @interface QNServiceAddress : NSObject 89 | 90 | - (instancetype)init:(NSString *)address ips:(NSArray *)ips; 91 | 92 | @property (nonatomic, readonly) NSString *address; 93 | @property (nonatomic, readonly) NSArray *ips; 94 | 95 | @end 96 | 97 | @interface QNZone : NSObject 98 | 99 | /** 100 | * 默认上传服务器地址 101 | */ 102 | @property (nonatomic, readonly) QNServiceAddress *up; 103 | 104 | /** 105 | * 备用上传服务器地址 106 | */ 107 | @property (nonatomic, readonly) QNServiceAddress *upBackup; 108 | 109 | /** 110 | * Zone初始化方法 111 | * 112 | * @param upHost 默认上传服务器地址 113 | * @param upHostBackup 备用上传服务器地址 114 | * @param upIp 备用上传IP 115 | * 116 | * @return Zone实例 117 | */ 118 | - (instancetype)initWithUp:(QNServiceAddress *)up 119 | upBackup:(QNServiceAddress *)upBackup; 120 | 121 | /** 122 | * zone 0 123 | * 124 | * @return 实例 125 | */ 126 | + (instancetype)zone0; 127 | 128 | /** 129 | * zone 1 130 | * 131 | * @return 实例 132 | */ 133 | + (instancetype)zone1; 134 | 135 | @end 136 | 137 | @interface QNConfigurationBuilder : NSObject 138 | 139 | /** 140 | * 默认上传服务器地址 141 | */ 142 | @property (nonatomic, strong) QNZone *zone; 143 | 144 | /** 145 | * 断点上传时的分片大小 146 | */ 147 | @property (assign) UInt32 chunkSize; 148 | 149 | /** 150 | * 如果大于此值就使用断点上传,否则使用form上传 151 | */ 152 | @property (assign) UInt32 putThreshold; 153 | 154 | /** 155 | * 上传失败的重试次数 156 | */ 157 | @property (assign) UInt32 retryMax; 158 | 159 | /** 160 | * 超时时间 单位 秒 161 | */ 162 | @property (assign) UInt32 timeoutInterval; 163 | 164 | @property (nonatomic, strong) id recorder; 165 | 166 | @property (nonatomic, strong) QNRecorderKeyGenerator recorderKeyGen; 167 | 168 | @property (nonatomic, strong) NSDictionary *proxy; 169 | 170 | @property (nonatomic, strong) QNUrlConvert converter; 171 | 172 | @property (nonatomic, strong) QNDnsManager *dns; 173 | 174 | @property (assign) BOOL disableATS; 175 | 176 | @end 177 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Storage/QNFormUpload.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNFormUpload.h 3 | // QiniuSDK 4 | // 5 | // Created by bailong on 15/1/4. 6 | // Copyright (c) 2015年 Qiniu. All rights reserved. 7 | // 8 | 9 | #import "QNHttpDelegate.h" 10 | #import "QNUpToken.h" 11 | #import "QNUploadManager.h" 12 | #import 13 | 14 | @interface QNFormUpload : NSObject 15 | 16 | - (instancetype)initWithData:(NSData *)data 17 | withKey:(NSString *)key 18 | withToken:(QNUpToken *)token 19 | withCompletionHandler:(QNUpCompletionHandler)block 20 | withOption:(QNUploadOption *)option 21 | withHttpManager:(id)http 22 | withConfiguration:(QNConfiguration *)config; 23 | 24 | - (void)put; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Storage/QNFormUpload.m: -------------------------------------------------------------------------------- 1 | // 2 | // QNFormUpload.m 3 | // QiniuSDK 4 | // 5 | // Created by bailong on 15/1/4. 6 | // Copyright (c) 2015年 Qiniu. All rights reserved. 7 | // 8 | 9 | #import "QNFormUpload.h" 10 | #import "QNConfiguration.h" 11 | #import "QNCrc32.h" 12 | #import "QNRecorderDelegate.h" 13 | #import "QNResponseInfo.h" 14 | #import "QNUploadManager.h" 15 | #import "QNUploadOption+Private.h" 16 | #import "QNUrlSafeBase64.h" 17 | 18 | @interface QNFormUpload () 19 | 20 | @property (nonatomic, strong) NSData *data; 21 | @property (nonatomic, strong) id httpManager; 22 | @property (nonatomic) int retryTimes; 23 | @property (nonatomic, strong) NSString *key; 24 | @property (nonatomic, strong) QNUpToken *token; 25 | @property (nonatomic, strong) QNUploadOption *option; 26 | @property (nonatomic, strong) QNUpCompletionHandler complete; 27 | @property (nonatomic, strong) QNConfiguration *config; 28 | @property (nonatomic) float previousPercent; 29 | 30 | @end 31 | 32 | @implementation QNFormUpload 33 | 34 | - (instancetype)initWithData:(NSData *)data 35 | withKey:(NSString *)key 36 | withToken:(QNUpToken *)token 37 | withCompletionHandler:(QNUpCompletionHandler)block 38 | withOption:(QNUploadOption *)option 39 | withHttpManager:(id)http 40 | withConfiguration:(QNConfiguration *)config { 41 | if (self = [super init]) { 42 | _data = data; 43 | _key = key; 44 | _token = token; 45 | _option = option != nil ? option : [QNUploadOption defaultOptions]; 46 | _complete = block; 47 | _httpManager = http; 48 | _config = config; 49 | _previousPercent = 0; 50 | } 51 | return self; 52 | } 53 | 54 | - (void)put { 55 | NSMutableDictionary *parameters = [NSMutableDictionary dictionary]; 56 | NSString *fileName = _key; 57 | if (_key) { 58 | parameters[@"key"] = _key; 59 | } else { 60 | fileName = @"?"; 61 | } 62 | 63 | parameters[@"token"] = _token.token; 64 | 65 | [parameters addEntriesFromDictionary:_option.params]; 66 | 67 | if (_option.checkCrc) { 68 | parameters[@"crc32"] = [NSString stringWithFormat:@"%u", (unsigned int)[QNCrc32 data:_data]]; 69 | } 70 | 71 | QNInternalProgressBlock p = ^(long long totalBytesWritten, long long totalBytesExpectedToWrite) { 72 | float percent = (float)totalBytesWritten / (float)totalBytesExpectedToWrite; 73 | if (percent > 0.95) { 74 | percent = 0.95; 75 | } 76 | if (percent > _previousPercent) { 77 | _previousPercent = percent; 78 | } else { 79 | percent = _previousPercent; 80 | } 81 | _option.progressHandler(_key, percent); 82 | }; 83 | 84 | QNCompleteBlock complete = ^(QNResponseInfo *info, NSDictionary *resp) { 85 | if (info.isOK) { 86 | _option.progressHandler(_key, 1.0); 87 | } 88 | if (info.isOK || !info.couldRetry) { 89 | _complete(info, _key, resp); 90 | return; 91 | } 92 | if (_option.cancellationSignal()) { 93 | _complete([QNResponseInfo cancel], _key, nil); 94 | return; 95 | } 96 | NSString *nextHost = _config.up.address; 97 | if (info.isConnectionBroken || info.needSwitchServer) { 98 | nextHost = _config.upBackup.address; 99 | } 100 | 101 | QNCompleteBlock retriedComplete = ^(QNResponseInfo *info, NSDictionary *resp) { 102 | if (info.isOK) { 103 | _option.progressHandler(_key, 1.0); 104 | } 105 | _complete(info, _key, resp); 106 | }; 107 | 108 | [_httpManager multipartPost:nextHost 109 | withData:_data 110 | withParams:parameters 111 | withFileName:fileName 112 | withMimeType:_option.mimeType 113 | withCompleteBlock:retriedComplete 114 | withProgressBlock:p 115 | withCancelBlock:_option.cancellationSignal]; 116 | }; 117 | 118 | [_httpManager multipartPost:_config.up.address 119 | withData:_data 120 | withParams:parameters 121 | withFileName:fileName 122 | withMimeType:_option.mimeType 123 | withCompleteBlock:complete 124 | withProgressBlock:p 125 | withCancelBlock:_option.cancellationSignal]; 126 | } 127 | 128 | @end 129 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Storage/QNResumeUpload.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNResumeUpload.h 3 | // QiniuSDK 4 | // 5 | // Created by bailong on 14/10/1. 6 | // Copyright (c) 2014年 Qiniu. All rights reserved. 7 | // 8 | 9 | #import "QNFileDelegate.h" 10 | #import "QNHttpDelegate.h" 11 | #import "QNUpToken.h" 12 | #import "QNUploadManager.h" 13 | #import 14 | 15 | @interface QNResumeUpload : NSObject 16 | 17 | - (instancetype)initWithFile:(id)file 18 | withKey:(NSString *)key 19 | withToken:(QNUpToken *)token 20 | withCompletionHandler:(QNUpCompletionHandler)block 21 | withOption:(QNUploadOption *)option 22 | withRecorder:(id)recorder 23 | withRecorderKey:(NSString *)recorderKey 24 | withHttpManager:(id)http 25 | withConfiguration:(QNConfiguration *)config; 26 | 27 | - (void)run; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Storage/QNUpToken.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNUpToken.h 3 | // QiniuSDK 4 | // 5 | // Created by bailong on 15/6/7. 6 | // Copyright (c) 2015年 Qiniu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface QNUpToken : NSObject 12 | 13 | + (instancetype)parse:(NSString *)token; 14 | 15 | @property (copy, nonatomic, readonly) NSString *access; 16 | @property (copy, nonatomic, readonly) NSString *bucket; 17 | @property (copy, nonatomic, readonly) NSString *token; 18 | 19 | @property (readonly) BOOL hasReturnUrl; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Storage/QNUpToken.m: -------------------------------------------------------------------------------- 1 | // 2 | // QNUpToken.m 3 | // QiniuSDK 4 | // 5 | // Created by bailong on 15/6/7. 6 | // Copyright (c) 2015年 Qiniu. All rights reserved. 7 | // 8 | 9 | #import "QNUrlSafeBase64.h" 10 | #import "QNUpToken.h" 11 | 12 | @interface QNUpToken () 13 | 14 | - (instancetype)init:(NSDictionary *)policy token:(NSString *)token; 15 | 16 | @end 17 | 18 | @implementation QNUpToken 19 | 20 | - (instancetype)init:(NSDictionary *)policy token:(NSString *)token { 21 | if (self = [super init]) { 22 | _token = token; 23 | _access = [self getAccess]; 24 | _bucket = [self getBucket:policy]; 25 | _hasReturnUrl = (policy[@"returnUrl"] != nil); 26 | } 27 | 28 | return self; 29 | } 30 | 31 | - (NSString *)getAccess { 32 | 33 | NSRange range = [_token rangeOfString:@":" options:NSCaseInsensitiveSearch]; 34 | return [_token substringToIndex:range.location]; 35 | } 36 | 37 | - (NSString *)getBucket:(NSDictionary *)info { 38 | 39 | NSString *scope = [info objectForKey:@"scope"]; 40 | if (!scope) { 41 | return @""; 42 | } 43 | 44 | NSRange range = [scope rangeOfString:@":"]; 45 | if (range.location == NSNotFound) { 46 | return scope; 47 | } 48 | return [scope substringToIndex:range.location]; 49 | } 50 | 51 | + (instancetype)parse:(NSString *)token { 52 | if (token == nil) { 53 | return nil; 54 | } 55 | NSArray *array = [token componentsSeparatedByString:@":"]; 56 | if (array == nil || array.count != 3) { 57 | return nil; 58 | } 59 | 60 | NSData *data = [QNUrlSafeBase64 decodeString:array[2]]; 61 | NSError *tmp = nil; 62 | NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&tmp]; 63 | if (tmp != nil || dict[@"scope"] == nil || dict[@"deadline"] == nil) { 64 | return nil; 65 | } 66 | return [[QNUpToken alloc] init:dict token:token]; 67 | } 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Storage/QNUploadOption+Private.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNUploadOption+Private.h 3 | // QiniuSDK 4 | // 5 | // Created by bailong on 14/10/5. 6 | // Copyright (c) 2014年 Qiniu. All rights reserved. 7 | // 8 | 9 | #import "QNUploadOption.h" 10 | 11 | @interface QNUploadOption (Private) 12 | 13 | @property (nonatomic, getter=priv_isCancelled, readonly) BOOL cancelled; 14 | @end 15 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Storage/QNUploadOption.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNUploadOption.h 3 | // QiniuSDK 4 | // 5 | // Created by bailong on 14/10/4. 6 | // Copyright (c) 2014年 Qiniu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /** 12 | * 上传进度回调函数 13 | * 14 | * @param key 上传时指定的存储key 15 | * @param percent 进度百分比 16 | */ 17 | typedef void (^QNUpProgressHandler)(NSString *key, float percent); 18 | 19 | /** 20 | * 上传中途取消函数 21 | * 22 | * @return 如果想取消,返回True, 否则返回No 23 | */ 24 | typedef BOOL (^QNUpCancellationSignal)(void); 25 | 26 | /** 27 | * 可选参数集合,此类初始化后sdk上传使用时 不会对此进行改变;如果参数没有变化以及没有使用依赖,可以重复使用。 28 | */ 29 | @interface QNUploadOption : NSObject 30 | 31 | /** 32 | * 用于服务器上传回调通知的自定义参数,参数的key必须以x: 开头 33 | */ 34 | @property (copy, nonatomic, readonly) NSDictionary *params; 35 | 36 | /** 37 | * 指定文件的mime类型 38 | */ 39 | @property (copy, nonatomic, readonly) NSString *mimeType; 40 | 41 | /** 42 | * 是否进行crc校验 43 | */ 44 | @property (readonly) BOOL checkCrc; 45 | 46 | /** 47 | * 进度回调函数 48 | */ 49 | @property (copy, readonly) QNUpProgressHandler progressHandler; 50 | 51 | /** 52 | * 中途取消函数 53 | */ 54 | @property (copy, readonly) QNUpCancellationSignal cancellationSignal; 55 | 56 | /** 57 | * 可选参数的初始化方法 58 | * 59 | * @param mimeType mime类型 60 | * @param progress 进度函数 61 | * @param params 自定义服务器回调参数 62 | * @param check 是否进行crc检查 63 | * @param cancellation 中途取消函数 64 | * 65 | * @return 可选参数类实例 66 | */ 67 | - (instancetype)initWithMime:(NSString *)mimeType 68 | progressHandler:(QNUpProgressHandler)progress 69 | params:(NSDictionary *)params 70 | checkCrc:(BOOL)check 71 | cancellationSignal:(QNUpCancellationSignal)cancellation; 72 | 73 | - (instancetype)initWithProgessHandler:(QNUpProgressHandler)progress DEPRECATED_ATTRIBUTE; 74 | - (instancetype)initWithProgressHandler:(QNUpProgressHandler)progress; 75 | 76 | /** 77 | * 内部使用,默认的参数实例 78 | * 79 | * @return 可选参数类实例 80 | */ 81 | + (instancetype)defaultOptions; 82 | 83 | @end 84 | -------------------------------------------------------------------------------- /ImageHosting/External/QiniuSDK/Storage/QNUploadOption.m: -------------------------------------------------------------------------------- 1 | // 2 | // QNUploadOption.m 3 | // QiniuSDK 4 | // 5 | // Created by bailong on 14/10/4. 6 | // Copyright (c) 2014年 Qiniu. All rights reserved. 7 | // 8 | 9 | #import "QNUploadOption+Private.h" 10 | #import "QNUploadManager.h" 11 | 12 | static NSString *mime(NSString *mimeType) { 13 | if (mimeType == nil || [mimeType isEqualToString:@""]) { 14 | return @"application/octet-stream"; 15 | } 16 | return mimeType; 17 | } 18 | 19 | @implementation QNUploadOption 20 | 21 | + (NSDictionary *)filteParam:(NSDictionary *)params { 22 | NSMutableDictionary *ret = [NSMutableDictionary dictionary]; 23 | if (params == nil) { 24 | return ret; 25 | } 26 | 27 | [params enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj, BOOL *stop) { 28 | if ([key hasPrefix:@"x:"] && ![obj isEqualToString:@""]) { 29 | ret[key] = obj; 30 | } 31 | }]; 32 | 33 | return ret; 34 | } 35 | 36 | - (instancetype)initWithProgessHandler:(QNUpProgressHandler)progress { 37 | return [self initWithMime:nil progressHandler:progress params:nil checkCrc:NO cancellationSignal:nil]; 38 | } 39 | 40 | - (instancetype)initWithProgressHandler:(QNUpProgressHandler)progress { 41 | return [self initWithMime:nil progressHandler:progress params:nil checkCrc:NO cancellationSignal:nil]; 42 | } 43 | 44 | - (instancetype)initWithMime:(NSString *)mimeType 45 | progressHandler:(QNUpProgressHandler)progress 46 | params:(NSDictionary *)params 47 | checkCrc:(BOOL)check 48 | cancellationSignal:(QNUpCancellationSignal)cancel { 49 | if (self = [super init]) { 50 | _mimeType = mime(mimeType); 51 | _progressHandler = progress != nil ? progress : ^(NSString *key, float percent) { 52 | }; 53 | _params = [QNUploadOption filteParam:params]; 54 | _checkCrc = check; 55 | _cancellationSignal = cancel != nil ? cancel : ^BOOL() { 56 | return NO; 57 | }; 58 | } 59 | 60 | return self; 61 | } 62 | 63 | + (instancetype)defaultOptions { 64 | return [[QNUploadOption alloc] initWithMime:nil progressHandler:nil params:nil checkCrc:NO cancellationSignal:nil]; 65 | } 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /ImageHosting/External/UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.h: -------------------------------------------------------------------------------- 1 | // UIActivityIndicatorView+AFNetworking.h 2 | // Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import 23 | 24 | #import 25 | 26 | #if TARGET_OS_IOS || TARGET_OS_TV 27 | 28 | #import 29 | 30 | /** 31 | This category adds methods to the UIKit framework's `UIActivityIndicatorView` class. The methods in this category provide support for automatically starting and stopping animation depending on the loading state of a session task. 32 | */ 33 | @interface UIActivityIndicatorView (AFNetworking) 34 | 35 | ///---------------------------------- 36 | /// @name Animating for Session Tasks 37 | ///---------------------------------- 38 | 39 | /** 40 | Binds the animating state to the state of the specified task. 41 | 42 | @param task The task. If `nil`, automatic updating from any previously specified operation will be disabled. 43 | */ 44 | - (void)setAnimatingWithStateOfTask:(nullable NSURLSessionTask *)task; 45 | 46 | @end 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /ImageHosting/External/UIKit+AFNetworking/UIImage+AFNetworking.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+AFNetworking.h 3 | // 4 | // 5 | // Created by Paulo Ferreira on 08/07/15. 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | 25 | #if TARGET_OS_IOS || TARGET_OS_TV 26 | 27 | #import 28 | 29 | @interface UIImage (AFNetworking) 30 | 31 | + (UIImage*) safeImageWithData:(NSData*)data; 32 | 33 | @end 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /ImageHosting/External/UIKit+AFNetworking/UIKit+AFNetworking.h: -------------------------------------------------------------------------------- 1 | // UIKit+AFNetworking.h 2 | // 3 | // Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ ) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #if TARGET_OS_IOS || TARGET_OS_TV 24 | #import 25 | 26 | #ifndef _UIKIT_AFNETWORKING_ 27 | #define _UIKIT_AFNETWORKING_ 28 | 29 | #if TARGET_OS_IOS 30 | #import "AFAutoPurgingImageCache.h" 31 | #import "AFImageDownloader.h" 32 | #import "AFNetworkActivityIndicatorManager.h" 33 | #import "UIRefreshControl+AFNetworking.h" 34 | #import "UIWebView+AFNetworking.h" 35 | #endif 36 | 37 | #import "UIActivityIndicatorView+AFNetworking.h" 38 | #import "UIButton+AFNetworking.h" 39 | #import "UIImageView+AFNetworking.h" 40 | #import "UIProgressView+AFNetworking.h" 41 | #endif /* _UIKIT_AFNETWORKING_ */ 42 | #endif 43 | -------------------------------------------------------------------------------- /ImageHosting/External/UIKit+AFNetworking/UIProgressView+AFNetworking.h: -------------------------------------------------------------------------------- 1 | // UIProgressView+AFNetworking.h 2 | // Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import 23 | 24 | #import 25 | 26 | #if TARGET_OS_IOS || TARGET_OS_TV 27 | 28 | #import 29 | 30 | NS_ASSUME_NONNULL_BEGIN 31 | 32 | 33 | /** 34 | This category adds methods to the UIKit framework's `UIProgressView` class. The methods in this category provide support for binding the progress to the upload and download progress of a session task. 35 | */ 36 | @interface UIProgressView (AFNetworking) 37 | 38 | ///------------------------------------ 39 | /// @name Setting Session Task Progress 40 | ///------------------------------------ 41 | 42 | /** 43 | Binds the progress to the upload progress of the specified session task. 44 | 45 | @param task The session task. 46 | @param animated `YES` if the change should be animated, `NO` if the change should happen immediately. 47 | */ 48 | - (void)setProgressWithUploadProgressOfTask:(NSURLSessionUploadTask *)task 49 | animated:(BOOL)animated; 50 | 51 | /** 52 | Binds the progress to the download progress of the specified session task. 53 | 54 | @param task The session task. 55 | @param animated `YES` if the change should be animated, `NO` if the change should happen immediately. 56 | */ 57 | - (void)setProgressWithDownloadProgressOfTask:(NSURLSessionDownloadTask *)task 58 | animated:(BOOL)animated; 59 | 60 | @end 61 | 62 | NS_ASSUME_NONNULL_END 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /ImageHosting/External/UIKit+AFNetworking/UIRefreshControl+AFNetworking.h: -------------------------------------------------------------------------------- 1 | // UIRefreshControl+AFNetworking.m 2 | // 3 | // Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ ) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | 25 | #import 26 | 27 | #if TARGET_OS_IOS 28 | 29 | #import 30 | 31 | NS_ASSUME_NONNULL_BEGIN 32 | 33 | /** 34 | This category adds methods to the UIKit framework's `UIRefreshControl` class. The methods in this category provide support for automatically beginning and ending refreshing depending on the loading state of a session task. 35 | */ 36 | @interface UIRefreshControl (AFNetworking) 37 | 38 | ///----------------------------------- 39 | /// @name Refreshing for Session Tasks 40 | ///----------------------------------- 41 | 42 | /** 43 | Binds the refreshing state to the state of the specified task. 44 | 45 | @param task The task. If `nil`, automatic updating from any previously specified operation will be disabled. 46 | */ 47 | - (void)setRefreshingWithStateOfTask:(NSURLSessionTask *)task; 48 | 49 | @end 50 | 51 | NS_ASSUME_NONNULL_END 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /ImageHosting/ImageHosting-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // ImageHosting-Prefix.pch 3 | // ImageHosting 4 | // 5 | // Created by chars on 16/9/7. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #ifndef ImageHosting_Prefix_pch 10 | #define ImageHosting_Prefix_pch 11 | 12 | // Include any system framework and library headers here that should be included in all compilation units. 13 | // You will also need to set the Prefix Header build setting of one or more of your targets to reference this file. 14 | 15 | #import "IHCommon.h" 16 | 17 | #endif /* ImageHosting_Prefix_pch */ 18 | -------------------------------------------------------------------------------- /ImageHosting/ImageHosting.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | com.apple.security.network.client 10 | 11 | com.apple.security.print 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ImageHosting/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.1.3 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 10 25 | LSApplicationCategoryType 26 | public.app-category.utilities 27 | LSMinimumSystemVersion 28 | $(MACOSX_DEPLOYMENT_TARGET) 29 | LSUIElement 30 | 31 | NSAppTransportSecurity 32 | 33 | NSAllowsArbitraryLoads 34 | 35 | 36 | NSHumanReadableCopyright 37 | Copyright © 2016年 chars. All rights reserved. 38 | NSMainStoryboardFile 39 | Main 40 | NSPrincipalClass 41 | NSApplication 42 | 43 | 44 | -------------------------------------------------------------------------------- /ImageHosting/Model/IHAccount.h: -------------------------------------------------------------------------------- 1 | // 2 | // IHAccount.h 3 | // ImageHosting 4 | // 5 | // Created by chars on 16/8/19. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSUInteger, IHAccountType) { 12 | IHAccountTypeNone = 0, 13 | IHAccountTypeQiniu 14 | }; 15 | 16 | @interface IHAccount : NSObject 17 | 18 | @property (assign) IHAccountType accountType; 19 | 20 | /** 七牛云账号专用 */ 21 | @property (copy) NSString *ak; 22 | @property (copy) NSString *sk; 23 | @property (copy) NSString *bucketName; 24 | @property (copy) NSString *region; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /ImageHosting/Model/IHAccount.m: -------------------------------------------------------------------------------- 1 | // 2 | // IHAccount.m 3 | // ImageHosting 4 | // 5 | // Created by chars on 16/8/19. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import "IHAccount.h" 10 | 11 | #define ACCOUNT_TYPE_KEY @"account_type" 12 | #define AK_KEY @"ak" 13 | #define SK_KEY @"sk" 14 | #define BUCKET_NAME_KEY @"bucket_name" 15 | #define REGION_KEY @"region" 16 | 17 | @implementation IHAccount 18 | 19 | #pragma mark - 编码 对对象属性进行编码的处理 20 | 21 | - (void)encodeWithCoder:(NSCoder *)aCoder 22 | { 23 | [aCoder encodeInteger:_accountType forKey:ACCOUNT_TYPE_KEY]; 24 | [aCoder encodeObject:_ak forKey:AK_KEY]; 25 | [aCoder encodeObject:_sk forKey:SK_KEY]; 26 | [aCoder encodeObject:_bucketName forKey:BUCKET_NAME_KEY]; 27 | [aCoder encodeObject:_region forKey:REGION_KEY]; 28 | } 29 | 30 | #pragma mark - 解码 解码归档数据来初始化对象 31 | 32 | - (id)initWithCoder:(NSCoder *)aDecoder 33 | { 34 | if (self = [super init]) { 35 | _accountType = [aDecoder decodeIntegerForKey:ACCOUNT_TYPE_KEY]; 36 | _ak = [aDecoder decodeObjectForKey:AK_KEY]; 37 | _sk = [aDecoder decodeObjectForKey:SK_KEY]; 38 | _bucketName = [aDecoder decodeObjectForKey:BUCKET_NAME_KEY]; 39 | _region = [aDecoder decodeObjectForKey:REGION_KEY]; 40 | } 41 | return self; 42 | } 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /ImageHosting/Model/IHCache.h: -------------------------------------------------------------------------------- 1 | // 2 | // IHCache.h 3 | // ImageHosting 4 | // 5 | // Created by dengw on 16/8/20. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface IHCache : NSCache 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ImageHosting/Model/IHCache.m: -------------------------------------------------------------------------------- 1 | // 2 | // IHCache.m 3 | // ImageHosting 4 | // 5 | // Created by dengw on 16/8/20. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import "IHCache.h" 10 | 11 | @implementation IHCache 12 | 13 | - (id)init { 14 | self = [super init]; 15 | if (self) { 16 | 17 | } 18 | return self; 19 | } 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /ImageHosting/Model/IHGeneral.h: -------------------------------------------------------------------------------- 1 | // 2 | // IHGeneral.h 3 | // ImageHosting 4 | // 5 | // Created by chars on 16/9/6. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface IHGeneral : NSObject 12 | 13 | @property (copy) NSString *userNotification; 14 | @property (copy) NSString *launchStartUp; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /ImageHosting/Model/IHGeneral.m: -------------------------------------------------------------------------------- 1 | // 2 | // IHGeneral.m 3 | // ImageHosting 4 | // 5 | // Created by chars on 16/9/6. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import "IHGeneral.h" 10 | 11 | #define USER_NOTIFICATION_KEY @"user_notification" 12 | #define LAUNCH_START_UP_KEY @"launch_startup" 13 | 14 | @implementation IHGeneral 15 | 16 | #pragma mark - 编码 对对象属性进行编码的处理 17 | 18 | - (void)encodeWithCoder:(NSCoder *)aCoder 19 | { 20 | [aCoder encodeObject:_userNotification forKey:USER_NOTIFICATION_KEY]; 21 | [aCoder encodeObject:_launchStartUp forKey:LAUNCH_START_UP_KEY]; 22 | } 23 | 24 | #pragma mark - 解码 解码归档数据来初始化对象 25 | 26 | - (id)initWithCoder:(NSCoder *)aDecoder 27 | { 28 | if (self = [super init]) { 29 | _userNotification = [aDecoder decodeObjectForKey:USER_NOTIFICATION_KEY]; 30 | _launchStartUp = [aDecoder decodeObjectForKey:LAUNCH_START_UP_KEY]; 31 | } 32 | return self; 33 | } 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /ImageHosting/Model/const.h: -------------------------------------------------------------------------------- 1 | // 2 | // const.h 3 | // ImageHosting 4 | // 5 | // Created by dengw on 16/8/20. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #ifndef const_h 10 | #define const_h 11 | 12 | typedef NS_ENUM(NSUInteger, IHAlertStyle) { 13 | IHAlertStyleNone, 14 | IHAlertStyleWarning, 15 | IHAlertStyleInformational, 16 | IHAlertStyleCritical 17 | }; 18 | 19 | #define AK_KEY @"ak" 20 | #define SK_KEY @"sk" 21 | #define BUCKET_KEY @"bucket" 22 | #define TYPE_KEY @"type" 23 | #define REGION_KEY @"region" 24 | 25 | #define REGION_EAST_CHINA @"east_china" 26 | #define REGION_NORTH_CHINA @"north_china" 27 | 28 | #define CURRENT_ACCOUNT_KEY @"current_account" 29 | #define ACCOUNTS_KEY @"accounts" 30 | 31 | #define SYSTEM_NOTIFICATION_KEY @"system_notification" 32 | 33 | #endif /* const_h */ 34 | -------------------------------------------------------------------------------- /ImageHosting/Util/IHAccountManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // IHAccountManager.h 3 | // ImageHosting 4 | // 5 | // Created by dengw on 16/8/19. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import "IHPreferencesManager.h" 10 | 11 | @class IHAccount; 12 | 13 | @interface IHAccountManager : IHPreferencesManager 14 | 15 | + (instancetype)sharedManager; 16 | 17 | - (IHAccount *)currentAccount; 18 | 19 | - (BOOL)archive:(id)object key:(NSString *)key; 20 | 21 | - (id)unarchiveForKey:(NSString *)key; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /ImageHosting/Util/IHAccountManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // IHAccountManager.m 3 | // ImageHosting 4 | // 5 | // Created by dengw on 16/8/19. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import "IHAccountManager.h" 10 | #import "IHAccount.h" 11 | #import "NSString+IHAddition.h" 12 | #import "const.h" 13 | #import "IHCache.h" 14 | 15 | #define ACCOUNT_FILE_NAME @"IHAccount.db" 16 | 17 | @interface IHAccountManager () 18 | 19 | @property (strong) IHCache *cache; 20 | 21 | @end 22 | 23 | @implementation IHAccountManager 24 | 25 | + (instancetype)sharedManager 26 | { 27 | static IHAccountManager *sharedManager = nil; 28 | static dispatch_once_t once_token; 29 | dispatch_once(&once_token, ^{ 30 | sharedManager = [[IHAccountManager alloc] init]; 31 | }); 32 | return sharedManager; 33 | } 34 | 35 | - (BOOL)archive:(id)object key:(NSString *)key 36 | { 37 | if (!object || !key) { 38 | return NO; 39 | } 40 | 41 | NSString *filePath = [self pathOfPreferences:ACCOUNT_FILE_NAME]; 42 | NSMutableData *archiverData = [NSMutableData data]; 43 | NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:archiverData]; 44 | NSData *unarchiverData = [NSData dataWithContentsOfFile:filePath]; 45 | NSKeyedUnarchiver *unachiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:unarchiverData]; 46 | 47 | if ([object isKindOfClass:[IHAccount class]]) { 48 | NSMutableArray *accounts = [unachiver decodeObjectForKey:key]; 49 | if (accounts) { 50 | BOOL replace = NO; 51 | for (IHAccount *cur in accounts) { 52 | if (cur.accountType == ((IHAccount *)object).accountType) { 53 | cur.ak = ((IHAccount *)object).ak; 54 | cur.sk = ((IHAccount *)object).sk; 55 | cur.bucketName = ((IHAccount *)object).bucketName; 56 | cur.region = ((IHAccount *)object).region; 57 | replace = YES; 58 | break; 59 | } 60 | } 61 | 62 | if (!replace) { 63 | [accounts addObject:object]; 64 | } 65 | } else { 66 | accounts = [NSMutableArray arrayWithObject:object]; 67 | } 68 | 69 | [archiver encodeObject:accounts forKey:key]; 70 | } else { 71 | [archiver encodeObject:object forKey:key]; 72 | } 73 | 74 | [archiver finishEncoding]; 75 | 76 | return [archiverData writeToFile:filePath atomically:YES]; 77 | 78 | } 79 | 80 | - (id)unarchiveForKey:(NSString *)key 81 | { 82 | NSString *filePath = [self pathOfPreferences:ACCOUNT_FILE_NAME]; 83 | NSData *unarchiverData = [NSData dataWithContentsOfFile:filePath]; 84 | NSKeyedUnarchiver *unachiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:unarchiverData]; 85 | 86 | return [unachiver decodeObjectForKey:key]; 87 | } 88 | 89 | - (IHAccount *)currentAccount 90 | { 91 | IHAccount *currentAccount = nil; 92 | if (self.cache) { 93 | currentAccount = [self.cache objectForKey:CURRENT_ACCOUNT_KEY]; 94 | } 95 | 96 | if (!currentAccount) { 97 | NSMutableArray *accounts = [self unarchiveForKey:ACCOUNTS_KEY]; 98 | currentAccount = [accounts lastObject]; 99 | 100 | [self.cache setObject:currentAccount forKey:CURRENT_ACCOUNT_KEY]; 101 | } 102 | IHLog(@"path of preferences file:%@ currentAccount:%@", [self pathOfPreferences:ACCOUNT_FILE_NAME], currentAccount); 103 | return currentAccount; 104 | } 105 | 106 | @end 107 | -------------------------------------------------------------------------------- /ImageHosting/Util/IHGeneralManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // IHGeneralManager.h 3 | // ImageHosting 4 | // 5 | // Created by dengw on 16/8/24. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import "IHPreferencesManager.h" 10 | 11 | @interface IHGeneralManager : IHPreferencesManager 12 | 13 | + (instancetype)sharedManager; 14 | 15 | - (BOOL)archive:(id)object key:(NSString *)key; 16 | 17 | - (id)unarchiveForKey:(NSString *)key; 18 | 19 | - (void)startupAppWhenLogin:(BOOL)startup; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /ImageHosting/Util/IHGeneralManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // IHGeneralManager.m 3 | // ImageHosting 4 | // 5 | // Created by dengw on 16/8/24. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import "IHGeneralManager.h" 10 | #import "const.h" 11 | #import 12 | #import 13 | 14 | #define GENERAL_FILE_NAME @"IHGeneral.db" 15 | 16 | @interface IHGeneralManager () 17 | 18 | @end 19 | 20 | @implementation IHGeneralManager 21 | 22 | + (instancetype)sharedManager 23 | { 24 | static IHGeneralManager *sharedManager = nil; 25 | static dispatch_once_t once_token; 26 | dispatch_once(&once_token, ^{ 27 | sharedManager = [[IHGeneralManager alloc] init]; 28 | }); 29 | return sharedManager; 30 | } 31 | 32 | - (instancetype)init 33 | { 34 | self = [super init]; 35 | if (self) { 36 | } 37 | return self; 38 | } 39 | 40 | - (BOOL)archive:(id)object key:(NSString *)key 41 | { 42 | if (!object || !key) { 43 | return NO; 44 | } 45 | 46 | NSString *filePath = [self pathOfPreferences:GENERAL_FILE_NAME]; 47 | NSMutableData *archiverData = [NSMutableData data]; 48 | NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:archiverData]; 49 | 50 | [archiver encodeObject:object forKey:key]; 51 | 52 | [archiver finishEncoding]; 53 | 54 | return [archiverData writeToFile:filePath atomically:YES]; 55 | 56 | } 57 | 58 | - (id)unarchiveForKey:(NSString *)key 59 | { 60 | NSString *filePath = [self pathOfPreferences:GENERAL_FILE_NAME]; 61 | NSData *unarchiverData = [NSData dataWithContentsOfFile:filePath]; 62 | NSKeyedUnarchiver *unachiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:unarchiverData]; 63 | 64 | return [unachiver decodeObjectForKey:key]; 65 | } 66 | 67 | - (void)startupAppWhenLogin:(BOOL)startup 68 | { 69 | SMLoginItemSetEnabled((CFStringRef)@"cn.zaker.chars.ImageHostingHelper", startup); 70 | BOOL startedAtLogin = NO; 71 | NSArray *apps = [NSWorkspace sharedWorkspace].runningApplications; 72 | for (NSRunningApplication *app in apps) { 73 | if ([app.bundleIdentifier isEqualToString:@"cn.zaker.chars.ImageHostingHelper"]) { 74 | startedAtLogin = YES; 75 | break; 76 | } 77 | } 78 | if (startedAtLogin) { 79 | [[NSDistributedNotificationCenter defaultCenter] postNotificationName:@"killIHhelper" object:[NSBundle mainBundle].bundleIdentifier]; 80 | } 81 | } 82 | 83 | @end 84 | -------------------------------------------------------------------------------- /ImageHosting/Util/IHPreferencesManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // IHPreferencesManager.h 3 | // ImageHosting 4 | // 5 | // Created by dengw on 16/8/24. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface IHPreferencesManager : NSObject 12 | 13 | - (NSString *)pathOfPreferences:(NSString *)fileName; 14 | 15 | - (BOOL)fileExistAtPath:(NSString *)path; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /ImageHosting/Util/IHPreferencesManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // IHPreferencesManager.m 3 | // ImageHosting 4 | // 5 | // Created by dengw on 16/8/24. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import "IHPreferencesManager.h" 10 | 11 | @implementation IHPreferencesManager 12 | 13 | + (instancetype)sharedManager 14 | { 15 | static IHPreferencesManager *sharedManager = nil; 16 | static dispatch_once_t once_token; 17 | dispatch_once(&once_token, ^{ 18 | sharedManager = [[IHPreferencesManager alloc] init]; 19 | }); 20 | return sharedManager; 21 | } 22 | 23 | - (NSString *)pathLibraryPreferences 24 | { 25 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES); 26 | NSString *libraryDirectory = [paths lastObject]; 27 | libraryDirectory = [libraryDirectory stringByAppendingString:@"/Preferences"]; 28 | return libraryDirectory; 29 | } 30 | 31 | - (NSString *)pathOfPreferences:(NSString *)fileName 32 | { 33 | NSString *path = [self pathLibraryPreferences]; 34 | NSString *append = [NSString stringWithFormat:@"/%@", fileName]; 35 | path = [path stringByAppendingString:append]; 36 | return path; 37 | } 38 | 39 | - (BOOL)fileExistAtPath:(NSString *)path 40 | { 41 | BOOL isExist = NO; 42 | isExist = [[NSFileManager defaultManager] fileExistsAtPath:path]; 43 | return isExist; 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /ImageHosting/Util/IHQiniuTokenManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // IHQiniuTokenManager.h 3 | // ImageHosting 4 | // 5 | // Created by dengw on 16/8/19. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class IHAccount; 12 | 13 | @interface IHQiniuTokenManager : NSObject 14 | 15 | + (instancetype) sharedManager; 16 | 17 | - (NSString *)generateUploadTokenForAccount:(IHAccount *)account; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /ImageHosting/Util/IHQiniuTokenManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // IHQiniuTokenManager.m 3 | // ImageHosting 4 | // 5 | // Created by dengw on 16/8/19. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import "IHQiniuTokenManager.h" 10 | #import "IHAccount.h" 11 | #import "IHCache.h" 12 | #import "const.h" 13 | #include 14 | #import "JSONKit.h" 15 | #import "QN_GTM_Base64.h" 16 | 17 | @interface IHQiniuTokenManager () 18 | 19 | @property (strong) IHCache *cache; 20 | @property (assign) NSUInteger expires; 21 | 22 | @end 23 | 24 | @implementation IHQiniuTokenManager 25 | 26 | + (instancetype)sharedManager 27 | { 28 | static IHQiniuTokenManager *sharedManager = nil; 29 | static dispatch_once_t once_token; 30 | dispatch_once(&once_token, ^{ 31 | sharedManager = [[IHQiniuTokenManager alloc] init]; 32 | }); 33 | return sharedManager; 34 | } 35 | 36 | - (NSString *)generateUploadTokenForAccount:(IHAccount *)account 37 | { 38 | if (!account) { 39 | return nil; 40 | } 41 | 42 | const char *secretKeyStr = [account.sk UTF8String]; 43 | NSString *policy = [self marshal:account.bucketName]; 44 | NSData *policyData = [policy dataUsingEncoding:NSUTF8StringEncoding]; 45 | NSString *encodedPolicy = [QN_GTM_Base64 stringByWebSafeEncodingData:policyData padded:TRUE]; 46 | const char *encodedPolicyStr = [encodedPolicy cStringUsingEncoding:NSUTF8StringEncoding]; 47 | 48 | char digestStr[CC_SHA1_DIGEST_LENGTH]; 49 | bzero(digestStr, 0); 50 | 51 | CCHmac(kCCHmacAlgSHA1, secretKeyStr, strlen(secretKeyStr), encodedPolicyStr, strlen(encodedPolicyStr), digestStr); 52 | 53 | NSString *encodedDigest = [QN_GTM_Base64 stringByWebSafeEncodingBytes:digestStr length:CC_SHA1_DIGEST_LENGTH padded:TRUE]; 54 | 55 | NSString *token = [NSString stringWithFormat:@"%@:%@:%@", account.ak, encodedDigest, encodedPolicy]; 56 | 57 | return token; 58 | } 59 | 60 | - (NSString *)marshal:(NSString *)bucketName 61 | { 62 | if (!bucketName) { 63 | return nil; 64 | } 65 | 66 | time_t deadline; 67 | time(&deadline);//返回当前系统时间 68 | 69 | deadline += (self.expires > 0) ? self.expires : 3600; // +3600秒,即默认token保存1小时. 70 | 71 | NSNumber *deadlineNumber = [NSNumber numberWithLongLong:deadline]; 72 | NSMutableDictionary *dict = [NSMutableDictionary dictionary]; 73 | [dict setObject:bucketName forKey:@"scope"]; 74 | [dict setObject:deadlineNumber forKey:@"deadline"]; 75 | 76 | NSString *json = [dict JSONString]; 77 | 78 | return json; 79 | } 80 | 81 | @end 82 | -------------------------------------------------------------------------------- /ImageHosting/Util/IHQiniuUploadManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // IHQiniuUploadManager.h 3 | // ImageHosting 4 | // 5 | // Created by dengw on 16/8/21. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class IHAccount; 12 | 13 | typedef void(^IHQiniuCompletionHandler)(NSString *key, NSDictionary *resp); 14 | typedef void(^IHQiniuProgressHandler)(NSString *key, CGFloat percent); 15 | 16 | @interface IHQiniuUploadManager : NSObject 17 | 18 | + (instancetype) sharedManager; 19 | 20 | - (void)uploadQiniuForAccount:(IHAccount *)account key:(NSString *)key filePath:(NSString *)path completion:(IHQiniuCompletionHandler)completion progress:(IHQiniuProgressHandler)progress; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /ImageHosting/Util/IHQiniuUploadManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // IHQiniuUploadManager.m 3 | // ImageHosting 4 | // 5 | // Created by dengw on 16/8/21. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import "IHQiniuUploadManager.h" 10 | #import "const.h" 11 | #import "IHAccount.h" 12 | #import "IHQiniuTokenManager.h" 13 | #import "QiniuSDK.h" 14 | 15 | @interface IHQiniuUploadManager () 16 | 17 | @end 18 | 19 | @implementation IHQiniuUploadManager 20 | 21 | + (instancetype)sharedManager 22 | { 23 | static IHQiniuUploadManager *sharedManager = nil; 24 | static dispatch_once_t once_token; 25 | dispatch_once(&once_token, ^{ 26 | sharedManager = [[IHQiniuUploadManager alloc] init]; 27 | }); 28 | return sharedManager; 29 | } 30 | 31 | - (void)uploadQiniuForAccount:(IHAccount *)account key:(NSString *)key filePath:(NSString *)path completion:(IHQiniuCompletionHandler)completion progress:(IHQiniuProgressHandler)progress 32 | { 33 | NSString *token = [[IHQiniuTokenManager sharedManager] generateUploadTokenForAccount:account]; 34 | QNUploadManager *manager = [[QNUploadManager alloc] init]; 35 | 36 | QNUploadOption *option = [[QNUploadOption alloc] initWithProgressHandler:^(NSString *key, float percent) { 37 | if (progress) { 38 | progress(key, percent); 39 | } 40 | }]; 41 | [manager putFile:path key:key token:token complete:^(QNResponseInfo *info, NSString *key, NSDictionary *resp) { 42 | IHLog(@"info:%@", info); 43 | if (completion) { 44 | completion(key, resp); 45 | } 46 | } option:option]; 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /ImageHosting/View/IHProgressIndicator.h: -------------------------------------------------------------------------------- 1 | // 2 | // IHProgressIndicator.h 3 | // ImageHosting 4 | // 5 | // Created by chars on 16/9/2. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface IHProgressIndicator : NSProgressIndicator 12 | 13 | @property (nonatomic, assign) NSInteger percent; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ImageHosting/View/IHProgressIndicator.m: -------------------------------------------------------------------------------- 1 | // 2 | // IHProgressIndicator.m 3 | // ImageHosting 4 | // 5 | // Created by chars on 16/9/2. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import "IHProgressIndicator.h" 10 | #import "NSColor+IHAddition.h" 11 | 12 | @implementation IHProgressIndicator 13 | 14 | - (void)setPercent:(NSInteger)percent 15 | { 16 | if (_percent != percent) { 17 | _percent = percent; 18 | } 19 | 20 | [self setNeedsDisplay:YES]; 21 | } 22 | 23 | - (void)drawRect:(NSRect)dirtyRect { 24 | [super drawRect:dirtyRect]; 25 | 26 | NSRect fillingRect = dirtyRect; 27 | fillingRect.size.width = dirtyRect.size.width * _percent / 100; 28 | NSColor *indicatorColor; 29 | 30 | if (_percent >= 99) { 31 | indicatorColor = [NSColor ih_colorWithRGBString:@"#24A061"]; 32 | } else if (_percent > 60) { 33 | indicatorColor = [NSColor ih_colorWithRGBString:@"#C28F30"]; 34 | } else { 35 | indicatorColor = [NSColor ih_colorWithRGBString:@"#289ECE"]; 36 | } 37 | [indicatorColor set]; 38 | NSRectFill(fillingRect); 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /ImageHosting/View/IHTableView.h: -------------------------------------------------------------------------------- 1 | // 2 | // IHTableView.h 3 | // ImageHosting 4 | // 5 | // Created by chars on 16/9/6. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class IHTableView; 12 | 13 | @protocol IHTableViewDelegate 14 | 15 | @optional 16 | - (void)ihTableView:(IHTableView *)tableView didFinishedDragWithFile:(NSString *)path; 17 | - (void)ihTableView:(IHTableView *)tableView didClickedClearAllUpload:(NSMenuItem *)item; 18 | 19 | @end 20 | 21 | @interface IHTableView : NSTableView 22 | 23 | @property (weak) id ihDelegate; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /ImageHosting/View/IHUploadFileCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // IHUploadFileCell.h 3 | // ImageHosting 4 | // 5 | // Created by chars on 16/9/1. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface IHUploadFileCell : NSTableCellView 12 | 13 | @property (nonatomic, copy) NSString *title; 14 | @property (nonatomic, copy) NSString *key; 15 | @property (nonatomic, strong) NSImage *image; 16 | @property (nonatomic, copy) NSString *progress; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /ImageHosting/View/IHUploadFileCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // IHUploadFileCell.m 3 | // ImageHosting 4 | // 5 | // Created by chars on 16/9/1. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import "IHUploadFileCell.h" 10 | #import "IHProgressIndicator.h" 11 | 12 | #define PERCENT_THROSHED 100 13 | 14 | #define WIDTH 380 15 | 16 | #define TITLE_WIDTH 300 17 | #define TITLE_HEIGHT 20 18 | 19 | #define PROGRESS_BAR_INDICATOR_WIDTH 300 20 | #define PROGRESS_BAR_INDICATOR_HEIGHT 3 21 | 22 | #define IMAGE_WIDTH 20 23 | #define IMAGE_HEIGHT 20 24 | 25 | @interface IHUploadFileCell () 26 | 27 | @property (strong) NSTextField *titleTextField; 28 | @property (strong) IHProgressIndicator *progressBarIndicator; 29 | @property (strong) NSImageView *hintImageView; 30 | 31 | @end 32 | 33 | @implementation IHUploadFileCell 34 | 35 | - (void)awakeFromNib 36 | { 37 | [self initSubViews]; 38 | } 39 | 40 | - (void)initSubViews 41 | { 42 | _progressBarIndicator = [[IHProgressIndicator alloc] initWithFrame:NSMakeRect(25, 3, PROGRESS_BAR_INDICATOR_WIDTH, PROGRESS_BAR_INDICATOR_HEIGHT)]; 43 | _progressBarIndicator.style = NSProgressIndicatorBarStyle; 44 | _progressBarIndicator.indeterminate = NO; 45 | _progressBarIndicator.minValue = 0; 46 | _progressBarIndicator.maxValue = 100; 47 | [self addSubview:_progressBarIndicator]; 48 | 49 | _titleTextField = [[NSTextField alloc] initWithFrame:NSMakeRect(27, 6, TITLE_WIDTH, TITLE_HEIGHT)]; 50 | _titleTextField.editable = NO; 51 | _titleTextField.lineBreakMode = NSLineBreakByTruncatingTail; 52 | _titleTextField.bordered = NO; 53 | _titleTextField.alignment = NSTextAlignmentLeft; 54 | _titleTextField.backgroundColor = [NSColor clearColor]; 55 | _titleTextField.textColor = [NSColor darkGrayColor]; 56 | [self addSubview:_titleTextField]; 57 | 58 | _hintImageView = [[NSImageView alloc] initWithFrame:NSMakeRect(334, 6, IMAGE_WIDTH, IMAGE_HEIGHT)]; 59 | _hintImageView.image = [NSImage imageNamed:@"success"]; 60 | [self addSubview:_hintImageView]; 61 | } 62 | 63 | - (void)setTitle:(NSString *)title 64 | { 65 | if (!title) { 66 | return; 67 | } 68 | 69 | if (_title != title) { 70 | _title = title; 71 | } 72 | 73 | self.titleTextField.stringValue = title; 74 | } 75 | 76 | - (void)setProgress:(NSString *)progress 77 | { 78 | if (_progress != progress) { 79 | _progress = progress; 80 | } 81 | NSInteger percent = [progress integerValue]; 82 | 83 | self.progressBarIndicator.percent = percent; 84 | } 85 | 86 | - (void)setImage:(NSImage *)image 87 | { 88 | if (_image != image) { 89 | _image = image; 90 | } 91 | 92 | self.hintImageView.image = image; 93 | } 94 | 95 | - (void)drawRect:(NSRect)dirtyRect 96 | { 97 | [super drawRect:dirtyRect]; 98 | 99 | CGContextRef ctx = [[NSGraphicsContext currentContext] graphicsPort]; 100 | 101 | NSColor *lineColor = [NSColor grayColor]; 102 | 103 | CGRect lineRect = CGRectMake(5, 0, WIDTH - 5 * 2, 1); 104 | CGContextSaveGState(ctx); 105 | CGContextSetFillColorWithColor(ctx, lineColor.CGColor); 106 | CGContextFillRect(ctx, lineRect); 107 | CGContextRestoreGState(ctx); 108 | } 109 | 110 | @end 111 | -------------------------------------------------------------------------------- /ImageHosting/View/IHUploadFileCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /ImageHosting/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ImageHosting 4 | // 5 | // Created by chars on 16/8/16. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, const char * argv[]) { 12 | return NSApplicationMain(argc, argv); 13 | } 14 | -------------------------------------------------------------------------------- /ImageHostingHelper/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // ImageHostingHelper 4 | // 5 | // Created by chars on 16/9/7. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : NSObject 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /ImageHostingHelper/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // ImageHostingHelper 4 | // 5 | // Created by chars on 16/9/7. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | - (void)dealloc 18 | { 19 | [[NSDistributedNotificationCenter defaultCenter] removeObserver:self]; 20 | } 21 | 22 | - (void)terminate 23 | { 24 | [NSApp terminate:nil]; 25 | } 26 | 27 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { 28 | // Insert code here to initialize your application 29 | NSString *mainAppId = @"cn.zaker.chars.ImageHosting"; 30 | NSArray *apps = [NSWorkspace sharedWorkspace].runningApplications; 31 | BOOL alreadyRunning = NO; 32 | for (NSRunningApplication *app in apps) { 33 | if ([app.bundleIdentifier isEqualToString:mainAppId]) { 34 | alreadyRunning = YES; 35 | break; 36 | } 37 | } 38 | 39 | if (!alreadyRunning) { 40 | [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(terminate) name:@"killIHhelper" object:mainAppId]; 41 | NSString *path = [NSBundle mainBundle].bundlePath; 42 | NSMutableArray *components = [[path pathComponents] mutableCopy]; 43 | [components removeLastObject]; 44 | [components removeLastObject]; 45 | [components removeLastObject]; 46 | [components addObject:@"MacOS"]; 47 | [components addObject:@"ImageHosting"]; 48 | 49 | NSString *newPath = [NSString pathWithComponents:components]; 50 | [[NSWorkspace sharedWorkspace] launchApplication:newPath]; 51 | } else { 52 | [self terminate]; 53 | } 54 | } 55 | 56 | - (void)applicationWillTerminate:(NSNotification *)aNotification { 57 | // Insert code here to tear down your application 58 | } 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /ImageHostingHelper/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "size" : "512x512", 51 | "scale" : "2x" 52 | } 53 | ], 54 | "info" : { 55 | "version" : 1, 56 | "author" : "xcode" 57 | } 58 | } -------------------------------------------------------------------------------- /ImageHostingHelper/ImageHostingHelper.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.network.client 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ImageHostingHelper/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSApplicationCategoryType 26 | public.app-category.utilities 27 | LSBackgroundOnly 28 | 29 | LSMinimumSystemVersion 30 | $(MACOSX_DEPLOYMENT_TARGET) 31 | NSHumanReadableCopyright 32 | Copyright © 2016年 chars. All rights reserved. 33 | NSMainStoryboardFile 34 | Main 35 | NSPrincipalClass 36 | NSApplication 37 | 38 | 39 | -------------------------------------------------------------------------------- /ImageHostingHelper/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // ImageHostingHelper 4 | // 5 | // Created by chars on 16/9/7. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : NSViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /ImageHostingHelper/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // ImageHostingHelper 4 | // 5 | // Created by chars on 16/9/7. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | @implementation ViewController 12 | 13 | - (void)viewDidLoad { 14 | [super viewDidLoad]; 15 | 16 | // Do any additional setup after loading the view. 17 | } 18 | 19 | - (void)setRepresentedObject:(id)representedObject { 20 | [super setRepresentedObject:representedObject]; 21 | 22 | // Update the view, if already loaded. 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /ImageHostingHelper/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ImageHostingHelper 4 | // 5 | // Created by chars on 16/9/7. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, const char * argv[]) { 12 | return NSApplicationMain(argc, argv); 13 | } 14 | -------------------------------------------------------------------------------- /ImageHostingHelperTests/ImageHostingHelperTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ImageHostingHelperTests.m 3 | // ImageHostingHelperTests 4 | // 5 | // Created by chars on 16/9/7. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ImageHostingHelperTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation ImageHostingHelperTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /ImageHostingHelperTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /ImageHostingHelperUITests/ImageHostingHelperUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ImageHostingHelperUITests.m 3 | // ImageHostingHelperUITests 4 | // 5 | // Created by chars on 16/9/7. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ImageHostingHelperUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation ImageHostingHelperUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /ImageHostingHelperUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /ImageHostingTests/ImageHostingTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ImageHostingTests.m 3 | // ImageHostingTests 4 | // 5 | // Created by chars on 16/8/16. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ImageHostingTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation ImageHostingTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /ImageHostingTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /ImageHostingUITests/ImageHostingUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ImageHostingUITests.m 3 | // ImageHostingUITests 4 | // 5 | // Created by chars on 16/8/16. 6 | // Copyright © 2016年 chars. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ImageHostingUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation ImageHostingUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /ImageHostingUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Chars 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ImageHosting 2 | [![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat 3 | )](http://mit-license.org) 4 | [![Platform](https://img.shields.io/badge/platform-osx-lightgrey.svg?style=flat 5 | )](https://developer.apple.com/resources/) 6 | ![Language](http://img.shields.io/badge/language-objectivec-orange.svg?style=flat 7 | ) 8 | 9 | 10 | # ImageHosting for Mac Usage 11 | 12 | 博主在转战iOS开发以来,一直坚持撰写自己的技术博客。使用Github Pages + Hexo 搭建了属于自己的空间。具体搭建方法可以参考[《手把手教 GitHub + Hexo 搭建博客》](http://charsdavy.github.io/2016/05/31/build-blog-by-hexo/) 。 然而,博客中有很多时候需要使用图片说明,俗话说“一图胜千言”,博主使用 七牛云 做图床,然每次编写博客时需要打开Web版上传图片,甚是繁琐。故此,博主自己编写了一个自己的图片上传软件。 13 | 14 | ![](http://o88e8any8.bkt.clouddn.com/ImageHosting-use-introduction-launchpad.png) 15 | 16 | 软件下载地址:[ImageHosting for Mac](https://github.com/charsdavy/ImageHosting/releases) 17 | 18 | ## 安装 19 | 20 | ![](http://o88e8any8.bkt.clouddn.com/imagehosting-use-introduction-8.png) 21 | 22 | 遇到以上问题,处理方法如下: 23 | 24 | 将权限改为“任何来源”即可 25 | 26 | ![](http://o88e8any8.bkt.clouddn.com/imagehosting-use-introduction-9.png) 27 | 28 | ## 软件菜单栏 29 | 30 | ![](http://o88e8any8.bkt.clouddn.com/ImageHosting-use-introduction-stateMenu.png) 31 | 32 | ## 打开软件配置,添加账户信息 33 | 34 | ![](http://o88e8any8.bkt.clouddn.com/ImageHosting-use-introduction-account.png) 35 | 36 | ## 打开文件选择页,选择文件 37 | 38 | ## 上传文件 39 | 40 | ![](http://o88e8any8.bkt.clouddn.com/ImageHosting-use-introduction-upload-main.png) 41 | 42 | ## 上传进度提示 43 | 44 | ![](http://o88e8any8.bkt.clouddn.com/ImageHosting-use-introduction-upload_1.png) 45 | 46 | ![](http://o88e8any8.bkt.clouddn.com/ImageHosting-use-introduction-upload_2.png) 47 | 48 | ![](http://o88e8any8.bkt.clouddn.com/ImageHosting-use-introduction-upload_3.png) 49 | 50 | ## 上传完成 51 | 52 | ![](http://o88e8any8.bkt.clouddn.com/ImageHosting-use-introduction-upload-success-main.png) 53 | 54 | ## 操作提示 55 | 56 | ### 未添加账户信息提示 57 | 58 | ![](http://o88e8any8.bkt.clouddn.com/ImageHosting-use-introduction-no-account.png) 59 | 60 | ### 未选择上传文件提示 61 | 62 | ![](http://o88e8any8.bkt.clouddn.com/ImageHosting-use-introduction-no-select.png) 63 | 64 | ### 上传文件成功提示 65 | 66 | ![](http://o88e8any8.bkt.clouddn.com/ImageHosting-use-introduction-upload-success.png) 67 | 68 | 69 | [博客传送门](http://charsdavy.github.io) 70 | 71 | -------------------------------------------------------------------------------- /SRC/archive/Applications: -------------------------------------------------------------------------------- 1 | /Applications -------------------------------------------------------------------------------- /SRC/image/background.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charsdavy/ImageHosting/048e49b60b0f5212d8ae110d51cd83c387d982c4/SRC/image/background.tif -------------------------------------------------------------------------------- /SRC/image/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charsdavy/ImageHosting/048e49b60b0f5212d8ae110d51cd83c387d982c4/SRC/image/icon.png -------------------------------------------------------------------------------- /SRC/image/upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charsdavy/ImageHosting/048e49b60b0f5212d8ae110d51cd83c387d982c4/SRC/image/upload.png -------------------------------------------------------------------------------- /SRC/image/upload_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charsdavy/ImageHosting/048e49b60b0f5212d8ae110d51cd83c387d982c4/SRC/image/upload_1.png -------------------------------------------------------------------------------- /SRC/image/upload_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charsdavy/ImageHosting/048e49b60b0f5212d8ae110d51cd83c387d982c4/SRC/image/upload_2.png -------------------------------------------------------------------------------- /SRC/image/upload_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/charsdavy/ImageHosting/048e49b60b0f5212d8ae110d51cd83c387d982c4/SRC/image/upload_3.png --------------------------------------------------------------------------------