Files
ShadowsocksX-NG-R/ShadowsocksX-NG/Utils.m
T
qinyuhang 8569bc590c finish integration basic ssr function
finish integration basic ssr function
2016-08-11 11:23:09 +08:00

144 lines
5.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]];
}else if ( [feature.messageString hasPrefix:@"ssr://"] ){
[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
// 或SSR URL,ServerProfile类已经默认添加SSR参数,默认放空,如果URL为SSR://则改变解析方法
// ss:// + base64(method:password@domain:port)
// ssr:// + base64(abc.xyz:12345:auth_sha1_v2:rc4-md5:tls1.2_ticket_auth:{base64(password)}/?obfsparam={base64(混淆参数(网址))}&remarks={base64(节点名称)})
NSDictionary<NSString *, id>* ParseSSURL(NSURL* url) {
if (!url.host) {
return nil;
}
NSString *urlString = [url absoluteString];
int i = 0;
NSString *errorReason = nil;
if([[NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:NULL ] hasPrefix:@"ss://"]){
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,
};
}
}else if ([[NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:NULL ] hasPrefix:@"ssr://"]){
NSLog(@"Have One ssr QR coming");
}
return nil;
}