Files
ShadowsocksX-NG/ShadowsocksX-NG/Utils.m
2016-06-09 00:30:08 +08:00

134 lines
4.9 KiB
Objective-C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// QRCodeUtils.m
// ShadowsocksX-NG
//
// Created by 邱宇舟 on 16/6/8.
// Copyright © 2016年 qiuyuzhou. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <CoreImage/CoreImage.h>
void ScanQRCodeOnScreen() {
/* displays[] Quartz display ID's */
CGDirectDisplayID *displays = nil;
CGError err = CGDisplayNoErr;
CGDisplayCount dspCount = 0;
/* How many active displays do we have? */
err = CGGetActiveDisplayList(0, NULL, &dspCount);
/* If we are getting an error here then their won't be much to display. */
if(err != CGDisplayNoErr)
{
NSLog(@"Could not get active display count (%d)\n", err);
return;
}
/* Allocate enough memory to hold all the display IDs we have. */
displays = calloc((size_t)dspCount, sizeof(CGDirectDisplayID));
// Get the list of active displays
err = CGGetActiveDisplayList(dspCount,
displays,
&dspCount);
/* More error-checking here. */
if(err != CGDisplayNoErr)
{
NSLog(@"Could not get active display list (%d)\n", err);
return;
}
NSMutableArray* foundSSUrls = [NSMutableArray array];
CIDetector *detector = [CIDetector detectorOfType:@"CIDetectorTypeQRCode"
context:nil
options:@{ CIDetectorAccuracy:CIDetectorAccuracyHigh }];
for (unsigned int displaysIndex = 0; displaysIndex < dspCount; displaysIndex++)
{
/* Make a snapshot image of the current display. */
CGImageRef image = CGDisplayCreateImage(displays[displaysIndex]);
NSArray *features = [detector featuresInImage:[CIImage imageWithCGImage:image]];
for (CIQRCodeFeature *feature in features) {
NSLog(@"%@", feature.messageString);
if ( [feature.messageString hasPrefix:@"ss://"] )
{
[foundSSUrls addObject:[NSURL URLWithString:feature.messageString]];
}
}
}
free(displays);
[[NSNotificationCenter defaultCenter]
postNotificationName:@"NOTIFY_FOUND_SS_URL"
object:nil
userInfo: @{ @"urls": foundSSUrls,
@"source": @"qrcode"
}
];
}
// 解析SS URL如果成功则返回一个与ServerProfile类兼容的dict
NSDictionary<NSString *, id>* ParseSSURL(NSURL* url) {
if (!url.host) {
return nil;
}
NSString *urlString = [url absoluteString];
int i = 0;
NSString *errorReason = nil;
while(i < 2) {
if (i == 1) {
NSString* host = url.host;
if ([host length]%4!=0) {
int n = 4 - [host length]%4;
if (1==n) {
host = [host stringByAppendingString:@"="];
} else if (2==n) {
host = [host stringByAppendingString:@"=="];
}
}
NSData *data = [[NSData alloc] initWithBase64EncodedString:host options:0];
NSString *decodedString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
urlString = decodedString;
}
i++;
urlString = [urlString stringByReplacingOccurrencesOfString:@"ss://" withString:@"" options:NSAnchoredSearch range:NSMakeRange(0, urlString.length)];
NSRange firstColonRange = [urlString rangeOfString:@":"];
NSRange lastColonRange = [urlString rangeOfString:@":" options:NSBackwardsSearch];
NSRange lastAtRange = [urlString rangeOfString:@"@" options:NSBackwardsSearch];
if (firstColonRange.length == 0) {
errorReason = @"colon not found";
continue;
}
if (firstColonRange.location == lastColonRange.location) {
errorReason = @"only one colon";
continue;
}
if (lastAtRange.length == 0) {
errorReason = @"at not found";
continue;
}
if (!((firstColonRange.location < lastAtRange.location) && (lastAtRange.location < lastColonRange.location))) {
errorReason = @"wrong position";
continue;
}
NSString *method = [urlString substringWithRange:NSMakeRange(0, firstColonRange.location)];
NSString *password = [urlString substringWithRange:NSMakeRange(firstColonRange.location + 1, lastAtRange.location - firstColonRange.location - 1)];
NSString *IP = [urlString substringWithRange:NSMakeRange(lastAtRange.location + 1, lastColonRange.location - lastAtRange.location - 1)];
NSString *port = [urlString substringWithRange:NSMakeRange(lastColonRange.location + 1, urlString.length - lastColonRange.location - 1)];
return @{@"ServerHost": IP,
@"ServerPort": @([port integerValue]),
@"Method": method,
@"Password": password,
};
}
return nil;
}