134 lines
4.9 KiB
Mathematica
134 lines
4.9 KiB
Mathematica
![]() |
//
|
|||
|
// 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;
|
|||
|
}
|