├── .gitignore ├── callkiller.xcodeproj └── .gitignore ├── callkiller-gui ├── JGProgressHUD │ ├── jg_hud_error.png │ ├── jg_hud_error@2x.png │ ├── jg_hud_error@3x.png │ ├── jg_hud_success.png │ ├── jg_hud_success@2x.png │ ├── jg_hud_success@3x.png │ ├── JGProgressHUDErrorIndicatorView.h │ ├── JGProgressHUDSuccessIndicatorView.h │ ├── JGProgressHUDImageIndicatorView.m │ ├── JGProgressHUDFadeAnimation.h │ ├── JGProgressHUDImageIndicatorView.h │ ├── JGProgressHUDShadow.m │ ├── JGProgressHUDIndeterminateIndicatorView.h │ ├── JGProgressHUDAnimation.m │ ├── JGProgressHUDFadeZoomAnimation.h │ ├── JGProgressHUDShadow.h │ ├── JGProgressHUDPieIndicatorView.h │ ├── JGProgressHUDIndeterminateIndicatorView.m │ ├── JGProgressHUDFadeAnimation.m │ ├── JGProgressHUDAnimation.h │ ├── JGProgressHUDRingIndicatorView.h │ ├── JGProgressHUDErrorIndicatorView.m │ ├── JGProgressHUDSuccessIndicatorView.m │ ├── JGProgressHUDIndicatorView.h │ ├── JGProgressHUD-Defines.h │ ├── JGProgressHUDIndicatorView.m │ ├── JGProgressHUDFadeZoomAnimation.m │ ├── JGProgressHUDPieIndicatorView.m │ └── JGProgressHUDRingIndicatorView.m ├── Assets.xcassets │ └── AppIcon.appiconset │ │ ├── AppIcon60x60@2xiPhoneApp_60pt@2x.png │ │ ├── AppIcon60x60@2xiPhoneApp_60pt@3x.png │ │ ├── AppIcon60x60@2xiPhoneNotification_20pt@2x.png │ │ ├── AppIcon60x60@2xiPhoneNotification_20pt@3x.png │ │ ├── AppIcon60x60@2xiPhoneSpootlight5_29pt@2x.png │ │ ├── AppIcon60x60@2xiPhoneSpootlight5_29pt@3x.png │ │ ├── AppIcon60x60@2xiPhoneSpootlight7_40pt@2x.png │ │ ├── AppIcon60x60@2xiPhoneSpootlight7_40pt@3x.png │ │ └── Contents.json ├── RootVC.h ├── HistoryVC.h ├── BlacklistVC.h ├── KeywordsVC.h ├── IgnoredPrefixVC.h ├── AppDelegate.h ├── ZoneVC.h ├── main.m ├── AlertUtil.h ├── entitlements.xml ├── AFNetworking │ ├── AFCompatibilityMacros.h │ ├── AFNetworking.h │ ├── AFSecurityPolicy.h │ └── AFNetworkReachabilityManager.h ├── Base.lproj │ └── LaunchScreen.storyboard ├── Info.plist ├── zh-Hans.lproj │ ├── Localizable.strings │ └── Main.strings ├── en.lproj │ ├── Localizable.strings │ └── Main.strings ├── AlertUtil.m ├── AppDelegate.m ├── KeywordsVC.m ├── HistoryVC.m ├── IgnoredPrefixVC.m └── cities.json ├── phone-f0df226e1d1c990220eb5a82acce88bd6955ce31.dat ├── callkiller ├── Package │ ├── Library │ │ └── MobileSubstrate │ │ │ └── DynamicLibraries │ │ │ ├── callkiller.dylib │ │ │ └── callkiller.plist │ └── DEBIAN │ │ └── control ├── callkiller-Prefix.pch ├── TUCallSoundPlayer.h ├── TUHandle.h ├── CTCallCenter.h ├── MPRecentsTableViewCell.h ├── CXCall.h ├── TUCallNotificationManager.h ├── MPRecentsTableViewController.h └── CHRecentCall.h ├── statics ├── GCDObjC │ ├── GCDObjC.h │ ├── GCDMacros.h │ ├── GCDGroup.m │ ├── GCDSemaphore.m │ ├── GCDGroup.h │ ├── GCDSemaphore.h │ ├── GCDQueue.m │ └── GCDQueue.h ├── fmdb │ ├── FMDB.h │ ├── Info.plist │ ├── FMDatabaseAdditions.h │ └── FMDatabaseAdditions.m ├── MobileRegionDetector.h ├── Preference.h ├── statics.h ├── MobileRegionDetector.mm ├── phonedata.h ├── phonedata.cpp └── Preference.m ├── deploy.sh ├── README.md └── generate_deb.sh /.gitignore: -------------------------------------------------------------------------------- 1 | /DerivedData/ 2 | /Packages/ 3 | /LatestBuild 4 | *.deb 5 | -------------------------------------------------------------------------------- /callkiller.xcodeproj/.gitignore: -------------------------------------------------------------------------------- 1 | /xcuserdata/ 2 | /project.xcworkspace/ 3 | -------------------------------------------------------------------------------- /callkiller-gui/JGProgressHUD/jg_hud_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laoyur/CallKiller-iOS/HEAD/callkiller-gui/JGProgressHUD/jg_hud_error.png -------------------------------------------------------------------------------- /callkiller-gui/JGProgressHUD/jg_hud_error@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laoyur/CallKiller-iOS/HEAD/callkiller-gui/JGProgressHUD/jg_hud_error@2x.png -------------------------------------------------------------------------------- /callkiller-gui/JGProgressHUD/jg_hud_error@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laoyur/CallKiller-iOS/HEAD/callkiller-gui/JGProgressHUD/jg_hud_error@3x.png -------------------------------------------------------------------------------- /callkiller-gui/JGProgressHUD/jg_hud_success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laoyur/CallKiller-iOS/HEAD/callkiller-gui/JGProgressHUD/jg_hud_success.png -------------------------------------------------------------------------------- /callkiller-gui/JGProgressHUD/jg_hud_success@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laoyur/CallKiller-iOS/HEAD/callkiller-gui/JGProgressHUD/jg_hud_success@2x.png -------------------------------------------------------------------------------- /callkiller-gui/JGProgressHUD/jg_hud_success@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laoyur/CallKiller-iOS/HEAD/callkiller-gui/JGProgressHUD/jg_hud_success@3x.png -------------------------------------------------------------------------------- /phone-f0df226e1d1c990220eb5a82acce88bd6955ce31.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laoyur/CallKiller-iOS/HEAD/phone-f0df226e1d1c990220eb5a82acce88bd6955ce31.dat -------------------------------------------------------------------------------- /callkiller/Package/Library/MobileSubstrate/DynamicLibraries/callkiller.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laoyur/CallKiller-iOS/HEAD/callkiller/Package/Library/MobileSubstrate/DynamicLibraries/callkiller.dylib -------------------------------------------------------------------------------- /callkiller-gui/Assets.xcassets/AppIcon.appiconset/AppIcon60x60@2xiPhoneApp_60pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laoyur/CallKiller-iOS/HEAD/callkiller-gui/Assets.xcassets/AppIcon.appiconset/AppIcon60x60@2xiPhoneApp_60pt@2x.png -------------------------------------------------------------------------------- /callkiller-gui/Assets.xcassets/AppIcon.appiconset/AppIcon60x60@2xiPhoneApp_60pt@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laoyur/CallKiller-iOS/HEAD/callkiller-gui/Assets.xcassets/AppIcon.appiconset/AppIcon60x60@2xiPhoneApp_60pt@3x.png -------------------------------------------------------------------------------- /callkiller-gui/RootVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // RootVC.h 3 | // callkiller-gui 4 | // 5 | // Created by mac on 2018/7/18. 6 | // 7 | 8 | #import 9 | 10 | @interface RootVC : UITableViewController 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /callkiller-gui/Assets.xcassets/AppIcon.appiconset/AppIcon60x60@2xiPhoneNotification_20pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laoyur/CallKiller-iOS/HEAD/callkiller-gui/Assets.xcassets/AppIcon.appiconset/AppIcon60x60@2xiPhoneNotification_20pt@2x.png -------------------------------------------------------------------------------- /callkiller-gui/Assets.xcassets/AppIcon.appiconset/AppIcon60x60@2xiPhoneNotification_20pt@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laoyur/CallKiller-iOS/HEAD/callkiller-gui/Assets.xcassets/AppIcon.appiconset/AppIcon60x60@2xiPhoneNotification_20pt@3x.png -------------------------------------------------------------------------------- /callkiller-gui/Assets.xcassets/AppIcon.appiconset/AppIcon60x60@2xiPhoneSpootlight5_29pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laoyur/CallKiller-iOS/HEAD/callkiller-gui/Assets.xcassets/AppIcon.appiconset/AppIcon60x60@2xiPhoneSpootlight5_29pt@2x.png -------------------------------------------------------------------------------- /callkiller-gui/Assets.xcassets/AppIcon.appiconset/AppIcon60x60@2xiPhoneSpootlight5_29pt@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laoyur/CallKiller-iOS/HEAD/callkiller-gui/Assets.xcassets/AppIcon.appiconset/AppIcon60x60@2xiPhoneSpootlight5_29pt@3x.png -------------------------------------------------------------------------------- /callkiller-gui/Assets.xcassets/AppIcon.appiconset/AppIcon60x60@2xiPhoneSpootlight7_40pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laoyur/CallKiller-iOS/HEAD/callkiller-gui/Assets.xcassets/AppIcon.appiconset/AppIcon60x60@2xiPhoneSpootlight7_40pt@2x.png -------------------------------------------------------------------------------- /callkiller-gui/Assets.xcassets/AppIcon.appiconset/AppIcon60x60@2xiPhoneSpootlight7_40pt@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laoyur/CallKiller-iOS/HEAD/callkiller-gui/Assets.xcassets/AppIcon.appiconset/AppIcon60x60@2xiPhoneSpootlight7_40pt@3x.png -------------------------------------------------------------------------------- /statics/GCDObjC/GCDObjC.h: -------------------------------------------------------------------------------- 1 | // 2 | // GCDObjC.h 3 | // GCDObjC 4 | // 5 | // Copyright (c) 2012 Mark Smith. All rights reserved. 6 | // 7 | 8 | #import "GCDMacros.h" 9 | 10 | #import "GCDGroup.h" 11 | #import "GCDQueue.h" 12 | #import "GCDSemaphore.h" 13 | -------------------------------------------------------------------------------- /callkiller/callkiller-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'callkiller' target in the 'callkiller' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #import "/opt/theos/Prefix.pch" //path/to/theos/Prefix.pch 8 | #endif 9 | -------------------------------------------------------------------------------- /callkiller-gui/HistoryVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // HistoryVC.h 3 | // callkiller-gui 4 | // 5 | // Created by mac on 2018/8/1. 6 | // 7 | 8 | #import 9 | 10 | @interface HistoryVC : UIViewController 11 | 12 | @property (weak, nonatomic) NSMutableArray *history; 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /callkiller-gui/BlacklistVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // BlacklistVC.h 3 | // callkiller-gui 4 | // 5 | // Created by mac on 2018/7/19. 6 | // 7 | 8 | #import 9 | 10 | @interface BlacklistVC : UIViewController 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /callkiller-gui/KeywordsVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // KeywordsVC.h 3 | // callkiller-gui 4 | // 5 | // Created by mac on 2018/7/19. 6 | // 7 | 8 | #import 9 | 10 | @interface KeywordsVC : UIViewController 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /callkiller-gui/IgnoredPrefixVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // IgnoredPrefixVC.h 3 | // callkiller-gui 4 | // 5 | // Created by mac on 2018/8/14. 6 | // 7 | 8 | #import 9 | 10 | @interface IgnoredPrefixVC : UIViewController 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /callkiller-gui/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // callkiller-gui 4 | // 5 | // Created by mac on 2018/7/18. 6 | // 7 | 8 | #import 9 | 10 | @interface AppDelegate : UIResponder 11 | 12 | @property (strong, nonatomic) UIWindow *window; 13 | 14 | 15 | @end 16 | 17 | -------------------------------------------------------------------------------- /callkiller-gui/ZoneVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZoneVC.h 3 | // callkiller-gui 4 | // 5 | // Created by mac on 2018/7/18. 6 | // 7 | 8 | #import 9 | 10 | @interface ZoneVC : UIViewController 11 | 12 | @property(nonatomic) BOOL forMobile; 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /statics/fmdb/FMDB.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | FOUNDATION_EXPORT double FMDBVersionNumber; 4 | FOUNDATION_EXPORT const unsigned char FMDBVersionString[]; 5 | 6 | #import "FMDatabase.h" 7 | #import "FMResultSet.h" 8 | #import "FMDatabaseAdditions.h" 9 | #import "FMDatabaseQueue.h" 10 | #import "FMDatabasePool.h" 11 | -------------------------------------------------------------------------------- /callkiller-gui/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // callkiller-gui 4 | // 5 | // Created by mac on 2018/7/18. 6 | // 7 | 8 | #import 9 | #import "AppDelegate.h" 10 | 11 | int main(int argc, char * argv[]) { 12 | @autoreleasepool { 13 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /statics/MobileRegionDetector.h: -------------------------------------------------------------------------------- 1 | // 2 | // MobileRegionDetector.h 3 | // statics 4 | // 5 | // Created by mac on 2018/7/26. 6 | // 7 | 8 | #import 9 | 10 | @interface MobileRegionDetector : NSObject 11 | 12 | +(instancetype)sharedInstance; 13 | -(NSString*)dbVersion; 14 | -(NSString*)detectRegionCode:(NSString*)mobileNumber; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | DEVICE_IP="192.168.1.93" 2 | if [[ $# -gt "0" ]]; then 3 | DEVICE_IP=$1 4 | fi 5 | 6 | VERSION=`/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' callkiller-gui/Info.plist` 7 | 8 | scp callkiller-${VERSION}.deb root@$DEVICE_IP:/tmp/callkiller.deb 9 | ssh root@$DEVICE_IP <<-'ENDSSH' 10 | dpkg -i /tmp/callkiller.deb 11 | sleep 2 12 | killall -9 SpringBoard 13 | ENDSSH 14 | -------------------------------------------------------------------------------- /callkiller/Package/DEBIAN/control: -------------------------------------------------------------------------------- 1 | Package: com.laoyur.callkiller 2 | Name: callkiller 3 | Version: 1.0.0 4 | Description: kill the fvcking annoying spamming calls 5 | Section: System 6 | Depends: firmware (>= 11.0), mobilesubstrate 7 | Conflicts: 8 | Replaces: 9 | Priority: optional 10 | Architecture: iphoneos-arm 11 | Author: laoyur 12 | dev: 13 | Homepage: 14 | Depiction: 15 | Maintainer: laoyur 16 | Icon: 17 | 18 | -------------------------------------------------------------------------------- /callkiller/Package/Library/MobileSubstrate/DynamicLibraries/callkiller.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Filter 6 | 7 | Bundles 8 | 9 | com.apple.springboard 10 | com.apple.mobilephone 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /callkiller-gui/JGProgressHUD/JGProgressHUDErrorIndicatorView.h: -------------------------------------------------------------------------------- 1 | // 2 | // JGProgressHUDErrorIndicatorView.h 3 | // JGProgressHUD 4 | // 5 | // Created by Jonas Gessner on 19.08.14. 6 | // Copyright (c) 2014 Jonas Gessner. All rights reserved. 7 | // 8 | 9 | #import "JGProgressHUDImageIndicatorView.h" 10 | 11 | /** 12 | An image indicator showing a cross, representing a failed operation. 13 | */ 14 | @interface JGProgressHUDErrorIndicatorView : JGProgressHUDImageIndicatorView 15 | 16 | /** 17 | Default initializer for this class. 18 | */ 19 | - (instancetype __nonnull)init; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /callkiller-gui/JGProgressHUD/JGProgressHUDSuccessIndicatorView.h: -------------------------------------------------------------------------------- 1 | // 2 | // JGProgressHUDSuccessIndicatorView.h 3 | // JGProgressHUD 4 | // 5 | // Created by Jonas Gessner on 19.08.14. 6 | // Copyright (c) 2014 Jonas Gessner. All rights reserved. 7 | // 8 | 9 | #import "JGProgressHUDImageIndicatorView.h" 10 | 11 | /** 12 | An image indicator showing a checkmark, representing a failed operation. 13 | */ 14 | @interface JGProgressHUDSuccessIndicatorView : JGProgressHUDImageIndicatorView 15 | 16 | /** 17 | Default initializer for this class. 18 | */ 19 | - (instancetype __nonnull)init; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /callkiller-gui/JGProgressHUD/JGProgressHUDImageIndicatorView.m: -------------------------------------------------------------------------------- 1 | // 2 | // JGProgressHUDImageIndicatorView.m 3 | // JGProgressHUD 4 | // 5 | // Created by Jonas Gessner on 05.08.15. 6 | // Copyright (c) 2015 Jonas Gessner. All rights reserved. 7 | // 8 | 9 | #import "JGProgressHUDImageIndicatorView.h" 10 | 11 | @implementation JGProgressHUDImageIndicatorView 12 | 13 | - (instancetype)initWithImage:(UIImage *)image { 14 | UIImageView *imageView = [[UIImageView alloc] initWithImage:image]; 15 | 16 | self = [super initWithContentView:imageView]; 17 | 18 | return self; 19 | } 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /callkiller-gui/AlertUtil.h: -------------------------------------------------------------------------------- 1 | // 2 | // AlertUtil.h 3 | // callkiller-gui 4 | // 5 | // Created by mac on 2018/7/19. 6 | // 7 | 8 | #import 9 | 10 | @interface AlertUtil : NSObject 11 | 12 | + (void) showInfo:(NSString *)title message:(NSString *)msg; 13 | + (void) showInfo:(NSString *)title message:(NSString *)msg onConfirm:(void(^)(void))cb; 14 | + (void) showQuery:(NSString *)title message:(NSString *)msg isDanger:(BOOL)danger onConfirm:(void(^)(void))cb; 15 | // 16 | + (void) showWaitingHud:(NSString *)text; 17 | + (void) showProgressHud:(NSString *)text; 18 | + (void) updateHudProgress:(float)ratio; 19 | + (void) updateHudText:(NSString *)text; 20 | + (void) hideHud; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /callkiller-gui/entitlements.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | application-identifier 6 | com.laoyur.callkiller-gui 7 | com.apple.private.security.container-required 8 | 9 | platform-application 10 | 11 | com.apple.springboard.opensensitiveurl 12 | 13 | com.apple.backboardd.launchapplications 14 | 15 | com.apple.frontboard.launchapplications 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /callkiller-gui/JGProgressHUD/JGProgressHUDFadeAnimation.h: -------------------------------------------------------------------------------- 1 | // 2 | // JGProgressHUDFadeAnimation.h 3 | // JGProgressHUD 4 | // 5 | // Created by Jonas Gessner on 20.7.14. 6 | // Copyright (c) 2014 Jonas Gessner. All rights reserved. 7 | // 8 | 9 | #import "JGProgressHUDAnimation.h" 10 | 11 | /** 12 | A simple fade animation that fades the HUD from alpha @c 0.0 to alpha @c 1.0. 13 | */ 14 | @interface JGProgressHUDFadeAnimation : JGProgressHUDAnimation 15 | 16 | /** 17 | Duration of the animation. 18 | 19 | @b Default: 0.4. 20 | */ 21 | @property (nonatomic, assign) NSTimeInterval duration; 22 | 23 | /** 24 | Animation options 25 | 26 | @b Default: UIViewAnimationOptionCurveEaseInOut. 27 | */ 28 | @property (nonatomic, assign) UIViewAnimationOptions animationOptions; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /callkiller-gui/JGProgressHUD/JGProgressHUDImageIndicatorView.h: -------------------------------------------------------------------------------- 1 | // 2 | // JGProgressHUDImageIndicatorView.h 3 | // JGProgressHUD 4 | // 5 | // Created by Jonas Gessner on 05.08.15. 6 | // Copyright (c) 2015 Jonas Gessner. All rights reserved. 7 | // 8 | 9 | #import "JGProgressHUDIndicatorView.h" 10 | 11 | /** 12 | An indicator for displaying custom images. Supports animated images. 13 | 14 | You may subclass this class to create a custom image indicator view. 15 | */ 16 | @interface JGProgressHUDImageIndicatorView : JGProgressHUDIndicatorView 17 | 18 | /** 19 | Initializes the indicator view with an UIImageView showing the @c image. 20 | 21 | @param image The image to show in the indicator view. 22 | */ 23 | - (instancetype __nonnull)initWithImage:(UIImage *__nonnull)image; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /callkiller-gui/JGProgressHUD/JGProgressHUDShadow.m: -------------------------------------------------------------------------------- 1 | // 2 | // JGProgressHUDShadow.m 3 | // JGProgressHUD 4 | // 5 | // Created by Jonas Gessner on 25.09.17. 6 | // Copyright © 2017 Jonas Gessner. All rights reserved. 7 | // 8 | 9 | #import "JGProgressHUDShadow.h" 10 | 11 | @implementation JGProgressHUDShadow 12 | 13 | + (instancetype)shadowWithColor:(UIColor *)color offset:(CGSize)offset radius:(CGFloat)radius opacity:(float)opacity { 14 | return [[self alloc] initWithColor:color offset:offset radius:radius opacity:opacity]; 15 | } 16 | 17 | - (instancetype)initWithColor:(UIColor *)color offset:(CGSize)offset radius:(CGFloat)radius opacity:(float)opacity { 18 | self = [super init]; 19 | 20 | if (self) { 21 | _color = color; 22 | _offset = offset; 23 | _radius = radius; 24 | _opacity = opacity; 25 | } 26 | 27 | return self; 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /statics/fmdb/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 | FMWK 17 | CFBundleShortVersionString 18 | 2.7.4 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /statics/GCDObjC/GCDMacros.h: -------------------------------------------------------------------------------- 1 | // 2 | // GCDMacros.h 3 | // GCDObjC 4 | // 5 | // Copyright (c) 2013 Mark Smith. All rights reserved. 6 | // 7 | // 8 | 9 | /** 10 | * Inserts code that executes a block only once, regardless of how many times the macro is invoked. 11 | * 12 | * @param block The block to execute once. 13 | */ 14 | #ifndef GCDExecOnce 15 | #define GCDExecOnce(block) \ 16 | { \ 17 | static dispatch_once_t predicate = 0; \ 18 | dispatch_once(&predicate, block); \ 19 | } 20 | #endif 21 | 22 | /** 23 | * Inserts code that declares, creates, and returns a single instance, regardless of how many times the macro is invoked. 24 | * 25 | * @param block A block that creates and returns the instance value. 26 | */ 27 | #ifndef GCDSharedInstance 28 | #define GCDSharedInstance(block) \ 29 | { \ 30 | static dispatch_once_t predicate = 0; \ 31 | static id sharedInstance = nil; \ 32 | dispatch_once(&predicate, ^{ sharedInstance = block(); }); \ 33 | return sharedInstance; \ 34 | } 35 | #endif 36 | -------------------------------------------------------------------------------- /callkiller-gui/JGProgressHUD/JGProgressHUDIndeterminateIndicatorView.h: -------------------------------------------------------------------------------- 1 | // 2 | // JGProgressHUDIndeterminateIndicatorView.h 3 | // JGProgressHUD 4 | // 5 | // Created by Jonas Gessner on 19.07.14. 6 | // Copyright (c) 2014 Jonas Gessner. All rights reserved. 7 | // 8 | 9 | #import "JGProgressHUD-Defines.h" 10 | #import "JGProgressHUDIndicatorView.h" 11 | 12 | /** 13 | An indeterminate progress indicator showing a @c UIActivityIndicatorView. 14 | */ 15 | @interface JGProgressHUDIndeterminateIndicatorView : JGProgressHUDIndicatorView 16 | 17 | /** 18 | Initializes the indicator view and sets the correct color to match the HUD style. 19 | */ 20 | - (instancetype __nonnull)initWithHUDStyle:(JGProgressHUDStyle)style __attribute((deprecated(("This initializer is no longer needed. Use the init initializer method.")))); 21 | 22 | /** 23 | Set the color of the activity indicator view. 24 | @param color The color to apply to the activity indicator view. 25 | */ 26 | - (void)setColor:(UIColor *__nonnull)color; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /callkiller-gui/JGProgressHUD/JGProgressHUDAnimation.m: -------------------------------------------------------------------------------- 1 | // 2 | // JGProgressHUDAnimation.m 3 | // JGProgressHUD 4 | // 5 | // Created by Jonas Gessner on 20.7.14. 6 | // Copyright (c) 2014 Jonas Gessner. All rights reserved. 7 | // 8 | 9 | #import "JGProgressHUDAnimation.h" 10 | #import "JGProgressHUD.h" 11 | 12 | @interface JGProgressHUD (Private) 13 | 14 | - (void)animationDidFinish:(BOOL)presenting; 15 | 16 | @end 17 | 18 | @interface JGProgressHUDAnimation () { 19 | BOOL _presenting; 20 | } 21 | 22 | @property (nonatomic, weak) JGProgressHUD *progressHUD; 23 | 24 | @end 25 | 26 | @implementation JGProgressHUDAnimation 27 | 28 | #pragma mark - Initializers 29 | 30 | + (instancetype)animation { 31 | return [[self alloc] init]; 32 | } 33 | 34 | #pragma mark - Public methods 35 | 36 | - (void)show { 37 | _presenting = YES; 38 | } 39 | 40 | - (void)hide { 41 | _presenting = NO; 42 | } 43 | 44 | - (void)animationFinished { 45 | [self.progressHUD animationDidFinish:_presenting]; 46 | } 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /callkiller-gui/JGProgressHUD/JGProgressHUDFadeZoomAnimation.h: -------------------------------------------------------------------------------- 1 | // 2 | // JGProgressHUDFadeZoomAnimation.h 3 | // JGProgressHUD 4 | // 5 | // Created by Jonas Gessner on 20.7.14. 6 | // Copyright (c) 2014 Jonas Gessner. All rights reserved. 7 | // 8 | 9 | #import "JGProgressHUDAnimation.h" 10 | 11 | /** 12 | An animation that fades in the HUD and expands the HUD from scale @c (0, 0) to a customizable scale, and finally to scale @c (1, 1), creating a bouncing effect. 13 | */ 14 | @interface JGProgressHUDFadeZoomAnimation : JGProgressHUDAnimation 15 | 16 | /** 17 | Duration of the animation from or to the shrinked state. 18 | 19 | @b Default: 0.2. 20 | */ 21 | @property (nonatomic, assign) NSTimeInterval shrinkAnimationDuaration; 22 | 23 | /** 24 | Duration of the animation from or to the expanded state. 25 | 26 | @b Default: 0.1. 27 | */ 28 | @property (nonatomic, assign) NSTimeInterval expandAnimationDuaration; 29 | 30 | /** 31 | The scale to apply to the HUD when expanding. 32 | 33 | @b Default: (1.1, 1.1). 34 | */ 35 | @property (nonatomic, assign) CGSize expandScale; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 截图 2 | ![](https://laoyur.com/dl/ios/callkiller/photo_2018-07-20_18-42-00.jpg) 3 | ![](https://laoyur.com/dl/ios/callkiller/photo_2018-07-20_18-42-09.jpg) 4 | ![](https://laoyur.com/dl/ios/callkiller/photo_2018-07-20_18-42-14.jpg) 5 | ![](https://laoyur.com/dl/ios/callkiller/photo_2018-07-20_18-42-18.jpg) 6 | 7 | # changes in 1.5.1 8 | * 兼容中国移动和多号业务 9 | * 来电时主动静音,若无需拦截,再进行响铃,以保证发生拦截时不会出现响一声的情况 10 | 11 | # changes in 1.3.2 12 | * 理论上也支持 iOS 10 13 | * 支持按归属地拦截手机号 14 | * 其他一些细节优化 15 | 16 | # changes in 1.1.0 17 | * 终于有GUI设置界面了 18 | * 应该可以拦截未知号码(需进一步测试) 19 | * 可以选择是否放行联系人 20 | * 支持按区号拦截 21 | * 支持自定义号码黑名单,支持通配符( * 和 ? ) 22 | * 支持自定义拦截关键词(跟1.0.0版一样,需要自行安装助手类App来写入标签数据库) 23 | * **接受捐赠**。我曾在v2ex上说过不需要捐赠,后来想了想,既然有GUI了,为啥不做一个功能进去呢 24 | 25 | # 如何安装 26 | * 从BigBoss搜索CallKiller 27 | * 直接从Release页面下载编译好的deb,但安装完后可能需要手动uicache一下 :( 28 | * 下载代码自己编译 29 | 30 | # 如何编译 31 | * 下载安装MonkeyDev 32 | * 下载安装Theos 33 | * 机器上装好`ldid`、`dpkg-deb`,推荐用Homebrew安装 34 | * 打开xcodeproj,配置证书 35 | * 打开终端,cd到项目根目录,执行 `sh generate_deb.sh`,deb包会生成在项目根目录 36 | * `sh deploy.sh DEVICE_IP`,可以快速把deb scp到手机上安装 37 | -------------------------------------------------------------------------------- /statics/GCDObjC/GCDGroup.m: -------------------------------------------------------------------------------- 1 | // 2 | // GCDGroup.m 3 | // GCDObjC 4 | // 5 | // Copyright (c) 2012 Mark Smith. All rights reserved. 6 | // 7 | 8 | #import "GCDGroup.h" 9 | 10 | @interface GCDGroup () 11 | @property (strong, readwrite, nonatomic) dispatch_group_t dispatchGroup; 12 | @end 13 | 14 | @implementation GCDGroup 15 | 16 | #pragma mark Lifecycle. 17 | 18 | - (instancetype)init { 19 | return [self initWithDispatchGroup:dispatch_group_create()]; 20 | } 21 | 22 | - (instancetype)initWithDispatchGroup:(dispatch_group_t)dispatchGroup { 23 | if ((self = [super init]) != nil) { 24 | self.dispatchGroup = dispatchGroup; 25 | } 26 | 27 | return self; 28 | } 29 | 30 | #pragma mark Public methods. 31 | 32 | - (void)enter { 33 | dispatch_group_enter(self.dispatchGroup); 34 | } 35 | 36 | - (void)leave { 37 | dispatch_group_leave(self.dispatchGroup); 38 | } 39 | 40 | - (void)wait { 41 | dispatch_group_wait(self.dispatchGroup, DISPATCH_TIME_FOREVER); 42 | } 43 | 44 | - (BOOL)wait:(double)seconds { 45 | return dispatch_group_wait(self.dispatchGroup, dispatch_time(DISPATCH_TIME_NOW, (seconds * NSEC_PER_SEC))) == 0; 46 | } 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /statics/GCDObjC/GCDSemaphore.m: -------------------------------------------------------------------------------- 1 | // 2 | // GCDSemaphore.m 3 | // GCDObjC 4 | // 5 | // Copyright (c) 2012 Mark Smith. All rights reserved. 6 | // 7 | 8 | #import "GCDSemaphore.h" 9 | 10 | @interface GCDSemaphore () 11 | @property (strong, readwrite, nonatomic) dispatch_semaphore_t dispatchSemaphore; 12 | @end 13 | 14 | @implementation GCDSemaphore 15 | 16 | #pragma mark Lifecycle. 17 | 18 | - (instancetype)init { 19 | return [self initWithValue:0]; 20 | } 21 | 22 | - (instancetype)initWithValue:(long)value { 23 | return [self initWithDispatchSemaphore:dispatch_semaphore_create(value)]; 24 | } 25 | 26 | - (instancetype)initWithDispatchSemaphore:(dispatch_semaphore_t)dispatchSemaphore { 27 | if ((self = [super init]) != nil) { 28 | self.dispatchSemaphore = dispatchSemaphore; 29 | } 30 | 31 | return self; 32 | } 33 | 34 | #pragma mark Public methods. 35 | 36 | - (BOOL)signal { 37 | return dispatch_semaphore_signal(self.dispatchSemaphore) != 0; 38 | } 39 | 40 | - (void)wait { 41 | dispatch_semaphore_wait(self.dispatchSemaphore, DISPATCH_TIME_FOREVER); 42 | } 43 | 44 | - (BOOL)wait:(double)seconds { 45 | return dispatch_semaphore_wait(self.dispatchSemaphore, dispatch_time(DISPATCH_TIME_NOW, (seconds * NSEC_PER_SEC))) == 0; 46 | } 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /callkiller-gui/JGProgressHUD/JGProgressHUDShadow.h: -------------------------------------------------------------------------------- 1 | // 2 | // JGProgressHUDShadow.h 3 | // JGProgressHUD 4 | // 5 | // Created by Jonas Gessner on 25.09.17. 6 | // Copyright © 2017 Jonas Gessner. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /** 12 | A wrapper representing properties of a shadow. 13 | */ 14 | @interface JGProgressHUDShadow : NSObject 15 | 16 | - (instancetype __nonnull)initWithColor:(UIColor *__nonnull)color offset:(CGSize)offset radius:(CGFloat)radius opacity:(float)opacity; 17 | 18 | /** Convenience initializer. */ 19 | + (instancetype __nonnull)shadowWithColor:(UIColor *__nonnull)color offset:(CGSize)offset radius:(CGFloat)radius opacity:(float)opacity; 20 | 21 | /** 22 | The color of the shadow. Colors created from patterns are currently NOT supported. 23 | */ 24 | @property (nonatomic, strong, readonly, nonnull) UIColor *color; 25 | 26 | /** The shadow offset. */ 27 | @property (nonatomic, assign, readonly) CGSize offset; 28 | 29 | /** The blur radius used to create the shadow. */ 30 | @property (nonatomic, assign, readonly) CGFloat radius; 31 | 32 | /** 33 | The opacity of the shadow. Specifying a value outside the [0,1] range will give undefined results. 34 | */ 35 | @property (nonatomic, assign, readonly) float opacity; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /callkiller/TUCallSoundPlayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // TUCallSoundPlayer.h 3 | // callkiller 4 | // 5 | // Created by mac on 2018/7/11. 6 | // 7 | 8 | #ifndef TUCallSoundPlayer_h 9 | #define TUCallSoundPlayer_h 10 | 11 | @class TUSoundPlayer; 12 | 13 | @interface TUCallSoundPlayer : NSObject { 14 | 15 | TUSoundPlayer* _player; 16 | long long _currentlyPlayingSoundType; 17 | 18 | } 19 | 20 | @property (nonatomic,retain) TUSoundPlayer * player; //@synthesize player=_player - In the implementation block 21 | @property (assign,nonatomic) long long currentlyPlayingSoundType; //@synthesize currentlyPlayingSoundType=_currentlyPlayingSoundType - In the implementation block 22 | @property (getter=isPlaying,nonatomic,readonly) BOOL playing; 23 | -(id)init; 24 | -(BOOL)isPlaying; 25 | -(BOOL)attemptToPlaySoundType:(long long)arg1 forCall:(id)arg2 completion:(/*^block*/id)arg3 ; 26 | -(BOOL)attemptToPlayDescriptor:(id)arg1 completion:(/*^block*/id)arg2 ; 27 | -(long long)currentlyPlayingSoundType; 28 | -(void)setCurrentlyPlayingSoundType:(long long)arg1 ; 29 | -(BOOL)attemptToPlaySoundType:(long long)arg1 forCall:(id)arg2 ; 30 | -(BOOL)attemptToPlayDescriptor:(id)arg1 ; 31 | -(TUSoundPlayer *)player; 32 | -(void)setPlayer:(TUSoundPlayer *)arg1 ; 33 | -(void)stopPlaying; 34 | @end 35 | 36 | #endif /* TUCallSoundPlayer_h */ 37 | -------------------------------------------------------------------------------- /callkiller-gui/JGProgressHUD/JGProgressHUDPieIndicatorView.h: -------------------------------------------------------------------------------- 1 | // 2 | // JGProgressHUDPieIndicatorView.h 3 | // JGProgressHUD 4 | // 5 | // Created by Jonas Gessner on 19.07.14. 6 | // Copyright (c) 2014 Jonas Gessner. All rights reserved. 7 | // 8 | 9 | #import "JGProgressHUD-Defines.h" 10 | #import "JGProgressHUDIndicatorView.h" 11 | 12 | /** 13 | A pie shaped determinate progress indicator. 14 | */ 15 | @interface JGProgressHUDPieIndicatorView : JGProgressHUDIndicatorView 16 | 17 | /** 18 | Initializes the indicator view and sets the correct color to match the HUD style. 19 | */ 20 | - (instancetype __nonnull)initWithHUDStyle:(JGProgressHUDStyle)style __attribute((deprecated(("This initializer is no longer needed. Use the init initializer method.")))); 21 | 22 | /** 23 | Tint color of the Pie. 24 | @attention Custom values need to be set after assigning the indicator view to @c JGProgressHUD's @c indicatorView property. 25 | 26 | @b Default: White for JGProgressHUDStyleDark, otherwise black. 27 | */ 28 | @property (nonatomic, strong, nonnull) UIColor *color; 29 | 30 | /** 31 | The background fill color inside the pie. 32 | @attention Custom values need to be set after assigning the indicator view to @c JGProgressHUD's @c indicatorView property. 33 | 34 | @b Default: Dark gray for JGProgressHUDStyleDark, otherwise light gray. 35 | */ 36 | @property (nonatomic, strong, nonnull) UIColor *fillColor; 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /statics/Preference.h: -------------------------------------------------------------------------------- 1 | // 2 | // Preference.h 3 | // statics 4 | // 5 | // Created by mac on 2018/7/18. 6 | // 7 | 8 | #import 9 | 10 | #define kKeyPrefVersion @"version" // added in 1.3.1 11 | #define kKeyEnabled @"enabled" 12 | #define kKeyBlockUnknown @"block-unknown-enabled" 13 | #define kKeyBypassContacts @"bypass-contacts-enabled" 14 | #define kKeyBlockedGroups @"blocked-groups" // 座机按省拦截 15 | #define kKeyBlockedCities @"blocked-cities" // 座机按市拦截 16 | #define kKeyBlockedCitiesFlattened @"blocked-cities-flattened" // for springboard 17 | #define kKeyMobileBlockedGroups @"mobile-blocked-groups" // 手机号按省拦截 18 | #define kKeyMobileBlockedCities @"mobile-blocked-cities" // 手机号按市拦截 19 | #define kKeyMobileBlockedCitiesFlattened @"mobile-blocked-cities-flattened" // for springboard 20 | #define kKeyBlacklist @"blacklist" 21 | #define kKeyIgnoredPrefixes @"ignored-prefixes" // added in 1.4.3 22 | #define kKeyBlackKeywords @"keywords" 23 | 24 | #define kKeyMPInjectionEnabled @"mp-injection-enabled" 25 | 26 | @interface Preference : NSObject { 27 | NSMutableDictionary *_pref; 28 | NSMutableDictionary *_mpPref; 29 | } 30 | 31 | +(instancetype)sharedInstance; 32 | +(NSDictionary*)load; 33 | +(NSDictionary*)loadMPPref; 34 | +(NSString*)mpPrefFilePath; 35 | 36 | -(NSMutableDictionary*)pref; 37 | -(void)save; 38 | -(void)saveOnly; 39 | 40 | -(NSMutableDictionary*)mpPref; 41 | -(void)saveMPPref; 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /callkiller-gui/JGProgressHUD/JGProgressHUDIndeterminateIndicatorView.m: -------------------------------------------------------------------------------- 1 | // 2 | // JGProgressHUDIndeterminateIndicatorView.m 3 | // JGProgressHUD 4 | // 5 | // Created by Jonas Gessner on 19.07.14. 6 | // Copyright (c) 2014 Jonas Gessner. All rights reserved. 7 | // 8 | 9 | #import "JGProgressHUDIndeterminateIndicatorView.h" 10 | 11 | @implementation JGProgressHUDIndeterminateIndicatorView 12 | 13 | - (instancetype)init { 14 | UIActivityIndicatorView *activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; 15 | [activityIndicatorView startAnimating]; 16 | 17 | self = [super initWithContentView:activityIndicatorView]; 18 | return self; 19 | } 20 | 21 | - (instancetype)initWithHUDStyle:(JGProgressHUDStyle)style { 22 | return [self init]; 23 | } 24 | 25 | - (void)setUpForHUDStyle:(JGProgressHUDStyle)style vibrancyEnabled:(BOOL)vibrancyEnabled { 26 | [super setUpForHUDStyle:style vibrancyEnabled:vibrancyEnabled]; 27 | 28 | if (style != JGProgressHUDStyleDark) { 29 | self.color = [UIColor blackColor]; 30 | } 31 | else { 32 | self.color = [UIColor whiteColor]; 33 | } 34 | } 35 | 36 | - (void)setColor:(UIColor *)color { 37 | [(UIActivityIndicatorView *)self.contentView setColor:color]; 38 | } 39 | 40 | - (void)updateAccessibility { 41 | self.accessibilityLabel = NSLocalizedString(@"Indeterminate progress",); 42 | } 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /statics/statics.h: -------------------------------------------------------------------------------- 1 | // 2 | // statics.h 3 | // statics 4 | // 5 | // Created by mac on 2018/7/16. 6 | // 7 | 8 | #import 9 | #import 10 | 11 | #import "GCDObjC/GCDObjC.h" 12 | #import "fmdb/FMDB.h" 13 | 14 | #define kMPHistoryFileName @"callkiller-history.txt" 15 | #define kMPHistoryAddedNotification "com.laoyur.callkiller.mp-block-history-added" 16 | #define kMPHistoryFileChangedNotification "com.laoyur.callkiller.mp-history-file-changed" 17 | #define kCallKillerPrefUpdatedNotification "com.laoyur.callkiller.preference-updated" 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | typedef enum : NSUInteger { 24 | ReasonNotBlocked = 0, 25 | ReasonBlockedAsUnknownNumber = 1, 26 | ReasonBlockedAsLandline = 2, 27 | ReasonBlockedAsMobile = 3, 28 | ReasonBlockedAsBlacklist = 4, 29 | ReasonBlockedAsKeywords = 5, 30 | ReasonBlockedAsSystemBlacklist = 99, 31 | } BlockReason; 32 | 33 | void Log(const char *fmt, ...); 34 | #ifdef __cplusplus 35 | } 36 | #endif 37 | 38 | @protocol MutableDeepCopying 39 | -(id) mutableDeepCopy; 40 | @end 41 | 42 | @interface NSDictionary (MutableDeepCopy) 43 | @end 44 | 45 | @interface NSArray (MutableDeepCopy) 46 | @end 47 | 48 | @interface NSString (CKAdditional) 49 | - (NSString *)trimming; 50 | - (BOOL) isVersionStringGE:(NSString *)version; 51 | @end 52 | 53 | @interface UIColor (Hex) 54 | + (UIColor *) colorWithHexString: (NSString *)color; 55 | @end 56 | -------------------------------------------------------------------------------- /callkiller-gui/JGProgressHUD/JGProgressHUDFadeAnimation.m: -------------------------------------------------------------------------------- 1 | // 2 | // JGProgressHUDFadeAnimation.m 3 | // JGProgressHUD 4 | // 5 | // Created by Jonas Gessner on 20.7.14. 6 | // Copyright (c) 2014 Jonas Gessner. All rights reserved. 7 | // 8 | 9 | #import "JGProgressHUDFadeAnimation.h" 10 | #import "JGProgressHUD.h" 11 | 12 | @implementation JGProgressHUDFadeAnimation 13 | 14 | #pragma mark - Initializers 15 | 16 | - (instancetype)init { 17 | self = [super init]; 18 | if (self) { 19 | self.duration = 0.4; 20 | self.animationOptions = UIViewAnimationOptionCurveEaseInOut; 21 | } 22 | return self; 23 | } 24 | 25 | - (void)setAnimationOptions:(UIViewAnimationOptions)animationOptions { 26 | _animationOptions = (animationOptions | UIViewAnimationOptionBeginFromCurrentState); 27 | } 28 | 29 | #pragma mark - Showing 30 | 31 | - (void)show { 32 | [super show]; 33 | 34 | self.progressHUD.alpha = 0.0; 35 | self.progressHUD.hidden = NO; 36 | 37 | [UIView animateWithDuration:self.duration delay:0.0 options:self.animationOptions animations:^{ 38 | self.progressHUD.alpha = 1.0; 39 | } completion:^(BOOL __unused finished) { 40 | [self animationFinished]; 41 | }]; 42 | } 43 | 44 | #pragma mark - Hiding 45 | 46 | - (void)hide { 47 | [super hide]; 48 | 49 | [UIView animateWithDuration:self.duration delay:0.0 options:self.animationOptions animations:^{ 50 | self.progressHUD.alpha = 0.0; 51 | } completion:^(BOOL __unused finished) { 52 | [self animationFinished]; 53 | }]; 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /callkiller-gui/JGProgressHUD/JGProgressHUDAnimation.h: -------------------------------------------------------------------------------- 1 | // 2 | // JGProgressHUDAnimation.h 3 | // JGProgressHUD 4 | // 5 | // Created by Jonas Gessner on 20.7.14. 6 | // Copyright (c) 2014 Jonas Gessner. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @class JGProgressHUD; 13 | 14 | /** 15 | You may subclass this class to create a custom progress indicator view. 16 | */ 17 | @interface JGProgressHUDAnimation : NSObject 18 | 19 | /** Convenience initializer. */ 20 | + (instancetype __nonnull)animation; 21 | 22 | /** The HUD using this animation. */ 23 | @property (nonatomic, weak, readonly, nullable) JGProgressHUD *progressHUD; 24 | 25 | /** 26 | The @c progressHUD is hidden from screen with @c alpha = 1 and @c hidden = @c YES. Ideally, you should prepare the HUD for presentation, then set @c hidden to @c NO on the @c progressHUD and then perform the animation. 27 | @post Call @c animationFinished. 28 | */ 29 | - (void)show NS_REQUIRES_SUPER; 30 | 31 | /** 32 | The @c progressHUD wis visible on screen with @c alpha = 1 and @c hidden = @c NO. You should only perform the animation in this method, the @c progressHUD itself will take care of hiding itself and removing itself from superview. 33 | @post Call @c animationFinished. 34 | */ 35 | - (void)hide NS_REQUIRES_SUPER; 36 | 37 | /** 38 | @pre This method should only be called at the end of a @c show or @c hide animaiton. 39 | @attention ALWAYS call this method after completing a @c show or @c hide animation. 40 | */ 41 | - (void)animationFinished NS_REQUIRES_SUPER; 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /callkiller/TUHandle.h: -------------------------------------------------------------------------------- 1 | // 2 | // TUHandle.h 3 | // callkiller 4 | // 5 | // Created by mac on 2018/7/12. 6 | // 7 | 8 | #ifndef TUHandle_h 9 | #define TUHandle_h 10 | 11 | @interface TUHandle : NSObject { 12 | 13 | long long _type; 14 | NSString* _value; 15 | 16 | } 17 | 18 | @property (nonatomic,copy,readonly) NSDictionary * dictionaryRepresentation; 19 | @property (assign,nonatomic) long long type; //@synthesize type=_type - In the implementation block 20 | @property (nonatomic,copy) NSString * value; //@synthesize value=_value - In the implementation block 21 | +(BOOL)supportsSecureCoding; 22 | +(id)stringForType:(long long)arg1 ; 23 | +(id)handleWithDestinationID:(id)arg1 ; 24 | +(id)handleWithDictionaryRepresentation:(id)arg1 ; 25 | +(id)handleWithPersonHandle:(id)arg1 ; 26 | -(id)init; 27 | -(id)initWithCoder:(id)arg1 ; 28 | -(void)encodeWithCoder:(id)arg1 ; 29 | -(BOOL)isEqual:(id)arg1 ; 30 | -(unsigned long long)hash; 31 | -(id)description; 32 | -(void)setType:(long long)arg1 ; 33 | -(long long)type; 34 | -(id)copyWithZone:(NSZone*)arg1 ; 35 | -(void)setValue:(NSString *)arg1 ; 36 | -(NSString *)value; 37 | -(NSDictionary *)dictionaryRepresentation; 38 | -(id)personHandle; 39 | -(BOOL)isEqualToHandle:(id)arg1 ; 40 | -(BOOL)isCanonicallyEqualToHandle:(id)arg1 isoCountryCode:(id)arg2 ; 41 | -(id)initWithDestinationID:(id)arg1 ; 42 | -(id)canonicalHandleForISOCountryCode:(id)arg1 ; 43 | -(id)initWithType:(long long)arg1 value:(id)arg2 ; 44 | @end 45 | 46 | #endif /* TUHandle_h */ 47 | -------------------------------------------------------------------------------- /statics/GCDObjC/GCDGroup.h: -------------------------------------------------------------------------------- 1 | // 2 | // GCDGroup.h 3 | // GCDObjC 4 | // 5 | // Copyright (c) 2012 Mark Smith. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | @interface GCDGroup : NSObject 11 | 12 | /** 13 | * Returns the underlying dispatch group object. 14 | * 15 | * @return The dispatch group object. 16 | */ 17 | @property (strong, readonly, nonatomic) dispatch_group_t dispatchGroup; 18 | 19 | /** 20 | * Initializes a new group. 21 | * 22 | * @return The initialized instance. 23 | * @see dispatch_group_create() 24 | */ 25 | - (instancetype)init; 26 | 27 | /** 28 | * The GCDGroup designated initializer. 29 | * 30 | * @param dispatchGroup A dispatch_group_t object. 31 | * @return The initialized instance. 32 | */ 33 | - (instancetype)initWithDispatchGroup:(dispatch_group_t)dispatchGroup; 34 | 35 | /** 36 | * Explicitly indicates that a block has entered the group. 37 | * 38 | * @see dispatch_group_enter() 39 | */ 40 | - (void)enter; 41 | 42 | /** 43 | * Explicitly indicates that a block in the group has completed. 44 | * 45 | * @see dispatch_group_leave() 46 | */ 47 | - (void)leave; 48 | 49 | /** 50 | * Waits forever for the previously submitted blocks in the group to complete. 51 | * 52 | * @see dispatch_group_wait() 53 | */ 54 | - (void)wait; 55 | 56 | /** 57 | * Waits for the previously submitted blocks in the group to complete. 58 | * 59 | * @param seconds The time to wait in seconds. 60 | * @return YES if all blocks completed, NO if the timeout occurred. 61 | * @see dispatch_group_wait() 62 | */ 63 | - (BOOL)wait:(double)seconds; 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /callkiller/CTCallCenter.h: -------------------------------------------------------------------------------- 1 | // 2 | // CTCallCenter.h 3 | // callkiller 4 | // 5 | // Created by mac on 2018/7/12. 6 | // 7 | 8 | #ifndef CTCallCenter_h 9 | #define CTCallCenter_h 10 | 11 | @class NSSet, CXCallObserver, NSString, CXCall; 12 | 13 | @interface CTCallCenter : NSObject// { 14 | 15 | // queue* _queue; 16 | // queue* clientQueue; 17 | // NSSet* _currentCalls; 18 | // /*^block*/id _callEventHandler; 19 | // CXCallObserver* _callKitObserver; 20 | // 21 | //} 22 | 23 | //@property (assign) CXCallObserver * callKitObserver; //@synthesize callKitObserver=_callKitObserver - In the implementation block 24 | @property (retain) NSSet * currentCalls; 25 | @property (nonatomic,copy) id callEventHandler; 26 | @property (readonly) unsigned long long hash; 27 | @property (readonly) Class superclass; 28 | @property (copy,readonly) NSString * description; 29 | @property (copy,readonly) NSString * debugDescription; 30 | -(BOOL)calculateCallStateChanges_sync:(id)arg1 ; 31 | //-(CXCallObserver *)callKitObserver; 32 | -(BOOL)getCurrentCallSetFromServer_sync:(id)arg1 ; 33 | -(id)callEventHandler; 34 | -(void)handleCallStatusChange_sync:(CXCall*)arg1 ; 35 | -(void)broadcastCallStateChangesIfNeededWithFailureLogMessage:(id)arg1 ; 36 | //-(void)setCallKitObserver:(CXCallObserver *)arg1 ; 37 | -(id)init; 38 | -(void)dealloc; 39 | -(void)initialize; 40 | -(NSString *)description; 41 | //-(id)initWithQueue:(dispatch_queue_sRef)arg1 ; 42 | -(void)setCallEventHandler:(id)arg1 ; 43 | -(NSSet *)currentCalls; 44 | -(void)setCurrentCalls:(NSSet *)arg1 ; 45 | -(void)callObserver:(id)arg1 callChanged:(id)arg2 ; 46 | @end 47 | 48 | #endif /* CTCallCenter_h */ 49 | -------------------------------------------------------------------------------- /callkiller-gui/AFNetworking/AFCompatibilityMacros.h: -------------------------------------------------------------------------------- 1 | // AFCompatibilityMacros.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 | #ifndef AFCompatibilityMacros_h 23 | #define AFCompatibilityMacros_h 24 | 25 | #ifdef API_UNAVAILABLE 26 | #define AF_API_UNAVAILABLE(x) API_UNAVAILABLE(x) 27 | #else 28 | #define AF_API_UNAVAILABLE(x) 29 | #endif // API_UNAVAILABLE 30 | 31 | #if __has_warning("-Wunguarded-availability-new") 32 | #define AF_CAN_USE_AT_AVAILABLE 1 33 | #else 34 | #define AF_CAN_USE_AT_AVAILABLE 0 35 | #endif 36 | 37 | #endif /* AFCompatibilityMacros_h */ 38 | -------------------------------------------------------------------------------- /callkiller-gui/JGProgressHUD/JGProgressHUDRingIndicatorView.h: -------------------------------------------------------------------------------- 1 | // 2 | // JGProgressHUDRingIndicatorView.h 3 | // JGProgressHUD 4 | // 5 | // Created by Jonas Gessner on 20.7.14. 6 | // Copyright (c) 2014 Jonas Gessner. All rights reserved. 7 | // 8 | 9 | #import "JGProgressHUD-Defines.h" 10 | #import "JGProgressHUDIndicatorView.h" 11 | 12 | /** 13 | A ring shaped determinate progress indicator. 14 | */ 15 | @interface JGProgressHUDRingIndicatorView : JGProgressHUDIndicatorView 16 | 17 | /** 18 | Initializes the indicator view and sets the correct color to match the HUD style. 19 | */ 20 | - (instancetype __nonnull)initWithHUDStyle:(JGProgressHUDStyle)style __attribute((deprecated(("This initializer is no longer needed. Use the init initializer method.")))); 21 | 22 | /** 23 | Background color of the ring. 24 | @attention Custom values need to be set after assigning the indicator view to @c JGProgressHUD's @c indicatorView property. 25 | 26 | @b Default: Black for JGProgressHUDStyleDark, light gray otherwise. 27 | */ 28 | @property (nonatomic, strong, nonnull) UIColor *ringBackgroundColor; 29 | 30 | /** 31 | Progress color of the progress ring. 32 | @attention Custom values need to be set after assigning the indicator view to @c JGProgressHUD's @c indicatorView property. 33 | 34 | @b Default: White for JGProgressHUDStyleDark, otherwise black. 35 | */ 36 | @property (nonatomic, strong, nonnull) UIColor *ringColor; 37 | 38 | /** 39 | Sets if the progress ring should have a rounded line cap. 40 | 41 | @b Default: NO. 42 | */ 43 | @property (nonatomic, assign) BOOL roundProgressLine; 44 | 45 | /** 46 | Width of the ring. 47 | 48 | @b Default: 3.0. 49 | */ 50 | @property (nonatomic, assign) CGFloat ringWidth; 51 | 52 | @end 53 | 54 | -------------------------------------------------------------------------------- /callkiller-gui/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 | -------------------------------------------------------------------------------- /callkiller-gui/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /statics/GCDObjC/GCDSemaphore.h: -------------------------------------------------------------------------------- 1 | // 2 | // GCDSemaphore.h 3 | // GCDObjC 4 | // 5 | // Copyright (c) 2012 Mark Smith. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | @interface GCDSemaphore : NSObject 11 | 12 | /** 13 | * Returns the underlying dispatch semaphore object. 14 | * 15 | * @return The dispatch semaphore object. 16 | */ 17 | @property (strong, readonly, nonatomic) dispatch_semaphore_t dispatchSemaphore; 18 | 19 | /** 20 | * Initializes a new semaphore with starting value 0. 21 | * 22 | * @return The initialized instance. 23 | * @see dispatch_semaphore_create() 24 | */ 25 | - (instancetype)init; 26 | 27 | /** 28 | * Initializes a new semaphore. 29 | * 30 | * @param value The starting value for the semaphore. 31 | * @return The initialized instance. 32 | * @see dispatch_semaphore_create() 33 | */ 34 | - (instancetype)initWithValue:(long)value; 35 | 36 | /** 37 | * The GCDSemaphore designated initializer. 38 | * 39 | * @param dispatchSemaphore A dispatch_semaphore_t object. 40 | * @return The initialized instance. 41 | * @see dispatch_semaphore_create() 42 | */ 43 | - (instancetype)initWithDispatchSemaphore:(dispatch_semaphore_t)dispatchSemaphore; 44 | 45 | /** 46 | * Signals (increments) the semaphore. 47 | * 48 | * @return YES if a thread is awoken, NO otherwise. 49 | * @see dispatch_semaphore_signal() 50 | */ 51 | - (BOOL)signal; 52 | 53 | /** 54 | * Waits forever for (decrements) the semaphore. 55 | * 56 | * @see dispatch_semaphore_wait() 57 | */ 58 | - (void)wait; 59 | 60 | /** 61 | * Waits for (decrements) the semaphore. 62 | * 63 | * @param seconds The time to wait in seconds. 64 | * @return YES on success, NO if the timeout occurred. 65 | * @see dispatch_semaphore_wait() 66 | */ 67 | - (BOOL)wait:(double)seconds; 68 | 69 | @end -------------------------------------------------------------------------------- /callkiller-gui/JGProgressHUD/JGProgressHUDErrorIndicatorView.m: -------------------------------------------------------------------------------- 1 | // 2 | // JGProgressHUDErrorIndicatorView.m 3 | // JGProgressHUD 4 | // 5 | // Created by Jonas Gessner on 19.08.14. 6 | // Copyright (c) 2014 Jonas Gessner. All rights reserved. 7 | // 8 | 9 | #import "JGProgressHUDErrorIndicatorView.h" 10 | #import "JGProgressHUD.h" 11 | 12 | @implementation JGProgressHUDErrorIndicatorView 13 | 14 | - (instancetype)initWithContentView:(UIView *__unused)contentView { 15 | NSBundle *currentBundle = [NSBundle bundleForClass:[self class]]; 16 | NSURL *resourceBundleURL = [currentBundle URLForResource:@"JGProgressHUD" withExtension:@"bundle"]; 17 | NSBundle *resourceBundle = currentBundle; 18 | if (resourceBundleURL) { 19 | resourceBundle = [NSBundle bundleWithURL:resourceBundleURL] ?: currentBundle; 20 | } 21 | 22 | NSString *imgPath = [resourceBundle pathForResource:@"jg_hud_error" ofType:@"png"]; 23 | self = [super initWithImage:[[UIImage imageWithContentsOfFile:imgPath] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]]; 24 | 25 | return self; 26 | } 27 | 28 | - (instancetype)init { 29 | return [self initWithContentView:nil]; 30 | } 31 | 32 | - (void)updateAccessibility { 33 | self.accessibilityLabel = NSLocalizedString(@"Error",); 34 | } 35 | 36 | - (void)setUpForHUDStyle:(JGProgressHUDStyle)style vibrancyEnabled:(BOOL)vibrancyEnabled { 37 | [super setUpForHUDStyle:style vibrancyEnabled:vibrancyEnabled]; 38 | 39 | if (style == JGProgressHUDStyleDark) { 40 | self.contentView.tintColor = [UIColor whiteColor]; 41 | } 42 | else { 43 | self.contentView.tintColor = [UIColor blackColor]; 44 | } 45 | } 46 | 47 | - (void)tintColorDidChange { 48 | [super tintColorDidChange]; 49 | self.contentView.tintColor = self.tintColor; 50 | } 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /callkiller-gui/JGProgressHUD/JGProgressHUDSuccessIndicatorView.m: -------------------------------------------------------------------------------- 1 | // 2 | // JGProgressHUDSuccessIndicatorView.m 3 | // JGProgressHUD 4 | // 5 | // Created by Jonas Gessner on 19.08.14. 6 | // Copyright (c) 2014 Jonas Gessner. All rights reserved. 7 | // 8 | 9 | #import "JGProgressHUDSuccessIndicatorView.h" 10 | #import "JGProgressHUD.h" 11 | 12 | @implementation JGProgressHUDSuccessIndicatorView 13 | 14 | - (instancetype)initWithContentView:(UIView *__unused)contentView { 15 | NSBundle *currentBundle = [NSBundle bundleForClass:[self class]]; 16 | NSURL *resourceBundleURL = [currentBundle URLForResource:@"JGProgressHUD" withExtension:@"bundle"]; 17 | NSBundle *resourceBundle = currentBundle; 18 | if (resourceBundleURL) { 19 | resourceBundle = [NSBundle bundleWithURL:resourceBundleURL] ?: currentBundle; 20 | } 21 | 22 | NSString *imgPath = [resourceBundle pathForResource:@"jg_hud_success" ofType:@"png"]; 23 | self = [super initWithImage:[[UIImage imageWithContentsOfFile:imgPath] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]]; 24 | 25 | return self; 26 | } 27 | 28 | - (instancetype)init { 29 | return [self initWithContentView:nil]; 30 | } 31 | 32 | - (void)updateAccessibility { 33 | self.accessibilityLabel = NSLocalizedString(@"Success",); 34 | } 35 | 36 | - (void)setUpForHUDStyle:(JGProgressHUDStyle)style vibrancyEnabled:(BOOL)vibrancyEnabled { 37 | [super setUpForHUDStyle:style vibrancyEnabled:vibrancyEnabled]; 38 | 39 | if (style == JGProgressHUDStyleDark) { 40 | self.contentView.tintColor = [UIColor whiteColor]; 41 | } 42 | else { 43 | self.contentView.tintColor = [UIColor blackColor]; 44 | } 45 | } 46 | 47 | - (void)tintColorDidChange { 48 | [super tintColorDidChange]; 49 | self.contentView.tintColor = self.tintColor; 50 | } 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /statics/MobileRegionDetector.mm: -------------------------------------------------------------------------------- 1 | // 2 | // MobileRegionDetector.m 3 | // statics 4 | // 5 | // Created by mac on 2018/7/26. 6 | // 7 | 8 | #import "MobileRegionDetector.h" 9 | #include "phonedata.h" 10 | 11 | #if TARGET_OS_SIMULATOR 12 | #define kCallKillerPreferenceFolder [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/callkiller"] 13 | #else 14 | #define kCallKillerPreferenceFolder @"/var/mobile/callkiller" 15 | #endif 16 | 17 | @interface MobileRegionDetector() { 18 | PhoneData *phonedata; 19 | } 20 | @end 21 | 22 | @implementation MobileRegionDetector 23 | 24 | +(instancetype)sharedInstance { 25 | static MobileRegionDetector *instance = nil; 26 | static dispatch_once_t onceToken; 27 | dispatch_once(&onceToken, ^{ 28 | instance = [[self alloc] init]; 29 | 30 | NSDirectoryEnumerator *iter = [[NSFileManager defaultManager] enumeratorAtPath:kCallKillerPreferenceFolder]; 31 | [iter skipDescendants]; 32 | NSString *pname; 33 | NSString *datFilePath = nil; 34 | while (pname = [iter nextObject]) { 35 | if ([pname hasPrefix:@"phone-"] && [pname hasSuffix:@".dat"]) { 36 | datFilePath = [kCallKillerPreferenceFolder stringByAppendingPathComponent:pname]; 37 | break; 38 | } 39 | } 40 | if (datFilePath.length > 0) 41 | instance->phonedata = new PhoneData([datFilePath UTF8String]); 42 | }); 43 | return instance; 44 | } 45 | -(NSString*)dbVersion { 46 | return [NSString stringWithUTF8String:phonedata->version().c_str()]; 47 | } 48 | -(NSString*)detectRegionCode:(NSString*)mobileNumber { 49 | std::string phone = [mobileNumber UTF8String]; 50 | const PhoneInfo& info = phonedata->lookUp(phone); 51 | return [NSString stringWithUTF8String:info.areaCode.c_str()]; 52 | } 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /statics/phonedata.h: -------------------------------------------------------------------------------- 1 | #ifndef _PHONEDATA_H_ 2 | #define _PHONEDATA_H_ 3 | 4 | #if defined(_WIN32) 5 | #if _MSC_VER >= 1600 6 | #pragma execution_character_set("utf-8") 7 | #else 8 | #error Visual Studio 2010 SP1 or above required 9 | #endif 10 | #endif 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | enum CARDTYPE 19 | { 20 | UNKNOWN = 0, // 未知,查找失败 21 | CMCC, // 中国移动 22 | CUCC, // 中国联通 23 | CTCC, // 中国电信 24 | CTCC_V, // 电信虚拟运营商 25 | CUCC_V, // 联通虚拟运营商 26 | CMCC_V // 移动虚拟运营商 27 | }; 28 | 29 | enum DATALEN 30 | { 31 | CHAR_LENGTH = 1, 32 | INT_LENGTH = 4, 33 | PHONE_LENGTH = 7, 34 | HEAD_LENGTH = 8, 35 | PHONE_INDEX_LENGTH = 9 36 | }; 37 | 38 | enum RECORD 39 | { 40 | PROVINCE = 0, // 省份 41 | CITY, // 城市 42 | ZIPCODE, // 邮编 43 | AREACODE // 长途区号 44 | }; 45 | 46 | std::string getPhoneType(CARDTYPE type); 47 | 48 | struct PhoneInfo 49 | { 50 | PhoneInfo() 51 | : type(UNKNOWN), phone(0) { } 52 | 53 | CARDTYPE type; 54 | uint32_t phone; 55 | std::string zipCode; 56 | std::string areaCode; 57 | std::string province; 58 | std::string city; 59 | }; 60 | 61 | struct DataHead 62 | { 63 | char version[4]; 64 | uint32_t offset; 65 | }; 66 | 67 | struct Record 68 | { 69 | uint32_t phone; 70 | uint32_t offset; 71 | uint8_t type; 72 | }; 73 | 74 | class PhoneData 75 | { 76 | public: 77 | PhoneData(const char *path); 78 | std::string version(); 79 | PhoneInfo lookUp(int64_t phone) const; 80 | PhoneInfo lookUp(const std::string &phone) const; 81 | 82 | private: 83 | PhoneInfo _lookUp(uint32_t phone7) const; 84 | static std::string getRecordContent(const std::vector &buffer, size_t startOffset); 85 | 86 | private: 87 | std::vector buffer; 88 | DataHead *head; 89 | size_t recordCount; 90 | }; 91 | 92 | #endif // !_PHONEDATA_H_ 93 | -------------------------------------------------------------------------------- /callkiller-gui/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | CallKiller 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.5.1 21 | CFBundleURLTypes 22 | 23 | 24 | CFBundleTypeRole 25 | Editor 26 | CFBundleURLName 27 | com.laoyur.callkiller 28 | CFBundleURLSchemes 29 | 30 | callkiller 31 | 32 | 33 | 34 | CFBundleVersion 35 | 1 36 | LSRequiresIPhoneOS 37 | 38 | NSAppTransportSecurity 39 | 40 | NSAllowsArbitraryLoads 41 | 42 | 43 | UILaunchStoryboardName 44 | LaunchScreen 45 | UIMainStoryboardFile 46 | Main 47 | UIRequiredDeviceCapabilities 48 | 49 | armv7 50 | 51 | UISupportedInterfaceOrientations 52 | 53 | UIInterfaceOrientationPortrait 54 | 55 | UISupportedInterfaceOrientations~ipad 56 | 57 | UIInterfaceOrientationPortrait 58 | UIInterfaceOrientationPortraitUpsideDown 59 | UIInterfaceOrientationLandscapeLeft 60 | UIInterfaceOrientationLandscapeRight 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /callkiller-gui/zh-Hans.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | 2 | "enabled" = "已启用"; 3 | "disabled" = "未启用"; 4 | "city-block-count-fmt" = "%ld 个城市"; 5 | "record-count-fmt" = "%ld 条记录"; 6 | "no-config" = "未配置"; 7 | "no-records" = "无记录"; 8 | "no-donation" = "尚无捐赠"; 9 | "donation-list" = "捐赠名单"; 10 | "donate-alipay" = "支付宝捐赠"; 11 | "error-title" = "出错了"; 12 | "error-content" = "服务器无响应,或网络错误"; 13 | "donate-alert-title-1" = "感谢您的支持!\n%@"; 14 | "donate-alert-title-2" = "即将跳转到支付宝,请在转账附言中留下您的昵称,以便显示在「捐赠名单」中。"; 15 | "donate-alipay-copied" = "支付宝账号已拷贝"; 16 | 17 | "ok" = "确定"; 18 | "cancel" = "取消"; 19 | "delete" = "删除"; 20 | 21 | "edit-comment" = "修改备注"; 22 | "comment" = "备注"; 23 | "comment-optional" = "备注 (选填)"; 24 | "enter-number" = "输入号码"; 25 | "duplicated-entry" = "重复条目,无法添加!"; 26 | "format-not-supported" = "不支持的格式!"; 27 | "blacklist-example" = "支持通配符(?、*)\n? 代表单个数字,\n* 代表0个或任意个数字。\n\n示例1:指定号码,10086\n示例2:指定号段,05128286*\n示例3:固定位数,1381234????\n\n请勿添加86前缀"; 28 | "add-blacklist" = "增加黑名单"; 29 | "del-all-blacklist-prompt" = "确定清空黑名单?"; 30 | 31 | "enter-keyword-prompt" = "输入关键词"; 32 | "add-keyword-title" = "增加关键词"; 33 | "add-keyword-content" = "不支持通配符"; 34 | "del-all-keywords-prompt" = "确定清空关键词?"; 35 | 36 | "enter-prefix-prompt" = "输入前缀"; 37 | "add-prefix-title" = "增加前缀"; 38 | "add-prefix-content" = "支持英文问号?通配符,代表单个数字"; 39 | "del-all-prefixes-prompt" = "确定清空所有前缀?"; 40 | 41 | "unknown" = "未知"; 42 | "mobile-query-location-fmt" = "查询耗时:%.6f ms\n归属地:%@\n区号:%@"; 43 | "mobile-query-placeholer" = "请输入11位手机号"; 44 | "mobile-query-alert-title" = "归属地查询"; 45 | "invalid-mobile-format" = "不正确的手机号!"; 46 | 47 | "eula-content" = "本软件为免费软件。\n因使用本软件而引起的任何问题和责任(包括但不限于数据丢失、设备故障、漏接电话等),均由使用者本人承担。\n如果你不能接受,请立刻卸载本软件。\n个人开发者的辛酸与不易,望理解,更何况这是一款免费软件。"; 48 | "check-all" = "全选中"; 49 | "uncheck-all" = "全取消"; 50 | 51 | "block-reason-unknown-number" = "未知号码"; 52 | "block-reason-landline" = "区号拦截"; 53 | "block-reason-mobile" = "归属地拦截"; 54 | "block-reason-blacklist" = "黑名单拦截"; 55 | "block-reason-keywords" = "关键词拦截"; 56 | "block-reason-unknown" = "未知拦截类型"; 57 | "block-reason-system" = "系统黑名单"; 58 | 59 | "trash-history-alert-title" = "清空拦截记录"; 60 | "trash-history-alert-content" = "确定清空吗?此操作无法恢复。"; 61 | 62 | "restart-mp-prompt" = "此改动在强杀电话应用后才能生效!"; 63 | -------------------------------------------------------------------------------- /callkiller/MPRecentsTableViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // MPRecentsTableViewCell.h 3 | // callkiller 4 | // 5 | // Created by mac on 2018/8/1. 6 | // 7 | 8 | #ifndef MPRecentsTableViewCell_h 9 | #define MPRecentsTableViewCell_h 10 | 11 | @interface MPRecentsTableViewCell : UITableViewCell 12 | //{ 13 | // NSDictionary *_allViewsDictionary; 14 | // long long _buildConstraintsOnceToken; 15 | // NSLayoutConstraint *_topConstraint; 16 | // NSLayoutConstraint *_bottomConstraint; 17 | // NSLayoutConstraint *_dateConstraint; 18 | // NSLayoutConstraint *_dateYConstraint; 19 | // NSLayoutConstraint *_labelConstraint; 20 | // CHRecentCall *_call; 21 | // UILabel *_callerCountLabel; 22 | // UIDateLabel *_callerDateLabel; 23 | // UILabel *_callerLabelLabel; 24 | // UILabel *_callerNameLabel; 25 | // UIImageView *_callTypeIconView; 26 | //} 27 | 28 | + (id)allMetrics; 29 | + (double)minimumRowHeight; 30 | + (double)marginWidth; 31 | + (double)editingMarginWidth; 32 | + (id)_sharedTTYRelayImage; 33 | + (id)_sharedTTYDirectImage; 34 | + (id)_sharedOutgoingFaceTimeImage; 35 | + (id)_sharedOutgoingCallImage; 36 | @property(retain, nonatomic) UIImageView *callTypeIconView; // @synthesize callTypeIconView=_callTypeIconView; 37 | @property(retain, nonatomic) UILabel *callerNameLabel; // @synthesize callerNameLabel=_callerNameLabel; 38 | @property(retain, nonatomic) UILabel *callerLabelLabel; // @synthesize callerLabelLabel=_callerLabelLabel; 39 | //@property(retain, nonatomic) UIDateLabel *callerDateLabel; // @synthesize callerDateLabel=_callerDateLabel; 40 | @property(retain, nonatomic) UILabel *callerCountLabel; // @synthesize callerCountLabel=_callerCountLabel; 41 | //@property(retain, nonatomic) CHRecentCall *call; // @synthesize call=_call; 42 | //- (void).cxx_destruct; 43 | - (void)_updateFonts; 44 | - (void)_handleContentSizeDidChange:(id)arg1; 45 | - (void)_updateConstraints; 46 | - (void)_buildConstraints; 47 | - (void)setEditing:(_Bool)arg1 animated:(_Bool)arg2; 48 | @property(readonly) NSDictionary *allMetrics; // @dynamic allMetrics; 49 | @property(readonly) NSDictionary *allViews; // @dynamic allViews; 50 | @property(readonly) long long count; // @dynamic count; 51 | - (void)dealloc; 52 | - (void)commonInit; 53 | - (id)initWithStyle:(long long)arg1 reuseIdentifier:(id)arg2; 54 | - (id)initWithFrame:(struct CGRect)arg1; 55 | - (id)initWithCoder:(id)arg1; 56 | - (id)init; 57 | 58 | @end 59 | 60 | #endif /* MPRecentsTableViewCell_h */ 61 | -------------------------------------------------------------------------------- /callkiller-gui/JGProgressHUD/JGProgressHUDIndicatorView.h: -------------------------------------------------------------------------------- 1 | // 2 | // JGProgressHUDIndicatorView.h 3 | // JGProgressHUD 4 | // 5 | // Created by Jonas Gessner on 20.7.14. 6 | // Copyright (c) 2014 Jonas Gessner. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "JGProgressHUD-Defines.h" 12 | 13 | /** You may subclass this class to create a custom progress indicator view. */ 14 | @interface JGProgressHUDIndicatorView : UIView 15 | 16 | /** 17 | Designated initializer for this class. 18 | 19 | @param contentView The content view to place on the container view (the container is the JGProgressHUDIndicatorView). 20 | */ 21 | - (instancetype __nonnull)initWithContentView:(UIView *__nullable)contentView; 22 | 23 | /** Use this method to set up the indicator view to fit the HUD style and vibrancy setting. This method is called by @c JGProgressHUD when the indicator view is added to the HUD and when the HUD's @c vibrancyEnabled property changes. This method may be called multiple times with different values. The default implementation does nothing. */ 24 | - (void)setUpForHUDStyle:(JGProgressHUDStyle)style vibrancyEnabled:(BOOL)vibrancyEnabled; 25 | 26 | /** Ranges from 0.0 to 1.0. */ 27 | @property (nonatomic, assign) float progress; 28 | 29 | /** 30 | Adjusts the current progress shown by the receiver, optionally animating the change. 31 | 32 | The current progress is represented by a floating-point value between 0.0 and 1.0, inclusive, where 1.0 indicates the completion of the task. The default value is 0.0. Values less than 0.0 and greater than 1.0 are pinned to those limits. 33 | 34 | @param progress The new progress value. 35 | @param animated YES if the change should be animated, NO if the change should happen immediately. 36 | */ 37 | - (void)setProgress:(float)progress animated:(BOOL)animated; 38 | 39 | /** 40 | The content view which displays the progress. 41 | */ 42 | @property (nonatomic, strong, readonly, nullable) UIView *contentView; 43 | 44 | /** Schedules an accessibility update on the next run loop. */ 45 | - (void)setNeedsAccessibilityUpdate; 46 | 47 | /** 48 | Runs @c updateAccessibility immediately if an accessibility update has been scheduled (through @c setNeedsAccessibilityUpdate) but has not executed yet. 49 | */ 50 | - (void)updateAccessibilityIfNeeded; 51 | 52 | /** 53 | Override to set custom accessibility properties. This method gets called once when initializing the view and after calling @c setNeedsAccessibilityUpdate. 54 | */ 55 | - (void)updateAccessibility; 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /callkiller-gui/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "AppIcon60x60@2xiPhoneNotification_20pt@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "AppIcon60x60@2xiPhoneNotification_20pt@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "AppIcon60x60@2xiPhoneSpootlight5_29pt@2x.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "AppIcon60x60@2xiPhoneSpootlight5_29pt@3x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "40x40", 29 | "idiom" : "iphone", 30 | "filename" : "AppIcon60x60@2xiPhoneSpootlight7_40pt@2x.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "AppIcon60x60@2xiPhoneSpootlight7_40pt@3x.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "60x60", 41 | "idiom" : "iphone", 42 | "filename" : "AppIcon60x60@2xiPhoneApp_60pt@2x.png", 43 | "scale" : "2x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "AppIcon60x60@2xiPhoneApp_60pt@3x.png", 49 | "scale" : "3x" 50 | }, 51 | { 52 | "idiom" : "ipad", 53 | "size" : "20x20", 54 | "scale" : "1x" 55 | }, 56 | { 57 | "idiom" : "ipad", 58 | "size" : "20x20", 59 | "scale" : "2x" 60 | }, 61 | { 62 | "idiom" : "ipad", 63 | "size" : "29x29", 64 | "scale" : "1x" 65 | }, 66 | { 67 | "idiom" : "ipad", 68 | "size" : "29x29", 69 | "scale" : "2x" 70 | }, 71 | { 72 | "idiom" : "ipad", 73 | "size" : "40x40", 74 | "scale" : "1x" 75 | }, 76 | { 77 | "idiom" : "ipad", 78 | "size" : "40x40", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "idiom" : "ipad", 83 | "size" : "76x76", 84 | "scale" : "1x" 85 | }, 86 | { 87 | "idiom" : "ipad", 88 | "size" : "76x76", 89 | "scale" : "2x" 90 | }, 91 | { 92 | "idiom" : "ipad", 93 | "size" : "83.5x83.5", 94 | "scale" : "2x" 95 | }, 96 | { 97 | "idiom" : "ios-marketing", 98 | "size" : "1024x1024", 99 | "scale" : "1x" 100 | } 101 | ], 102 | "info" : { 103 | "version" : 1, 104 | "author" : "xcode" 105 | } 106 | } -------------------------------------------------------------------------------- /callkiller-gui/JGProgressHUD/JGProgressHUD-Defines.h: -------------------------------------------------------------------------------- 1 | // 2 | // JGProgressHUD-Defines.h 3 | // JGProgressHUD 4 | // 5 | // Created by Jonas Gessner on 28.04.15. 6 | // Copyright (c) 2015 Jonas Gessner. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /** 12 | Positions of the HUD. 13 | */ 14 | typedef NS_ENUM(NSUInteger, JGProgressHUDPosition) { 15 | /** Center position. */ 16 | JGProgressHUDPositionCenter = 0, 17 | /** Top left position. */ 18 | JGProgressHUDPositionTopLeft, 19 | /** Top center position. */ 20 | JGProgressHUDPositionTopCenter, 21 | /** Top right position. */ 22 | JGProgressHUDPositionTopRight, 23 | /** Center left position. */ 24 | JGProgressHUDPositionCenterLeft, 25 | /** Center right position. */ 26 | JGProgressHUDPositionCenterRight, 27 | /** Bottom left position. */ 28 | JGProgressHUDPositionBottomLeft, 29 | /** Bottom center position. */ 30 | JGProgressHUDPositionBottomCenter, 31 | /** Bottom right position. */ 32 | JGProgressHUDPositionBottomRight 33 | }; 34 | 35 | /** 36 | Appearance styles of the HUD. 37 | */ 38 | typedef NS_ENUM(NSUInteger, JGProgressHUDStyle) { 39 | /** Extra light HUD with dark elements. */ 40 | JGProgressHUDStyleExtraLight = 0, 41 | /** Light HUD with dark elemets. */ 42 | JGProgressHUDStyleLight, 43 | /** Dark HUD with light elements. */ 44 | JGProgressHUDStyleDark 45 | }; 46 | 47 | #if TARGET_OS_IOS 48 | /** 49 | Interaction types. 50 | */ 51 | typedef NS_ENUM(NSUInteger, JGProgressHUDInteractionType) { 52 | /** Block all touches. No interaction behin the HUD is possible. */ 53 | JGProgressHUDInteractionTypeBlockAllTouches = 0, 54 | /** Block touches on the HUD view. */ 55 | JGProgressHUDInteractionTypeBlockTouchesOnHUDView, 56 | /** Block no touches. */ 57 | JGProgressHUDInteractionTypeBlockNoTouches 58 | }; 59 | #endif 60 | 61 | /** 62 | Parallax Modes. 63 | */ 64 | typedef NS_ENUM(NSUInteger, JGProgressHUDParallaxMode) { 65 | /** Follows the device setting for parallax. If "Reduce Motion" is enabled, no parallax effect is added to the HUD, if "Reduce Motion" is disabled the HUD will have a parallax effect. This behaviour is only supported on iOS 8 and higher. */ 66 | JGProgressHUDParallaxModeDevice = 0, 67 | /** Always adds a parallax effect to the HUD. Parallax is only supported on iOS 7 and higher. */ 68 | JGProgressHUDParallaxModeAlwaysOn, 69 | /** Never adds a parallax effect to the HUD. */ 70 | JGProgressHUDParallaxModeAlwaysOff 71 | }; 72 | 73 | #ifndef fequal 74 | /** 75 | Macro for safe floating point comparison (for internal use in JGProgressHUD). 76 | */ 77 | #define fequal(a,b) (fabs((a) - (b)) < FLT_EPSILON) 78 | #endif 79 | -------------------------------------------------------------------------------- /callkiller-gui/en.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | 2 | "enabled" = "Enabled"; 3 | "disabled" = "Disabled"; 4 | "city-block-count-fmt" = "%ld cities"; 5 | "record-count-fmt" = "%ld records"; 6 | "no-config" = "no items"; 7 | "no-records" = "no items"; 8 | "no-donation" = "No donations"; 9 | "donation-list" = "Donation list"; 10 | "donate-alipay" = "Donate with Alipay"; 11 | "error-title" = "Error"; 12 | "error-content" = "Server or network error"; 13 | "donate-alert-title-1" = "Thanks for your support!\n%@"; 14 | "donate-alert-title-2" = "Navigating to Alipay, please leave your nickname in transfer note. I will add your nickname in donation list."; 15 | "donate-alipay-copied" = "Alipay account has been copied to your pastedboard."; 16 | 17 | "ok" = "Ok"; 18 | "cancel" = "Cancel"; 19 | "delete" = "Delete"; 20 | 21 | "edit-comment" = "Edit comment"; 22 | "comment" = "Comment"; 23 | "comment-optional" = "Comment (optional)"; 24 | "enter-number" = "Enter number"; 25 | "duplicated-entry" = "Duplicated!"; 26 | "format-not-supported" = "Unsupported format!"; 27 | "blacklist-example" = "Wildcard is supported(? and *) \n? is for a single digit,\n* is for 0, 1 or multiple digits.\n\neg1: specific number, 10086\neg2: specific prefix, 05128286*\neg3: fixed length, 1381234????\n\nDo NOT add country prefix."; 28 | "add-blacklist" = "Add blacklist"; 29 | "del-all-blacklist-prompt" = "Sure to delete all blacklist?"; 30 | 31 | "enter-keyword-prompt" = "Enter keyword"; 32 | "add-keyword-title" = "Add keyword"; 33 | "add-keyword-content" = "Wildcard is NOT supported"; 34 | "del-all-keywords-prompt" = "Sure to delete all keywords?"; 35 | 36 | "enter-prefix-prompt" = "Enter prefix"; 37 | "add-prefix-title" = "Add prefix"; 38 | "add-prefix-content" = "Wildcard ? is supported for a single digit"; 39 | "del-all-prefixes-prompt" = "Sure to delete all items?"; 40 | 41 | "unknown" = "Unknown"; 42 | "mobile-query-location-fmt" = "time cost:%.6f ms\ncity:%@\narea number:%@"; 43 | "mobile-query-placeholer" = "Please enter mobile phone number"; 44 | "mobile-query-alert-title" = "Mobile area query"; 45 | "invalid-mobile-format" = "Invalid mobile phone number!"; 46 | 47 | "eula-content" = "Take your own risk to use this tweak! \nThe developer takes no responsibility for your missing calls."; 48 | "check-all" = "Check All"; 49 | "uncheck-all" = "Uncheck All"; 50 | 51 | "block-reason-unknown-number" = "Unknwon number"; 52 | "block-reason-landline" = "Landline area"; 53 | "block-reason-mobile" = "Mobile area"; 54 | "block-reason-blacklist" = "Blacklist"; 55 | "block-reason-keywords" = "Keywords"; 56 | "block-reason-unknown" = "Unknown reason"; 57 | "block-reason-system" = "Blocked by system"; 58 | 59 | "trash-history-alert-title" = "Clear all history"; 60 | "trash-history-alert-content" = "Sure to clear all history, cannot undo."; 61 | 62 | "restart-mp-prompt" = "You need to restart Phone app to view the change."; 63 | -------------------------------------------------------------------------------- /callkiller/CXCall.h: -------------------------------------------------------------------------------- 1 | // 2 | // CXCall.h 3 | // callkiller 4 | // 5 | // Created by mac on 2018/7/12. 6 | // 7 | 8 | #ifndef CXCall_h 9 | #define CXCall_h 10 | 11 | @interface CXCall : NSObject // { 12 | 13 | // BOOL _outgoing; 14 | // BOOL _onHold; 15 | // BOOL _hasConnected; 16 | // BOOL _hasEnded; 17 | // BOOL _endpointOnCurrentDevice; 18 | // BOOL _hostedOnCurrentDevice; 19 | // NSUUID* _UUID; 20 | // 21 | //} 22 | 23 | @property (assign,getter=isOutgoing,nonatomic) BOOL outgoing; //@synthesize outgoing=_outgoing - In the implementation block 24 | @property (assign,getter=isOnHold,nonatomic) BOOL onHold; //@synthesize onHold=_onHold - In the implementation block 25 | @property (assign,nonatomic) BOOL hasConnected; //@synthesize hasConnected=_hasConnected - In the implementation block 26 | @property (assign,nonatomic) BOOL hasEnded; //@synthesize hasEnded=_hasEnded - In the implementation block 27 | @property (assign,getter=isEndpointOnCurrentDevice,nonatomic) BOOL endpointOnCurrentDevice; //@synthesize endpointOnCurrentDevice=_endpointOnCurrentDevice - In the implementation block 28 | @property (assign,getter=isHostedOnCurrentDevice,nonatomic) BOOL hostedOnCurrentDevice; //@synthesize hostedOnCurrentDevice=_hostedOnCurrentDevice - In the implementation block 29 | @property (nonatomic,copy,readonly) NSUUID * UUID; //@synthesize UUID=_UUID - In the implementation block 30 | @property (readonly) unsigned long long hash; 31 | @property (readonly) Class superclass; 32 | @property (copy,readonly) NSString * description; 33 | @property (copy,readonly) NSString * debugDescription; 34 | +(BOOL)supportsSecureCoding; 35 | -(void)setHasConnected:(BOOL)arg1 ; 36 | -(id)init; 37 | -(id)initWithCoder:(id)arg1 ; 38 | -(void)encodeWithCoder:(id)arg1 ; 39 | -(BOOL)isEqual:(id)arg1 ; 40 | -(unsigned long long)hash; 41 | -(id)copyWithZone:(NSZone*)arg1 ; 42 | -(NSUUID *)UUID; 43 | -(id)initWithUUID:(id)arg1 ; 44 | -(BOOL)isHostedOnCurrentDevice; 45 | -(BOOL)isEndpointOnCurrentDevice; 46 | -(void)setHostedOnCurrentDevice:(BOOL)arg1 ; 47 | -(void)setEndpointOnCurrentDevice:(BOOL)arg1 ; 48 | -(BOOL)isEqualToCall:(id)arg1 ; 49 | -(void)updateCopy:(id)arg1 withZone:(NSZone*)arg2 ; 50 | -(id)sanitizedCopyWithZone:(NSZone*)arg1 ; 51 | -(void)updateSanitizedCopy:(id)arg1 withZone:(NSZone*)arg2 ; 52 | -(id)sanitizedCopy; 53 | -(void)setOnHold:(BOOL)arg1 ; 54 | -(void)setHasEnded:(BOOL)arg1 ; 55 | -(void)setOutgoing:(BOOL)arg1 ; 56 | -(BOOL)isOutgoing; 57 | -(BOOL)hasConnected; 58 | -(BOOL)hasEnded; 59 | -(BOOL)isOnHold; 60 | @end 61 | 62 | #endif /* CXCall_h */ 63 | -------------------------------------------------------------------------------- /callkiller-gui/JGProgressHUD/JGProgressHUDIndicatorView.m: -------------------------------------------------------------------------------- 1 | // 2 | // JGProgressHUDIndicatorView.m 3 | // JGProgressHUD 4 | // 5 | // Created by Jonas Gessner on 20.7.14. 6 | // Copyright (c) 2014 Jonas Gessner. All rights reserved. 7 | // 8 | 9 | #import "JGProgressHUDIndicatorView.h" 10 | #import "JGProgressHUD.h" 11 | 12 | @interface JGProgressHUDIndicatorView () { 13 | BOOL _accessibilityUpdateScheduled; 14 | } 15 | 16 | + (void)runBlock:(void (^)(void))block; 17 | 18 | @end 19 | 20 | static void runOnNextRunLoop(void (^block)(void)) { 21 | [[NSRunLoop currentRunLoop] performSelector:@selector(runBlock:) target:[JGProgressHUDIndicatorView class] argument:(id)block order:0 modes:@[NSRunLoopCommonModes]]; 22 | } 23 | 24 | @implementation JGProgressHUDIndicatorView 25 | 26 | #pragma mark - Initializers 27 | 28 | - (instancetype)initWithFrame:(CGRect __unused)frame { 29 | return [self init]; 30 | } 31 | 32 | - (instancetype)init { 33 | return [self initWithContentView:nil]; 34 | } 35 | 36 | - (instancetype)initWithContentView:(UIView *)contentView { 37 | self = [super initWithFrame:(contentView ? contentView.frame : CGRectMake(0.0, 0.0, 50.0, 50.0))]; 38 | if (self) { 39 | self.opaque = NO; 40 | self.backgroundColor = [UIColor clearColor]; 41 | 42 | self.isAccessibilityElement = YES; 43 | [self setNeedsAccessibilityUpdate]; 44 | 45 | if (contentView) { 46 | _contentView = contentView; 47 | 48 | [self addSubview:self.contentView]; 49 | } 50 | } 51 | return self; 52 | } 53 | 54 | #pragma mark - Setup 55 | 56 | - (void)setUpForHUDStyle:(JGProgressHUDStyle)style vibrancyEnabled:(BOOL)vibrancyEnabled {} 57 | 58 | #pragma mark - Accessibility 59 | 60 | + (void)runBlock:(void (^)(void))block { 61 | if (block != nil) { 62 | block(); 63 | } 64 | } 65 | 66 | - (void)setNeedsAccessibilityUpdate { 67 | if (!_accessibilityUpdateScheduled) { 68 | _accessibilityUpdateScheduled = YES; 69 | 70 | runOnNextRunLoop(^{ 71 | [self updateAccessibilityIfNeeded]; 72 | }); 73 | } 74 | } 75 | 76 | - (void)updateAccessibilityIfNeeded { 77 | if (_accessibilityUpdateScheduled) { 78 | [self updateAccessibility]; 79 | _accessibilityUpdateScheduled = NO; 80 | } 81 | } 82 | 83 | - (void)updateAccessibility { 84 | self.accessibilityLabel = [NSLocalizedString(@"Loading",) stringByAppendingFormat:@" %.f %%", self.progress]; 85 | } 86 | 87 | #pragma mark - Getters & Setters 88 | 89 | - (void)setProgress:(float)progress { 90 | [self setProgress:progress animated:NO]; 91 | } 92 | 93 | - (void)setProgress:(float)progress animated:(__unused BOOL)animated { 94 | if (fequal(self.progress, progress)) { 95 | return; 96 | } 97 | 98 | _progress = progress; 99 | 100 | [self setNeedsAccessibilityUpdate]; 101 | } 102 | 103 | @end 104 | -------------------------------------------------------------------------------- /callkiller-gui/AlertUtil.m: -------------------------------------------------------------------------------- 1 | // 2 | // AlertUtil.m 3 | // callkiller-gui 4 | // 5 | // Created by mac on 2018/7/19. 6 | // 7 | 8 | #import 9 | #import "AlertUtil.h" 10 | #import "JGProgressHUD.h" 11 | 12 | static JGProgressHUD *sharedHud = nil; 13 | 14 | @implementation AlertUtil 15 | 16 | + (void) showInfo:(NSString *)title message:(NSString *)msg { 17 | [AlertUtil showInfo:title message:msg onConfirm:nil]; 18 | } 19 | 20 | + (void) showInfo:(NSString *)title message:(NSString *)msg onConfirm:(void(^)(void))cb { 21 | UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:msg preferredStyle:UIAlertControllerStyleAlert]; 22 | [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { 23 | if (cb) 24 | cb(); 25 | }]]; 26 | [UIApplication.sharedApplication.keyWindow.rootViewController presentViewController:alert animated:YES completion:^{ 27 | // 28 | }]; 29 | } 30 | 31 | + (void) showQuery:(NSString *)title message:(NSString *)msg isDanger:(BOOL)danger onConfirm:(void(^)(void))cb { 32 | UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:msg preferredStyle:UIAlertControllerStyleAlert]; 33 | [alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]]; 34 | [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:danger ? UIAlertActionStyleDestructive : UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { 35 | if (cb) 36 | cb(); 37 | }]]; 38 | [UIApplication.sharedApplication.keyWindow.rootViewController presentViewController:alert animated:YES completion:^{ 39 | // 40 | }]; 41 | } 42 | 43 | + (void) hideHud { 44 | if (sharedHud) { 45 | [sharedHud dismissAnimated:NO]; 46 | } 47 | sharedHud = nil; 48 | } 49 | 50 | + (void) showWaitingHud:(NSString *)text { 51 | [AlertUtil hideHud]; 52 | sharedHud = [JGProgressHUD progressHUDWithStyle:JGProgressHUDStyleDark]; 53 | sharedHud.indicatorView = [JGProgressHUDIndeterminateIndicatorView new]; 54 | if (text) 55 | sharedHud.textLabel.text = text; 56 | [sharedHud showInView:UIApplication.sharedApplication.keyWindow.rootViewController.view animated:NO]; 57 | } 58 | 59 | + (void) updateHudText:(NSString *)text { 60 | if (sharedHud) { 61 | sharedHud.textLabel.text = text; 62 | } 63 | } 64 | 65 | + (void) showProgressHud:(NSString *)text { 66 | [AlertUtil hideHud]; 67 | sharedHud = [JGProgressHUD progressHUDWithStyle:JGProgressHUDStyleDark]; 68 | sharedHud.indicatorView = [JGProgressHUDPieIndicatorView new]; 69 | if (text) 70 | sharedHud.textLabel.text = text; 71 | [sharedHud showInView:UIApplication.sharedApplication.keyWindow.rootViewController.view animated:NO]; 72 | } 73 | 74 | + (void) updateHudProgress:(float)ratio { 75 | if (sharedHud) { 76 | [sharedHud setProgress:ratio animated:NO]; 77 | } 78 | } 79 | 80 | @end 81 | -------------------------------------------------------------------------------- /callkiller/TUCallNotificationManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // TUCallNotificationManager.h 3 | // callkiller 4 | // 5 | // Created by mac on 2018/7/11. 6 | // 7 | 8 | #ifndef TUCallNotificationManager_h 9 | #define TUCallNotificationManager_h 10 | 11 | @interface TUCallNotificationManager : NSObject { 12 | 13 | NSMutableArray* _deferredNotificationBlocks; 14 | 15 | } 16 | 17 | @property (nonatomic,retain) NSMutableArray * deferredNotificationBlocks; //@synthesize deferredNotificationBlocks=_deferredNotificationBlocks - In the implementation block 18 | -(void)_postNotificationName:(id)arg1 object:(id)arg2 ; 19 | -(void)_postNotificationName:(id)arg1 object:(id)arg2 userInfo:(id)arg3 ; 20 | -(void)postNotificationsForCall:(id)arg1 usingComparisonCall:(id)arg2 afterUpdatesInBlock:(/*^block*/id)arg3 ; 21 | -(void)deferNotificationsUntilAfterPerformingBlock:(/*^block*/id)arg1 ; 22 | -(void)postNotificationsForCallContainer:(id)arg1 afterUpdatesInBlock:(/*^block*/id)arg2 ; 23 | -(void)postNotificationsForCall:(id)arg1 afterUpdatesInBlock:(/*^block*/id)arg2 ; 24 | -(void)statusChangedForCall:(id)arg1 ; 25 | -(void)connectingChangedForCall:(id)arg1 ; 26 | -(void)connectedChangedForCall:(id)arg1 ; 27 | -(void)wantsHoldMusicChangedForCall:(id)arg1 ; 28 | -(void)endpointOnCurrentDeviceChangedForCall:(id)arg1 ; 29 | -(void)shouldSuppressRingtoneChangedForCall:(id)arg1 ; 30 | -(void)faceTimeIDStatusChangedForCall:(id)arg1 ; 31 | -(void)hardPauseDigitsStateChangedForCall:(id)arg1 ; 32 | -(void)needsManualInCallSoundsChangedForCall:(id)arg1 ; 33 | -(void)hasSentInvitationChangedForCall:(id)arg1 ; 34 | -(void)isUsingBasebandChangedForCall:(id)arg1 ; 35 | -(void)isOnHoldChangedForCall:(id)arg1 ; 36 | -(void)isUplinkMutedChangedForCall:(id)arg1 ; 37 | -(void)isSendingAudioChangedForCall:(id)arg1 ; 38 | -(void)isThirdPartyVideoChangedForCall:(id)arg1 ; 39 | -(void)mediaStalledChangedForCall:(id)arg1 ; 40 | -(void)videoDegradedChangedForCall:(id)arg1 ; 41 | -(void)videoPausedChangedForCall:(id)arg1 ; 42 | -(void)destinationIDChangedForCall:(id)arg1 ; 43 | -(void)displayContextChangedForCall:(id)arg1 ; 44 | -(void)isEmergencyChangedForCall:(id)arg1 ; 45 | -(void)audioPropertiesChangedForCall:(id)arg1 ; 46 | -(void)hasUpdatedAudioChangedForCall:(id)arg1 ; 47 | -(void)ttyTypeChangedForCall:(id)arg1 ; 48 | -(void)supportsTTYWithVoiceChangedForCall:(id)arg1 ; 49 | -(void)cameraTypeChangedForCall:(id)arg1 ; 50 | -(void)remoteScreenOrientationChangedForCall:(id)arg1 ; 51 | -(void)remoteScreenAspectRatioChangedForCall:(id)arg1 ; 52 | -(void)prefersExclusiveAccessToCellularNetworkChangedForCall:(id)arg1 ; 53 | -(void)remoteUplinkMutedChangedForCall:(id)arg1 ; 54 | -(void)modelChangedForCall:(id)arg1 ; 55 | -(void)remoteAspectRatioChangedForCall:(id)arg1 ; 56 | -(void)remoteVideoContentRectChangedForCall:(id)arg1 ; 57 | -(void)remoteCameraOrientationChangedForCall:(id)arg1 ; 58 | -(void)mediaPropertiesChangedForCall:(id)arg1 remoteAspectRatioDidChange:(BOOL)arg2 remoteCameraOrientationDidChange:(BOOL)arg3 ; 59 | -(NSMutableArray *)deferredNotificationBlocks; 60 | -(void)conferenceParticipantCallsChangedForCallContainer:(id)arg1 conferenceParticipantCalls:(id)arg2 ; 61 | -(void)setDeferredNotificationBlocks:(NSMutableArray *)arg1 ; 62 | -(void)postNotificationsForCall:(id)arg1 usingComparisonCall:(id)arg2 ; 63 | @end 64 | 65 | #endif /* TUCallNotificationManager_h */ 66 | -------------------------------------------------------------------------------- /callkiller-gui/JGProgressHUD/JGProgressHUDFadeZoomAnimation.m: -------------------------------------------------------------------------------- 1 | // 2 | // JGProgressHUDFadeZoomAnimation.m 3 | // JGProgressHUD 4 | // 5 | // Created by Jonas Gessner on 20.7.14. 6 | // Copyright (c) 2014 Jonas Gessner. All rights reserved. 7 | // 8 | 9 | #import "JGProgressHUDFadeZoomAnimation.h" 10 | #import "JGProgressHUD.h" 11 | 12 | @implementation JGProgressHUDFadeZoomAnimation 13 | 14 | #pragma mark - Initializers 15 | 16 | - (instancetype)init { 17 | self = [super init]; 18 | if (self) { 19 | self.shrinkAnimationDuaration = 0.2; 20 | self.expandAnimationDuaration = 0.1; 21 | self.expandScale = CGSizeMake(1.1, 1.1); 22 | } 23 | return self; 24 | } 25 | 26 | #pragma mark - Showing 27 | 28 | - (void)show { 29 | [super show]; 30 | 31 | self.progressHUD.alpha = 0.0; 32 | self.progressHUD.HUDView.transform = CGAffineTransformMakeScale(0.1, 0.1); 33 | 34 | NSTimeInterval totalDuration = self.expandAnimationDuaration+self.shrinkAnimationDuaration; 35 | 36 | self.progressHUD.hidden = NO; 37 | 38 | [UIView animateWithDuration:totalDuration delay:0.0 options:(UIViewAnimationOptions)(UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseInOut) animations:^{ 39 | self.progressHUD.alpha = 1.0; 40 | } completion:nil]; 41 | 42 | [UIView animateWithDuration:self.shrinkAnimationDuaration delay:0.0 options:(UIViewAnimationOptions)(UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionBeginFromCurrentState) animations:^{ 43 | self.progressHUD.HUDView.transform = CGAffineTransformMakeScale(self.expandScale.width, self.expandScale.height); 44 | } completion:^(BOOL __unused _finished) { 45 | [UIView animateWithDuration:self.expandAnimationDuaration delay:0.0 options:(UIViewAnimationOptions)(UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionBeginFromCurrentState) animations:^{ 46 | self.progressHUD.HUDView.transform = CGAffineTransformIdentity; 47 | } completion:^(BOOL __unused __finished) { 48 | [self animationFinished]; 49 | }]; 50 | }]; 51 | } 52 | 53 | #pragma mark - Hiding 54 | 55 | - (void)hide { 56 | [super hide]; 57 | 58 | NSTimeInterval totalDuration = self.expandAnimationDuaration+self.shrinkAnimationDuaration; 59 | 60 | [UIView animateWithDuration:totalDuration delay:0.0 options:(UIViewAnimationOptions)(UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseInOut) animations:^{ 61 | self.progressHUD.alpha = 0.0; 62 | } completion:nil]; 63 | 64 | [UIView animateWithDuration:self.expandAnimationDuaration delay:0.0 options:(UIViewAnimationOptions)(UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionBeginFromCurrentState) animations:^{ 65 | self.progressHUD.HUDView.transform = CGAffineTransformMakeScale(self.expandScale.width, self.expandScale.height); 66 | } completion:^(BOOL __unused _finished) { 67 | [UIView animateWithDuration:self.shrinkAnimationDuaration delay:0.0 options:(UIViewAnimationOptions)(UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionBeginFromCurrentState) animations:^{ 68 | self.progressHUD.HUDView.transform = CGAffineTransformMakeScale(0.1, 0.1); 69 | } completion:^(BOOL __unused __finished) { 70 | self.progressHUD.HUDView.transform = CGAffineTransformIdentity; 71 | 72 | [self animationFinished]; 73 | }]; 74 | }]; 75 | } 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /generate_deb.sh: -------------------------------------------------------------------------------- 1 | LDID_PATH=`which ldid` 2 | if [[ $LDID_PATH = "" ]]; then 3 | echo "ldid not installed" 4 | exit 0 5 | fi 6 | 7 | DPKG_PATH=`which dpkg-deb` 8 | if [[ $DPKG_PATH = "" ]]; then 9 | echo "dpkg-deb not installed" 10 | exit 0 11 | fi 12 | 13 | rm -fr DerivedData/callkiller/Build/Products/Release-iphoneos/* 14 | xcodebuild -project callkiller.xcodeproj -scheme callkiller -configuration Release clean 15 | xcodebuild -project callkiller.xcodeproj \ 16 | -scheme callkiller \ 17 | -configuration Release \ 18 | MonkeyDevDeviceIP="" \ 19 | MonkeyDevInstallOnAnyBuild=NO \ 20 | VALIDATE_PRODUCT=NO \ 21 | build 22 | 23 | if [[ $? -ne "0" ]]; then 24 | echo "callkiller build failed" 25 | exit 0 26 | fi 27 | 28 | xcodebuild -project callkiller.xcodeproj -scheme callkiller-gui -configuration Release clean 29 | xcodebuild -project callkiller.xcodeproj \ 30 | -scheme callkiller-gui \ 31 | -configuration Release \ 32 | MonkeyDevDeviceIP="" \ 33 | MonkeyDevInstallOnAnyBuild=NO \ 34 | VALIDATE_PRODUCT=NO \ 35 | build 36 | 37 | if [[ $? -ne "0" ]]; then 38 | echo "callkiller-gui build failed" 39 | exit 0 40 | fi 41 | 42 | sudo rm -fr dpkg-tmp 43 | mkdir -p dpkg-tmp/tmp/callkiller 44 | cp -r callkiller/Package/* dpkg-tmp/ 45 | cp phone-*.dat dpkg-tmp/tmp/callkiller/ 46 | rm -f dpkg-tmp/Library/.DS_Store 47 | rm -f dpkg-tmp/Library/.gitignore 48 | rm -f dpkg-tmp/Library/MobileSubstrate/.DS_Store 49 | rm -f dpkg-tmp/Library/MobileSubstrate/.gitignore 50 | rm -f dpkg-tmp/Library/MobileSubstrate/DynamicLibraries/.gitignore 51 | rm -f dpkg-tmp/Library/MobileSubstrate/DynamicLibraries/.DS_Store 52 | cp -f DerivedData/callkiller/Build/Products/Release-iphoneos/callkiller.dylib dpkg-tmp/Library/MobileSubstrate/DynamicLibraries/ 53 | mkdir -p dpkg-tmp/Applications 54 | cp -fr DerivedData/callkiller/Build/Products/Release-iphoneos/callkiller-gui.app dpkg-tmp/Applications/ 55 | rm -f dpkg-tmp/Applications/callkiller-gui.app/embedded.mobileprovision 56 | 57 | ldid -Scallkiller-gui/entitlements.xml dpkg-tmp/Applications/callkiller-gui.app/callkiller-gui 58 | 59 | sudo chown -R root:wheel dpkg-tmp/Applications/callkiller-gui.app 60 | 61 | rm -fr dpkg-tmp/DEBIAN/* 62 | VERSION=`/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' callkiller-gui/Info.plist` 63 | echo "Package: com.laoyur.callkiller" > dpkg-tmp/DEBIAN/control 64 | echo "Name: CallKiller" >> dpkg-tmp/DEBIAN/control 65 | echo "Version: ${VERSION}" >> dpkg-tmp/DEBIAN/control 66 | cat >> dpkg-tmp/DEBIAN/control <= 10.0), mobilesubstrate 71 | Conflicts: 72 | Replaces: 73 | Priority: optional 74 | Architecture: iphoneos-arm 75 | Author: laoyur 76 | dev: 77 | Homepage: 78 | Depiction: 79 | Maintainer: laoyur 80 | Icon: file:///Applications/callkiller-gui.app/AppIcon60x60@2x.png 81 | 82 | EOF 83 | 84 | cat > dpkg-tmp/DEBIAN/postinst << EOF 85 | #!/bin/sh 86 | mkdir -p /var/mobile/callkiller 87 | rm -f /var/mobile/callkiller/phone-*.dat 88 | mv /tmp/callkiller/* /var/mobile/callkiller/ 89 | rm -fr /tmp/callkiller 90 | chown -R mobile:mobile /var/mobile/callkiller 91 | chmod -R 755 /var/mobile/callkiller 92 | if [[ -e /var/mobile/callkiller-pref.json ]]; then 93 | chown mobile:mobile /var/mobile/callkiller-pref.json 94 | chmod 755 /var/mobile/callkiller-pref.json 95 | fi 96 | uicache 97 | exit 0 98 | EOF 99 | 100 | cat > dpkg-tmp/DEBIAN/postrm << EOF 101 | #!/bin/sh 102 | uicache 103 | exit 0 104 | EOF 105 | 106 | chmod a+x dpkg-tmp/DEBIAN/postinst 107 | chmod a+x dpkg-tmp/DEBIAN/postrm 108 | 109 | dpkg-deb -Z gzip --build dpkg-tmp callkiller-${VERSION}.deb 110 | sudo rm -fr dpkg-tmp 111 | -------------------------------------------------------------------------------- /statics/phonedata.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "phonedata.h" 3 | #include 4 | #include 5 | 6 | static std::vector ssplit(const std::string &str, const std::string &c) 7 | { 8 | std::vector vec; 9 | std::string::size_type pos1 = 0, pos2 = str.find(c); 10 | while (std::string::npos != pos2) 11 | { 12 | std::string tmp = str.substr(pos1, pos2 - pos1); 13 | if (!tmp.empty()) 14 | { 15 | vec.push_back(std::move(tmp)); 16 | } 17 | 18 | pos1 = pos2 + c.size(); 19 | pos2 = str.find(c, pos1); 20 | } 21 | if (pos1 < str.length()) 22 | { 23 | vec.push_back(str.substr(pos1)); 24 | } 25 | return vec; 26 | } 27 | 28 | std::string getPhoneType(CARDTYPE type) 29 | { 30 | assert(type > UNKNOWN && type <= CMCC_V); 31 | 32 | switch (type) 33 | { 34 | case UNKNOWN: 35 | return std::string("未知"); 36 | case CMCC: 37 | return std::string("中国移动"); 38 | case CUCC: 39 | return std::string("中国联通"); 40 | case CTCC: 41 | return std::string("中国电信"); 42 | case CTCC_V: 43 | return std::string("电信虚拟运营商"); 44 | case CUCC_V: 45 | return std::string("联通虚拟运营商"); 46 | case CMCC_V: 47 | return std::string("移动虚拟运营商"); 48 | default: 49 | return std::string(); 50 | } 51 | } 52 | 53 | PhoneData::PhoneData(const char *path) 54 | { 55 | std::ifstream stream(path, std::ios::binary); 56 | if (!stream.is_open()) 57 | { 58 | head = nullptr; 59 | return; 60 | } 61 | 62 | buffer = std::vector(std::istreambuf_iterator(stream), std::istreambuf_iterator()); 63 | head = reinterpret_cast(buffer.data()); 64 | recordCount = (buffer.size() - head->offset) / PHONE_INDEX_LENGTH; 65 | } 66 | 67 | std::string PhoneData::version() { 68 | char v[5] = {0}; 69 | strncpy(v, head->version, 4); 70 | return v; 71 | } 72 | 73 | PhoneInfo PhoneData::lookUp(int64_t phone) const 74 | { 75 | if (phone >= 1000000 && phone <= 99999999999) 76 | { 77 | while (phone > 9999999) 78 | { 79 | phone /= 10; 80 | } 81 | return _lookUp(static_cast(phone)); 82 | } 83 | 84 | return PhoneInfo(); 85 | } 86 | 87 | PhoneInfo PhoneData::lookUp(const std::string &phone) const 88 | { 89 | if (phone.size() >= 7 && phone.size() <= 11) 90 | { 91 | return _lookUp(std::stoul(phone.substr(0, 7))); 92 | } 93 | 94 | return PhoneInfo(); 95 | } 96 | 97 | PhoneInfo PhoneData::_lookUp(uint32_t phone7) const 98 | { 99 | if (head && phone7 >= 1000000 && phone7 <= 99999999999) 100 | { 101 | size_t left = 0; 102 | size_t right = recordCount; 103 | 104 | while (left <= right) 105 | { 106 | size_t middle = (left + right) / 2; 107 | size_t currentOffset = head->offset + middle * PHONE_INDEX_LENGTH; 108 | if (currentOffset >= buffer.size()) 109 | { 110 | return PhoneInfo(); 111 | } 112 | 113 | auto _buffer = std::vector(buffer.cbegin() + currentOffset, buffer.cbegin() + currentOffset + PHONE_INDEX_LENGTH); 114 | Record *_record = reinterpret_cast(_buffer.data()); 115 | 116 | if (_record->phone > phone7) 117 | { 118 | right = middle - 1; 119 | } 120 | else if (_record->phone < phone7) 121 | { 122 | left = middle + 1; 123 | } 124 | else 125 | { 126 | std::string recordContent = getRecordContent(buffer, _record->offset); 127 | std::vector contents = ssplit(recordContent, std::string("|")); 128 | PhoneInfo info; 129 | info.type = static_cast(_record->type); 130 | info.phone = _record->phone; 131 | info.province = contents[PROVINCE]; 132 | info.city = contents[CITY]; 133 | info.zipCode = contents[ZIPCODE]; 134 | info.areaCode = contents[AREACODE]; 135 | 136 | return info; 137 | } 138 | } 139 | } 140 | 141 | return PhoneInfo(); 142 | } 143 | 144 | std::string PhoneData::getRecordContent(const std::vector &buffer, size_t startOffset) 145 | { 146 | size_t endOffset = std::find(buffer.cbegin() + startOffset, buffer.cend(), '\0') - buffer.cbegin(); 147 | return std::string(buffer.cbegin() + startOffset, buffer.cbegin() + endOffset); 148 | } 149 | -------------------------------------------------------------------------------- /statics/GCDObjC/GCDQueue.m: -------------------------------------------------------------------------------- 1 | // 2 | // GCDQueue.m 3 | // GCDObjC 4 | // 5 | // Copyright (c) 2012 Mark Smith. All rights reserved. 6 | // 7 | 8 | #import "GCDGroup.h" 9 | #import "GCDQueue.h" 10 | 11 | static GCDQueue *mainQueue; 12 | static GCDQueue *globalQueue; 13 | static GCDQueue *highPriorityGlobalQueue; 14 | static GCDQueue *lowPriorityGlobalQueue; 15 | static GCDQueue *backgroundPriorityGlobalQueue; 16 | 17 | static uint8_t mainQueueMarker[] = {0}; 18 | 19 | @interface GCDQueue () 20 | @property (strong, readwrite, nonatomic) dispatch_queue_t dispatchQueue; 21 | @end 22 | 23 | @implementation GCDQueue 24 | 25 | #pragma mark Global queue accessors. 26 | 27 | + (GCDQueue *)mainQueue { 28 | return mainQueue; 29 | } 30 | 31 | + (GCDQueue *)globalQueue { 32 | return globalQueue; 33 | } 34 | 35 | + (GCDQueue *)highPriorityGlobalQueue { 36 | return highPriorityGlobalQueue; 37 | } 38 | 39 | + (GCDQueue *)lowPriorityGlobalQueue { 40 | return lowPriorityGlobalQueue; 41 | } 42 | 43 | + (GCDQueue *)backgroundPriorityGlobalQueue { 44 | return backgroundPriorityGlobalQueue; 45 | } 46 | 47 | + (BOOL)isMainQueue { 48 | return dispatch_get_specific(mainQueueMarker) == mainQueueMarker; 49 | } 50 | 51 | #pragma mark Lifecycle. 52 | 53 | + (void)initialize { 54 | if (self == [GCDQueue class]) { 55 | mainQueue = [[GCDQueue alloc] initWithDispatchQueue:dispatch_get_main_queue()]; 56 | globalQueue = [[GCDQueue alloc] initWithDispatchQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)]; 57 | highPriorityGlobalQueue = [[GCDQueue alloc] initWithDispatchQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)]; 58 | lowPriorityGlobalQueue = [[GCDQueue alloc] initWithDispatchQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0)]; 59 | backgroundPriorityGlobalQueue = [[GCDQueue alloc] initWithDispatchQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)]; 60 | 61 | [mainQueue setContext:mainQueueMarker forKey:mainQueueMarker]; 62 | } 63 | } 64 | 65 | - (instancetype)init { 66 | return [self initSerial]; 67 | } 68 | 69 | - (instancetype)initSerial { 70 | return [self initWithDispatchQueue:dispatch_queue_create(nil, DISPATCH_QUEUE_SERIAL)]; 71 | } 72 | 73 | - (instancetype)initConcurrent { 74 | return [self initWithDispatchQueue:dispatch_queue_create(nil, DISPATCH_QUEUE_CONCURRENT)]; 75 | } 76 | 77 | - (instancetype)initWithDispatchQueue:(dispatch_queue_t)dispatchQueue { 78 | if ((self = [super init]) != nil) { 79 | self.dispatchQueue = dispatchQueue; 80 | } 81 | 82 | return self; 83 | } 84 | 85 | #pragma mark Public methods. 86 | 87 | - (void)queueBlock:(dispatch_block_t)block { 88 | dispatch_async(self.dispatchQueue, block); 89 | } 90 | 91 | - (void)queueBlock:(dispatch_block_t)block afterDelay:(double)seconds { 92 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (seconds * NSEC_PER_SEC)), self.dispatchQueue, block); 93 | } 94 | 95 | - (void)queueAndAwaitBlock:(dispatch_block_t)block { 96 | dispatch_sync(self.dispatchQueue, block); 97 | } 98 | 99 | - (void)queueAndAwaitBlock:(void (^)(size_t))block iterationCount:(size_t)count { 100 | dispatch_apply(count, self.dispatchQueue, block); 101 | } 102 | 103 | - (void)queueBlock:(dispatch_block_t)block inGroup:(GCDGroup *)group { 104 | dispatch_group_async(group.dispatchGroup, self.dispatchQueue, block); 105 | } 106 | 107 | - (void)queueNotifyBlock:(dispatch_block_t)block inGroup:(GCDGroup *)group { 108 | dispatch_group_notify(group.dispatchGroup, self.dispatchQueue, block); 109 | } 110 | 111 | - (void)queueBarrierBlock:(dispatch_block_t)block { 112 | dispatch_barrier_async(self.dispatchQueue, block); 113 | } 114 | 115 | - (void)queueAndAwaitBarrierBlock:(dispatch_block_t)block { 116 | dispatch_barrier_sync(self.dispatchQueue, block); 117 | } 118 | 119 | - (void)suspend { 120 | dispatch_suspend(self.dispatchQueue); 121 | } 122 | 123 | - (void)resume { 124 | dispatch_resume(self.dispatchQueue); 125 | } 126 | 127 | - (void *)contextForKey:(const void *)key { 128 | return dispatch_get_specific(key); 129 | } 130 | 131 | - (void)setContext:(void *)context forKey:(const void *)key { 132 | dispatch_queue_set_specific(self.dispatchQueue, key, context, NULL); 133 | } 134 | 135 | @end 136 | -------------------------------------------------------------------------------- /callkiller-gui/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // callkiller-gui 4 | // 5 | // Created by mac on 2018/7/18. 6 | // 7 | 8 | #import "AppDelegate.h" 9 | #import "Preference.h" 10 | #import "GCDObjC.h" 11 | 12 | @interface LSApplicationWorkspace : NSObject 13 | +(id)defaultWorkspace; 14 | -(BOOL)openApplicationWithBundleID:(id)arg1; 15 | @end 16 | 17 | @interface AppDelegate () 18 | 19 | @end 20 | 21 | @implementation AppDelegate 22 | 23 | 24 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 25 | // Override point for customization after application launch. 26 | return YES; 27 | } 28 | 29 | - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options { 30 | /** 31 | callkiller://add_to_blacklist/?from=com.apple.mobilephone&number=NUMBER&label=COMMENT 32 | */ 33 | if ([url.host isEqualToString:@"add_to_blacklist"]) { 34 | 35 | NSURLComponents *urlComponents = [NSURLComponents componentsWithURL:url 36 | resolvingAgainstBaseURL:NO]; 37 | NSString *number = nil; 38 | NSString *label = @""; 39 | NSString *from = @""; 40 | for (NSURLQueryItem *item in urlComponents.queryItems) { 41 | if ([item.name isEqualToString:@"number"]) { 42 | number = item.value; 43 | } else if ([item.name isEqualToString:@"label"]) { 44 | label = item.value; 45 | } else if ([item.name isEqualToString:@"from"]) { 46 | from = item.value; 47 | } 48 | } 49 | 50 | if (number.length) { 51 | NSMutableDictionary *pref = [[Preference sharedInstance] pref]; 52 | NSMutableArray *blacklist = pref[kKeyBlacklist]; 53 | if (!blacklist) { 54 | blacklist = [NSMutableArray new]; 55 | pref[kKeyBlacklist] = blacklist; 56 | } 57 | BOOL shouldAdd = YES; 58 | for (NSArray *item in blacklist) { 59 | if ([item[0] isEqualToString:number]) { 60 | shouldAdd = NO; 61 | break; 62 | } 63 | } 64 | if (shouldAdd) { 65 | NSString *pattern = [number stringByReplacingOccurrencesOfString:@"*" withString:@"\\d*"]; 66 | pattern = [pattern stringByReplacingOccurrencesOfString:@"?" withString:@"\\d"]; 67 | pattern = [NSString stringWithFormat:@"^%@$", pattern]; 68 | [blacklist addObject:@[number, pattern, label]]; 69 | [[Preference sharedInstance] save]; 70 | } 71 | 72 | [[GCDQueue mainQueue] queueBlock:^{ 73 | if (from.length) 74 | [[LSApplicationWorkspace defaultWorkspace] openApplicationWithBundleID:from]; 75 | } afterDelay:0.6]; 76 | } 77 | } 78 | return YES; 79 | } 80 | 81 | - (void)applicationWillResignActive:(UIApplication *)application { 82 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 83 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 84 | } 85 | 86 | 87 | - (void)applicationDidEnterBackground:(UIApplication *)application { 88 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 89 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 90 | } 91 | 92 | 93 | - (void)applicationWillEnterForeground:(UIApplication *)application { 94 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 95 | } 96 | 97 | 98 | - (void)applicationDidBecomeActive:(UIApplication *)application { 99 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 100 | } 101 | 102 | 103 | - (void)applicationWillTerminate:(UIApplication *)application { 104 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 105 | } 106 | 107 | 108 | @end 109 | -------------------------------------------------------------------------------- /callkiller-gui/zh-Hans.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | /* Class = "UILabel"; text = "全部拦截"; ObjectID = "0Yn-ZW-7iL"; */ 3 | "0Yn-ZW-7iL.text" = "全部拦截"; 4 | 5 | /* Class = "UILabel"; text = "Title"; ObjectID = "0v5-UI-jnG"; */ 6 | "0v5-UI-jnG.text" = "Title"; 7 | 8 | /* Class = "UILabel"; text = "Label"; ObjectID = "2Gx-NC-qzY"; */ 9 | "2Gx-NC-qzY.text" = "Label"; 10 | 11 | /* Class = "UILabel"; text = "Label"; ObjectID = "3Jm-sp-X7X"; */ 12 | "3Jm-sp-X7X.text" = "Label"; 13 | 14 | /* Class = "UINavigationItem"; title = "号码黑名单"; ObjectID = "3np-Tm-w3F"; */ 15 | "3np-Tm-w3F.title" = "号码黑名单"; 16 | 17 | /* Class = "UILabel"; text = "按区号拦截固话(中国内地)"; ObjectID = "4fu-3x-1WL"; */ 18 | "4fu-3x-1WL.text" = "按区号拦截固话 *"; 19 | 20 | /* Class = "UILabel"; text = "内地手机号归属地测试"; ObjectID = "Aby-nN-l5F"; */ 21 | "xK9-lI-N2e.text" = "内地手机号归属地查询"; 22 | 23 | /* Class = "UILabel"; text = "Label"; ObjectID = "Boe-Kq-JvX"; */ 24 | "Boe-Kq-JvX.text" = "Label"; 25 | 26 | /* Class = "UITableViewSection"; footerTitle = "* 关键词拦截功能,需要你自行安装“防骚扰大师”之类的App,并写入号码库到系统后,才能正常工作。CallKiller将对此类软件的识别结果进行关键词匹配。个人开发者精力和能力有限,难以自行维护号码数据库,望理解。"; ObjectID = "ENJ-Ja-TcT"; */ 27 | "ENJ-Ja-TcT.footerTitle" = "* 仅适用于中国内地\n** 关键词拦截功能,需要你自行安装“防骚扰大师”之类的App,并写入号码库到系统后,才能正常工作。CallKiller将对此类软件的识别结果进行关键词匹配。个人开发者精力和能力有限,难以自行维护号码数据库,望理解。"; 28 | 29 | /* Class = "UINavigationItem"; title = "按归属地拦截手机号"; ObjectID = "Ggw-PO-dFE"; */ 30 | "Ggw-PO-dFE.title" = "按归属地拦截手机号"; 31 | 32 | /* Class = "UINavigationItem"; title = "CallKiller"; ObjectID = "I1h-UH-vWR"; */ 33 | "I1h-UH-vWR.title" = "CallKiller"; 34 | 35 | /* Class = "UILabel"; text = "拦截「未知号码」"; ObjectID = "KOI-i6-3HF"; */ 36 | "KOI-i6-3HF.text" = "拦截「未知号码」"; 37 | 38 | /* Class = "UILabel"; text = "Label"; ObjectID = "La8-46-pNw"; */ 39 | "La8-46-pNw.text" = "Label"; 40 | 41 | /* Class = "UISearchBar"; placeholder = "输入关键字"; ObjectID = "Mxi-bD-0Lk"; */ 42 | "Mxi-bD-0Lk.placeholder" = "输入关键字"; 43 | 44 | /* Class = "UILabel"; text = "Title"; ObjectID = "OuF-I6-aFg"; */ 45 | "OuF-I6-aFg.text" = "Title"; 46 | 47 | /* Class = "UILabel"; text = "built with ♥ by laoyur"; ObjectID = "Q0p-kf-64s"; */ 48 | "Q0p-kf-64s.text" = "built with ♥ by laoyur"; 49 | 50 | /* Class = "UILabel"; text = "Label"; ObjectID = "Qod-Kr-Alc"; */ 51 | "Qod-Kr-Alc.text" = "Label"; 52 | 53 | /* Class = "UILabel"; text = "按归属地拦截手机号(中国内地)"; ObjectID = "Rvt-ix-4ru"; */ 54 | "Rvt-ix-4ru.text" = "按归属地拦截手机号 *"; 55 | 56 | /* Class = "UILabel"; text = "放行联系人"; ObjectID = "Ttl-2b-vDT"; */ 57 | "Ttl-2b-vDT.text" = "放行联系人"; 58 | 59 | /* Class = "UILabel"; text = "无锡市"; ObjectID = "USm-tZ-hSQ"; */ 60 | "USm-tZ-hSQ.text" = "无锡市"; 61 | 62 | /* Class = "UIBarButtonItem"; title = "全选"; ObjectID = "ZhZ-JO-AzB"; */ 63 | "ZhZ-JO-AzB.title" = "全选"; 64 | 65 | /* Class = "UIBarButtonItem"; title = "全选"; ObjectID = "aeJ-an-yEB"; */ 66 | "aeJ-an-yEB.title" = "全选"; 67 | 68 | /* Class = "UILabel"; text = "Detail"; ObjectID = "d9d-ZO-bln"; */ 69 | "d9d-ZO-bln.text" = "Detail"; 70 | 71 | /* Class = "UIBarButtonItem"; title = "退出"; ObjectID = "fTK-Zy-mgO"; */ 72 | "fTK-Zy-mgO.title" = "退出"; 73 | 74 | /* Class = "UILabel"; text = "归属地数据库版本号"; ObjectID = "g4Z-o3-HuL"; */ 75 | "g4Z-o3-HuL.text" = "归属地数据库版本号"; 76 | 77 | /* Class = "UILabel"; text = "版本号"; ObjectID = "ike-c6-maK"; */ 78 | "ike-c6-maK.text" = "版本号"; 79 | 80 | /* Class = "UINavigationItem"; title = "拦截关键词"; ObjectID = "mFb-xq-vUc"; */ 81 | "mFb-xq-vUc.title" = "拦截关键词"; 82 | 83 | /* Class = "UISearchBar"; placeholder = "输入关键字"; ObjectID = "n0l-DE-jel"; */ 84 | "n0l-DE-jel.placeholder" = "输入关键字"; 85 | 86 | /* Class = "UILabel"; text = "拦截关键词 *"; ObjectID = "nQf-Z5-fYM"; */ 87 | "nQf-Z5-fYM.text" = "拦截关键词 **"; 88 | 89 | /* Class = "UILabel"; text = "号码黑名单"; ObjectID = "rt1-i0-rUv"; */ 90 | "rt1-i0-rUv.text" = "号码黑名单"; 91 | 92 | /* Class = "UILabel"; text = "无锡市"; ObjectID = "sPx-S6-YV2"; */ 93 | "sPx-S6-YV2.text" = "无锡市"; 94 | 95 | /* Class = "UILabel"; text = "Label"; ObjectID = "tMe-7W-7MG"; */ 96 | "tMe-7W-7MG.text" = "Label"; 97 | 98 | /* Class = "UILabel"; text = "支付宝捐赠"; ObjectID = "tsZ-aX-oIw"; */ 99 | "tsZ-aX-oIw.text" = "支付宝捐赠"; 100 | 101 | /* Class = "UILabel"; text = "全部拦截"; ObjectID = "vNs-sR-u19"; */ 102 | "vNs-sR-u19.text" = "全部拦截"; 103 | 104 | /* Class = "UILabel"; text = "启用"; ObjectID = "yH8-rm-lmu"; */ 105 | "yH8-rm-lmu.text" = "启用"; 106 | 107 | /* Class = "UILabel"; text = "捐赠名单"; ObjectID = "zBI-1p-dE7"; */ 108 | "zBI-1p-dE7.text" = "捐赠名单"; 109 | 110 | /* Class = "UINavigationItem"; title = "按区号拦截固话"; ObjectID = "zOF-mO-cI1"; */ 111 | "zOF-mO-cI1.title" = "按区号拦截固话"; 112 | 113 | /* Class = "UILabel"; text = "捐赠名单"; ObjectID = "yN3-Av-FQ1"; */ 114 | "yN3-Av-FQ1.text" = "免责声明"; 115 | 116 | /* Class = "UILabel"; text = "捐赠名单"; ObjectID = "qze-rW-gOX"; */ 117 | "qze-rW-gOX.text" = "开源组件"; 118 | 119 | "Aby-nN-l5F.text" = "拦截记录"; 120 | "4py-b4-JiY.title" = "拦截记录"; 121 | "pra-xj-Xb3.text" = "集成到电话应用"; 122 | "wig-6E-Wta.footerTitle" = "集成到电话应用后:\n1. 被拦截的电话旁会显示🚫标记;\n2. 可以通过左滑菜单把号码快速加入到CallKiller黑名单。"; 123 | 124 | "CLS-Db-QtD.text" = "匹配时忽略号码前缀"; 125 | "8j3-Oz-g5u.title" = "忽略号码前缀"; 126 | "a1C-Kr-EGr.text" = "使用说明:\n此功能的典型用例,是处理移动的「和多号」业务。\n当副卡来电时,号码前会自动加上 12583x 前缀。\n因此添加条目「12583?」即可忽略这些副卡前缀。\n举例来说,若来电号码是 12583113900010002 ,它将被视作 13900010002 进行后续处理。\n\n其他使用场景?作者也不知道,请自行挖掘。"; 127 | -------------------------------------------------------------------------------- /callkiller-gui/JGProgressHUD/JGProgressHUDPieIndicatorView.m: -------------------------------------------------------------------------------- 1 | // 2 | // JGProgressHUDPieIndicatorView.m 3 | // JGProgressHUD 4 | // 5 | // Created by Jonas Gessner on 19.07.14. 6 | // Copyright (c) 2014 Jonas Gessner. All rights reserved. 7 | // 8 | 9 | #import "JGProgressHUDPieIndicatorView.h" 10 | 11 | @interface JGProgressHUDPieIndicatorLayer : CALayer 12 | 13 | @property (nonatomic, assign) float progress; 14 | 15 | @property (nonatomic, weak) UIColor *color; 16 | 17 | @property (nonatomic, weak) UIColor *fillColor; 18 | 19 | @end 20 | 21 | @implementation JGProgressHUDPieIndicatorLayer 22 | 23 | @dynamic progress, color, fillColor; 24 | 25 | + (BOOL)needsDisplayForKey:(NSString *)key { 26 | return ([key isEqualToString:@"progress"] || [key isEqualToString:@"color"] || [key isEqualToString:@"fillColor"] || [super needsDisplayForKey:key]); 27 | } 28 | 29 | - (id )actionForKey:(NSString *)key { 30 | if ([key isEqualToString:@"progress"]) { 31 | CABasicAnimation *progressAnimation = [CABasicAnimation animation]; 32 | progressAnimation.fromValue = [self.presentationLayer valueForKey:key]; 33 | 34 | progressAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 35 | 36 | return progressAnimation; 37 | } 38 | 39 | return [super actionForKey:key]; 40 | } 41 | 42 | - (void)drawInContext:(CGContextRef)ctx { 43 | UIGraphicsPushContext(ctx); 44 | 45 | CGRect rect = self.bounds; 46 | 47 | CGPoint center = CGPointMake(rect.origin.x + (CGFloat)floor(rect.size.width/2.0), rect.origin.y + (CGFloat)floor(rect.size.height/2.0)); 48 | CGFloat lineWidth = 2.0; 49 | CGFloat radius = (CGFloat)floor(MIN(rect.size.width, rect.size.height)/2.0)-lineWidth; 50 | 51 | UIBezierPath *borderPath = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:0.0 endAngle:2.0*(CGFloat)M_PI clockwise:NO]; 52 | 53 | [borderPath setLineWidth:lineWidth]; 54 | 55 | if (self.fillColor) { 56 | [self.fillColor setFill]; 57 | 58 | [borderPath fill]; 59 | } 60 | 61 | [self.color set]; 62 | 63 | [borderPath stroke]; 64 | 65 | if (self.progress > 0.0) { 66 | UIBezierPath *processPath = [UIBezierPath bezierPath]; 67 | 68 | [processPath setLineWidth:radius]; 69 | 70 | CGFloat startAngle = -((CGFloat)M_PI/2.0); 71 | CGFloat endAngle = startAngle + 2.0 * (CGFloat)M_PI * self.progress; 72 | 73 | [processPath addArcWithCenter:center radius:radius/2.0 startAngle:startAngle endAngle:endAngle clockwise:YES]; 74 | 75 | [processPath stroke]; 76 | } 77 | 78 | UIGraphicsPopContext(); 79 | } 80 | 81 | @end 82 | 83 | 84 | @implementation JGProgressHUDPieIndicatorView 85 | 86 | #pragma mark - Initializers 87 | 88 | - (instancetype)init { 89 | self = [super initWithContentView:nil]; 90 | 91 | if (self) { 92 | self.layer.contentsScale = [UIScreen mainScreen].scale; 93 | [self.layer setNeedsDisplay]; 94 | 95 | self.color = [UIColor clearColor]; 96 | self.fillColor = [UIColor clearColor]; 97 | } 98 | 99 | return self; 100 | } 101 | 102 | - (instancetype)initWithHUDStyle:(JGProgressHUDStyle)style { 103 | return [self init]; 104 | } 105 | 106 | - (instancetype)initWithContentView:(UIView *)contentView { 107 | return [self init]; 108 | } 109 | 110 | #pragma mark - Getters & Setters 111 | 112 | - (void)setColor:(UIColor *)tintColor { 113 | if ([tintColor isEqual:self.color]) { 114 | return; 115 | } 116 | 117 | _color = tintColor; 118 | 119 | [(JGProgressHUDPieIndicatorLayer *)self.layer setColor:self.color]; 120 | } 121 | 122 | - (void)setFillColor:(UIColor *)fillColor { 123 | if ([fillColor isEqual:self.fillColor]) { 124 | return; 125 | } 126 | 127 | _fillColor = fillColor; 128 | 129 | [(JGProgressHUDPieIndicatorLayer *)self.layer setFillColor:self.fillColor]; 130 | } 131 | 132 | - (void)setProgress:(float)progress animated:(BOOL)animated { 133 | if (fequal(self.progress, progress)) { 134 | return; 135 | } 136 | 137 | [super setProgress:progress animated:animated]; 138 | 139 | [CATransaction begin]; 140 | [CATransaction setAnimationDuration:(animated ? 0.3 : 0.0)]; 141 | 142 | [(JGProgressHUDPieIndicatorLayer *)self.layer setProgress:progress]; 143 | 144 | [CATransaction commit]; 145 | } 146 | 147 | #pragma mark - Overrides 148 | 149 | - (void)setUpForHUDStyle:(JGProgressHUDStyle)style vibrancyEnabled:(BOOL)vibrancyEnabled { 150 | [super setUpForHUDStyle:style vibrancyEnabled:vibrancyEnabled]; 151 | 152 | if (style == JGProgressHUDStyleDark) { 153 | self.color = [UIColor colorWithWhite:1.0 alpha:1.0]; 154 | self.fillColor = [UIColor colorWithWhite:0.2 alpha:1.0]; 155 | } 156 | else { 157 | self.color = [UIColor blackColor]; 158 | if (style == JGProgressHUDStyleLight) { 159 | self.fillColor = [UIColor colorWithWhite:0.85 alpha:1.0]; 160 | } 161 | else { 162 | self.fillColor = [UIColor colorWithWhite:0.9 alpha:1.0]; 163 | } 164 | } 165 | } 166 | 167 | + (Class)layerClass { 168 | return [JGProgressHUDPieIndicatorLayer class]; 169 | } 170 | 171 | @end 172 | -------------------------------------------------------------------------------- /callkiller-gui/KeywordsVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // KeywordsVC.m 3 | // callkiller-gui 4 | // 5 | // Created by mac on 2018/7/19. 6 | // 7 | 8 | #import "KeywordsVC.h" 9 | #import "Preference.h" 10 | #import "AlertUtil.h" 11 | 12 | @interface KeywordsVC () 13 | @property (weak, nonatomic) IBOutlet UIBarButtonItem *trashButton; 14 | @property (weak, nonatomic) IBOutlet UITableView *tableview; 15 | @property (weak, nonatomic) UIAlertAction *alertAction; 16 | @end 17 | 18 | @implementation KeywordsVC 19 | 20 | - (void)viewDidLoad { 21 | [super viewDidLoad]; 22 | 23 | NSDictionary *pref = [[Preference sharedInstance] pref]; 24 | NSArray *keywords = pref[kKeyBlackKeywords]; 25 | self.trashButton.enabled = keywords.count > 0; 26 | } 27 | 28 | - (void)didReceiveMemoryWarning { 29 | [super didReceiveMemoryWarning]; 30 | // Dispose of any resources that can be recreated. 31 | } 32 | - (IBAction)onTrash:(id)sender { 33 | [AlertUtil showQuery:NSLocalizedString(@"del-all-keywords-prompt", nil) message:nil isDanger:YES onConfirm:^{ 34 | NSMutableDictionary *pref = [[Preference sharedInstance] pref]; 35 | NSMutableArray *keywords = pref[kKeyBlackKeywords]; 36 | [keywords removeAllObjects]; 37 | [[Preference sharedInstance] save]; 38 | [self.tableview reloadData]; 39 | self.trashButton.enabled = NO; 40 | }]; 41 | } 42 | - (IBAction)onAdd:(id)sender { 43 | UIAlertController *alert = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"add-keyword-title", nil) message:NSLocalizedString(@"add-keyword-content", nil) preferredStyle:UIAlertControllerStyleAlert]; 44 | [alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"cancel", nil) style:UIAlertActionStyleCancel handler:nil]]; 45 | UIAlertAction *confirm = [UIAlertAction actionWithTitle:NSLocalizedString(@"ok", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { 46 | NSString *keyword = [alert.textFields[0].text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; 47 | if (keyword.length) { 48 | NSMutableDictionary *pref = [[Preference sharedInstance] pref]; 49 | NSMutableArray *keywords = pref[kKeyBlackKeywords]; 50 | if (!keywords) { 51 | keywords = [NSMutableArray new]; 52 | pref[kKeyBlackKeywords] = keywords; 53 | } 54 | for (NSString *item in keywords) { 55 | if ([item isEqualToString:keyword]) { 56 | [AlertUtil showInfo:NSLocalizedString(@"duplicated-entry", nil) message:nil]; 57 | return; 58 | } 59 | } 60 | [keywords addObject:keyword]; 61 | [[Preference sharedInstance] save]; 62 | [self.tableview reloadData]; 63 | self.trashButton.enabled = YES; 64 | } 65 | }]; 66 | confirm.enabled = NO; 67 | self.alertAction = confirm; 68 | [alert addAction:confirm]; 69 | [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { 70 | textField.placeholder = NSLocalizedString(@"enter-keyword-prompt", nil); 71 | textField.delegate = self; 72 | }]; 73 | [UIApplication.sharedApplication.keyWindow.rootViewController presentViewController:alert animated:YES completion:^{ 74 | // 75 | }]; 76 | } 77 | 78 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 79 | NSDictionary *pref = [[Preference sharedInstance] pref]; 80 | NSArray *keywords = pref[kKeyBlackKeywords]; 81 | return keywords.count; 82 | } 83 | 84 | - (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 85 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"]; 86 | NSDictionary *pref = [[Preference sharedInstance] pref]; 87 | NSArray *keywords = pref[kKeyBlackKeywords]; 88 | cell.textLabel.text = keywords[indexPath.row]; 89 | return cell; 90 | } 91 | 92 | - (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath { 93 | NSMutableArray *actions = [NSMutableArray new]; 94 | [actions addObject:[UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDestructive title:NSLocalizedString(@"delete", nil) handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) { 95 | NSMutableDictionary *pref = [[Preference sharedInstance] pref]; 96 | NSMutableArray *keywords = pref[kKeyBlackKeywords]; 97 | [keywords removeObjectAtIndex:indexPath.row]; 98 | [[Preference sharedInstance] save]; 99 | [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; 100 | [tableView setEditing:NO animated:NO]; 101 | 102 | if (keywords.count == 0) { 103 | self.trashButton.enabled = NO; 104 | } 105 | }]]; 106 | return actions; 107 | } 108 | 109 | - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { 110 | NSString *newText = [textField.text stringByReplacingCharactersInRange:range withString:string]; 111 | self.alertAction.enabled = [newText stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]].length > 0; 112 | return YES; 113 | } 114 | 115 | @end 116 | -------------------------------------------------------------------------------- /statics/GCDObjC/GCDQueue.h: -------------------------------------------------------------------------------- 1 | // 2 | // GCDQueue.h 3 | // GCDObjC 4 | // 5 | // Copyright (c) 2012 Mark Smith. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | @class GCDGroup; 11 | 12 | @interface GCDQueue : NSObject 13 | 14 | /** 15 | * Returns the underlying dispatch queue object. 16 | * 17 | * @return The dispatch queue object. 18 | */ 19 | @property (strong, readonly, nonatomic) dispatch_queue_t dispatchQueue; 20 | 21 | /** 22 | * Returns the serial dispatch queue associated with the application’s main thread. 23 | * 24 | * @return The main queue. This queue is created automatically on behalf of the main thread before main is called. 25 | * @see dispatch_get_main_queue() 26 | */ 27 | + (GCDQueue *)mainQueue; 28 | 29 | /** 30 | * Returns the default priority global concurrent queue. 31 | * 32 | * @return The queue. 33 | * @see dispatch_get_global_queue() 34 | */ 35 | + (GCDQueue *)globalQueue; 36 | 37 | /** 38 | * Returns the high priority global concurrent queue. 39 | * 40 | * @return The queue. 41 | * @see dispatch_get_global_queue() 42 | */ 43 | + (GCDQueue *)highPriorityGlobalQueue; 44 | 45 | /** 46 | * Returns the low priority global concurrent queue. 47 | * 48 | * @return The queue. 49 | * @see dispatch_get_global_queue() 50 | */ 51 | + (GCDQueue *)lowPriorityGlobalQueue; 52 | 53 | /** 54 | * Returns the background priority global concurrent queue. 55 | * 56 | * @return The queue. 57 | * @see dispatch_get_global_queue() 58 | */ 59 | + (GCDQueue *)backgroundPriorityGlobalQueue; 60 | 61 | /** 62 | * Returns whether the current block is executing on the main queue. 63 | * 64 | * @return YES if so, NO othewise. 65 | */ 66 | + (BOOL)isMainQueue; 67 | 68 | /** 69 | * Initializes a new serial queue. 70 | * 71 | * @return The initialized instance. 72 | * @see dispatch_queue_create() 73 | */ 74 | - (instancetype)init; 75 | 76 | /** 77 | * Initializes a new serial queue. 78 | * 79 | * @return The initialized instance. 80 | * @see dispatch_queue_create() 81 | */ 82 | - (instancetype)initSerial; 83 | 84 | /** 85 | * Initializes a new concurrent queue. 86 | * 87 | * @return The initialized instance. 88 | * @see dispatch_queue_create() 89 | */ 90 | - (instancetype)initConcurrent; 91 | 92 | /** 93 | * The GCDQueue designated initializer. 94 | * 95 | * @param dispatchQueue A dispatch_queue_t object. 96 | * @return The initialized instance. 97 | */ 98 | - (instancetype)initWithDispatchQueue:(dispatch_queue_t)dispatchQueue; 99 | 100 | /** 101 | * Submits a block for asynchronous execution on the queue. 102 | * 103 | * @param block The block to submit. 104 | * @see dispatch_async() 105 | */ 106 | - (void)queueBlock:(dispatch_block_t)block; 107 | 108 | /** 109 | * Submits a block for asynchronous execution on the queue after a delay. 110 | * 111 | * @param block The block to submit. 112 | * @param afterDelay The delay in seconds. 113 | * @see dispatch_after() 114 | */ 115 | - (void)queueBlock:(dispatch_block_t)block afterDelay:(double)seconds; 116 | 117 | /** 118 | * Submits a block for execution on the queue and waits until it completes. 119 | * 120 | * @param block The block to submit. 121 | * @see dispatch_sync() 122 | */ 123 | - (void)queueAndAwaitBlock:(dispatch_block_t)block; 124 | 125 | /** 126 | * Submits a block for execution on the queue multiple times and waits until all executions complete. 127 | * 128 | * @param block The block to submit. 129 | * @param iterationCount The number of times to execute the block. 130 | * @see dispatch_apply() 131 | */ 132 | - (void)queueAndAwaitBlock:(void (^)(size_t))block iterationCount:(size_t)count; 133 | 134 | /** 135 | * Submits a block for asynchronous execution on the queue and associates it with the group. 136 | * 137 | * @param block The block to submit. 138 | * @param inGroup The group to associate the block with. 139 | * @see dispatch_group_async() 140 | */ 141 | - (void)queueBlock:(dispatch_block_t)block inGroup:(GCDGroup *)group; 142 | 143 | /** 144 | * Schedules a block to be submitted to the queue when a group of previously submitted blocks have completed. 145 | * 146 | * @param block The block to submit when the group completes. 147 | * @param inGroup The group to observe. 148 | * @see dispatch_group_notify() 149 | */ 150 | - (void)queueNotifyBlock:(dispatch_block_t)block inGroup:(GCDGroup *)group; 151 | 152 | /** 153 | * Submits a barrier block for asynchronous execution on the queue. 154 | * 155 | * @param block The barrier block to submit. 156 | * @see dispatch_barrier_async() 157 | */ 158 | - (void)queueBarrierBlock:(dispatch_block_t)block; 159 | 160 | /** 161 | * Submits a barrier block for execution on the queue and waits until it completes. 162 | * 163 | * @param block The barrier block to submit. 164 | * @see dispatch_barrier_sync() 165 | */ 166 | - (void)queueAndAwaitBarrierBlock:(dispatch_block_t)block; 167 | 168 | /** 169 | * Suspends execution of blocks on the queue. 170 | * 171 | * @see dispatch_suspend() 172 | */ 173 | - (void)suspend; 174 | 175 | /** 176 | * Resumes execution of blocks on the queue. 177 | * 178 | * @see dispatch_resume() 179 | */ 180 | - (void)resume; 181 | 182 | /** 183 | * Returns the context associated with a key. 184 | * 185 | * @see dispatch_get_specific() 186 | */ 187 | - (void *)contextForKey:(const void *)key; 188 | 189 | /** 190 | * Sets the context associated with a key. 191 | * 192 | * @see dispatch_queue_set_specific() 193 | */ 194 | - (void)setContext:(void *)context forKey:(const void *)key; 195 | 196 | @end 197 | -------------------------------------------------------------------------------- /callkiller-gui/en.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | /* Class = "UILabel"; text = "全部拦截"; ObjectID = "0Yn-ZW-7iL"; */ 3 | "0Yn-ZW-7iL.text" = "Block All"; 4 | 5 | /* Class = "UILabel"; text = "Title"; ObjectID = "0v5-UI-jnG"; */ 6 | "0v5-UI-jnG.text" = "Title"; 7 | 8 | /* Class = "UILabel"; text = "Label"; ObjectID = "2Gx-NC-qzY"; */ 9 | "2Gx-NC-qzY.text" = "Label"; 10 | 11 | /* Class = "UILabel"; text = "Label"; ObjectID = "3Jm-sp-X7X"; */ 12 | "3Jm-sp-X7X.text" = "Label"; 13 | 14 | /* Class = "UINavigationItem"; title = "号码黑名单"; ObjectID = "3np-Tm-w3F"; */ 15 | "3np-Tm-w3F.title" = "Blacklist"; 16 | 17 | /* Class = "UILabel"; text = "按区号拦截固话(中国内地)"; ObjectID = "4fu-3x-1WL"; */ 18 | "4fu-3x-1WL.text" = "Block landline number by area *"; 19 | 20 | /* Class = "UILabel"; text = "内地手机号归属地测试"; ObjectID = "Aby-nN-l5F"; */ 21 | "xK9-lI-N2e.text" = "Mobile phone number test"; 22 | 23 | /* Class = "UILabel"; text = "Label"; ObjectID = "Boe-Kq-JvX"; */ 24 | "Boe-Kq-JvX.text" = "Label"; 25 | 26 | /* Class = "UITableViewSection"; footerTitle = "* 关键词拦截功能,需要你自行安装“防骚扰大师”之类的App,并写入号码库到系统后,才能正常工作。CallKiller将对此类软件的识别结果进行关键词匹配。个人开发者精力和能力有限,难以自行维护号码数据库,望理解。"; ObjectID = "ENJ-Ja-TcT"; */ 27 | "ENJ-Ja-TcT.footerTitle" = "* for China mainland only\n** You need to install CallKit based apps manually to generate number-label database. CallKiller is developed by individual, and the developer simply has no resource to maintain such a database."; 28 | 29 | /* Class = "UINavigationItem"; title = "按归属地拦截手机号"; ObjectID = "Ggw-PO-dFE"; */ 30 | "Ggw-PO-dFE.title" = "Block mobile by area"; 31 | 32 | /* Class = "UINavigationItem"; title = "CallKiller"; ObjectID = "I1h-UH-vWR"; */ 33 | "I1h-UH-vWR.title" = "CallKiller"; 34 | 35 | /* Class = "UILabel"; text = "拦截「未知号码」"; ObjectID = "KOI-i6-3HF"; */ 36 | "KOI-i6-3HF.text" = "Block「Unknown Number」"; 37 | 38 | /* Class = "UILabel"; text = "Label"; ObjectID = "La8-46-pNw"; */ 39 | "La8-46-pNw.text" = "Label"; 40 | 41 | /* Class = "UISearchBar"; placeholder = "输入关键字"; ObjectID = "Mxi-bD-0Lk"; */ 42 | "Mxi-bD-0Lk.placeholder" = "Type to filter"; 43 | 44 | /* Class = "UILabel"; text = "Title"; ObjectID = "OuF-I6-aFg"; */ 45 | "OuF-I6-aFg.text" = "Title"; 46 | 47 | /* Class = "UILabel"; text = "built with ♥ by laoyur"; ObjectID = "Q0p-kf-64s"; */ 48 | "Q0p-kf-64s.text" = "built with ♥ by laoyur"; 49 | 50 | /* Class = "UILabel"; text = "Label"; ObjectID = "Qod-Kr-Alc"; */ 51 | "Qod-Kr-Alc.text" = "Label"; 52 | 53 | /* Class = "UILabel"; text = "按归属地拦截手机号(中国内地)"; ObjectID = "Rvt-ix-4ru"; */ 54 | "Rvt-ix-4ru.text" = "Block mobile by area *"; 55 | 56 | /* Class = "UILabel"; text = "放行联系人"; ObjectID = "Ttl-2b-vDT"; */ 57 | "Ttl-2b-vDT.text" = "Bypass address-book numbers"; 58 | 59 | /* Class = "UILabel"; text = "无锡市"; ObjectID = "USm-tZ-hSQ"; */ 60 | "USm-tZ-hSQ.text" = "无锡市"; 61 | 62 | /* Class = "UIBarButtonItem"; title = "全选"; ObjectID = "ZhZ-JO-AzB"; */ 63 | "ZhZ-JO-AzB.title" = "Check All"; 64 | 65 | /* Class = "UIBarButtonItem"; title = "全选"; ObjectID = "aeJ-an-yEB"; */ 66 | "aeJ-an-yEB.title" = "Check All"; 67 | 68 | /* Class = "UILabel"; text = "Detail"; ObjectID = "d9d-ZO-bln"; */ 69 | "d9d-ZO-bln.text" = "Detail"; 70 | 71 | /* Class = "UIBarButtonItem"; title = "退出"; ObjectID = "fTK-Zy-mgO"; */ 72 | "fTK-Zy-mgO.title" = "Exit"; 73 | 74 | /* Class = "UILabel"; text = "归属地数据库版本号"; ObjectID = "g4Z-o3-HuL"; */ 75 | "g4Z-o3-HuL.text" = "Mobile area DB version"; 76 | 77 | /* Class = "UILabel"; text = "版本号"; ObjectID = "ike-c6-maK"; */ 78 | "ike-c6-maK.text" = "Version"; 79 | 80 | /* Class = "UINavigationItem"; title = "拦截关键词"; ObjectID = "mFb-xq-vUc"; */ 81 | "mFb-xq-vUc.title" = "Keywords"; 82 | 83 | /* Class = "UISearchBar"; placeholder = "输入关键字"; ObjectID = "n0l-DE-jel"; */ 84 | "n0l-DE-jel.placeholder" = "Type to filter"; 85 | 86 | /* Class = "UILabel"; text = "拦截关键词 *"; ObjectID = "nQf-Z5-fYM"; */ 87 | "nQf-Z5-fYM.text" = "Block by keywords **"; 88 | 89 | /* Class = "UILabel"; text = "号码黑名单"; ObjectID = "rt1-i0-rUv"; */ 90 | "rt1-i0-rUv.text" = "Blacklist"; 91 | 92 | /* Class = "UILabel"; text = "无锡市"; ObjectID = "sPx-S6-YV2"; */ 93 | "sPx-S6-YV2.text" = "无锡市"; 94 | 95 | /* Class = "UILabel"; text = "Label"; ObjectID = "tMe-7W-7MG"; */ 96 | "tMe-7W-7MG.text" = "Label"; 97 | 98 | /* Class = "UILabel"; text = "支付宝捐赠"; ObjectID = "tsZ-aX-oIw"; */ 99 | "tsZ-aX-oIw.text" = "Donate with Alipay"; 100 | 101 | /* Class = "UILabel"; text = "全部拦截"; ObjectID = "vNs-sR-u19"; */ 102 | "vNs-sR-u19.text" = "Block All"; 103 | 104 | /* Class = "UILabel"; text = "启用"; ObjectID = "yH8-rm-lmu"; */ 105 | "yH8-rm-lmu.text" = "Enabled"; 106 | 107 | /* Class = "UILabel"; text = "捐赠名单"; ObjectID = "zBI-1p-dE7"; */ 108 | "zBI-1p-dE7.text" = "Donation list"; 109 | 110 | /* Class = "UINavigationItem"; title = "按区号拦截固话"; ObjectID = "zOF-mO-cI1"; */ 111 | "zOF-mO-cI1.title" = "Block landline by area"; 112 | 113 | /* Class = "UILabel"; text = "捐赠名单"; ObjectID = "yN3-Av-FQ1"; */ 114 | "yN3-Av-FQ1.text" = "EULA"; 115 | 116 | /* Class = "UILabel"; text = "捐赠名单"; ObjectID = "qze-rW-gOX"; */ 117 | "qze-rW-gOX.text" = "Open sourced components"; 118 | 119 | "Aby-nN-l5F.text" = "Block history"; 120 | "4py-b4-JiY.title" = "Block history"; 121 | "pra-xj-Xb3.text" = "Inject to Phone app"; 122 | "wig-6E-Wta.footerTitle" = "If inject-to-phone-app enabled:\n1. 🚫 will be shown aside the phonenumber which has been blocked by CallKiller;\n2. You can add phonenumber to CallKiller blacklist from right-to-left-swipe menu"; 123 | 124 | "CLS-Db-QtD.text" = "Ignore phone prefix"; 125 | "8j3-Oz-g5u.title" = "Ignore phone prefix"; 126 | "a1C-Kr-EGr.text" = "Usage example:\n\nstep 1. add an item with '12583?',\nstep 2. incoming call phonenumber '12583113900010002' will be treated as '13900010002' for further processing.\n\nUseful or useless? Who knows!"; 127 | -------------------------------------------------------------------------------- /callkiller/MPRecentsTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // MPRecentsTableViewController.h 3 | // callkiller 4 | // 5 | // Created by mac on 2018/8/1. 6 | // 7 | 8 | #ifndef MPRecentsTableViewController_h 9 | #define MPRecentsTableViewController_h 10 | 11 | @interface MPRecentsTableViewController //: PhoneViewController 12 | //{ 13 | // _Bool _dataSourceNeedsReload; 14 | // _Bool _tableViewNeedsReload; 15 | // _Bool _contentUnavailable; 16 | // NSMutableArray *_recentCalls; 17 | // MPRecentsController *_recentsController; 18 | // TUMetadataCache *_metadataCache; 19 | // CNAvatarCardController *_avatarCardController; 20 | // UIBarButtonItem *_clearButtonItem; 21 | // _UIContentUnavailableView *_contentUnavailableView; 22 | // NSString *_contentUnavailableViewTitle; 23 | // UISegmentedControl *_tableViewDisplayModeSegmentedControl; 24 | // UITableView *_tableView; 25 | // NSArray *_indexPathsForMissedCalls; 26 | // NSArray *_indexPathsForNormalCalls; 27 | // long long _tableViewDisplayMode; 28 | //} 29 | 30 | + (id)tabBarIconName; 31 | + (long long)tabBarSystemItem; 32 | + (int)tabViewType; 33 | + (_Bool)requiresNavigationControllerContainer; 34 | + (void)initialize; 35 | //+ (CDStruct_5ec447a9)badge; 36 | @property(nonatomic) long long tableViewDisplayMode; // @synthesize tableViewDisplayMode=_tableViewDisplayMode; 37 | @property(retain, nonatomic) NSArray *indexPathsForNormalCalls; // @synthesize indexPathsForNormalCalls=_indexPathsForNormalCalls; 38 | @property(retain, nonatomic) NSArray *indexPathsForMissedCalls; // @synthesize indexPathsForMissedCalls=_indexPathsForMissedCalls; 39 | @property(retain, nonatomic) UITableView *tableView; // @synthesize tableView=_tableView; 40 | @property(retain, nonatomic) UISegmentedControl *tableViewDisplayModeSegmentedControl; // @synthesize tableViewDisplayModeSegmentedControl=_tableViewDisplayModeSegmentedControl; 41 | @property(copy, nonatomic) NSString *contentUnavailableViewTitle; // @synthesize contentUnavailableViewTitle=_contentUnavailableViewTitle; 42 | //@property(retain, nonatomic) _UIContentUnavailableView *contentUnavailableView; // @synthesize contentUnavailableView=_contentUnavailableView; 43 | @property(nonatomic) _Bool contentUnavailable; // @synthesize contentUnavailable=_contentUnavailable; 44 | @property(retain, nonatomic) UIBarButtonItem *clearButtonItem; // @synthesize clearButtonItem=_clearButtonItem; 45 | //@property(retain, nonatomic) CNAvatarCardController *avatarCardController; // @synthesize avatarCardController=_avatarCardController; 46 | @property(nonatomic) _Bool tableViewNeedsReload; // @synthesize tableViewNeedsReload=_tableViewNeedsReload; 47 | @property(nonatomic) _Bool dataSourceNeedsReload; // @synthesize dataSourceNeedsReload=_dataSourceNeedsReload; 48 | //@property(retain, nonatomic) TUMetadataCache *metadataCache; // @synthesize metadataCache=_metadataCache; 49 | //@property(retain, nonatomic) MPRecentsController *recentsController; // @synthesize recentsController=_recentsController; 50 | @property(retain, nonatomic) NSMutableArray *recentCalls; // @synthesize recentCalls=_recentCalls; 51 | //- (void).cxx_destruct; 52 | - (void)showRecentCallDetailsViewControllerForRecentCall:(id)arg1 animated:(_Bool)arg2; 53 | - (void)setNavigationItemsForEditing:(_Bool)arg1 animated:(_Bool)arg2; 54 | - (void)refreshView; 55 | - (void)reloadTableView; 56 | - (void)refreshTabBarItemBadge; 57 | - (void)reloadDataSource; 58 | - (void)makeUIForDefaultPNG; 59 | - (double)tableView:(id)arg1 estimatedHeightForRowAtIndexPath:(id)arg2; 60 | - (void)contactViewController:(id)arg1 didCompleteWithContact:(id)arg2; 61 | - (id)presentingViewControllerForAvatarCardController:(id)arg1; 62 | - (long long)avatarCardController:(id)arg1 presentationResultForLocation:(struct CGPoint)arg2; 63 | - (id)contactViewControllerForRecentCall:(id)arg1 contact:(id)arg2; 64 | - (id)contactViewControllerForRecentCall:(id)arg1; 65 | - (void)removeRecentCallsAtIndexPaths:(id)arg1; 66 | - (void)removeAllRecentCalls; 67 | - (void)selectedSegmentDidChangeForSender:(id)arg1; 68 | - (void)clearButtonAction:(id)arg1; 69 | - (void)contentSizeCategoryDidChange; 70 | - (void)handleCurrentLocaleDidChangeNotification:(id)arg1; 71 | - (void)phoneApplicationDidChangeTabBarSelection:(id)arg1; 72 | - (void)applicationDidEnterBackground:(id)arg1; 73 | - (void)metadataCacheDidFinishUpdating:(id)arg1; 74 | - (void)handleCallHistoryControllerUnreadCallCountDidChangeNotification:(id)arg1; 75 | - (void)handleCallHistoryControllerRecentCallsDidChangeNotification:(id)arg1; 76 | - (void)tableView:(id)arg1 commitEditingStyle:(long long)arg2 forRowAtIndexPath:(id)arg3; 77 | - (void)tableView:(id)arg1 accessoryButtonTappedForRowWithIndexPath:(id)arg2; 78 | - (void)tableView:(id)arg1 didSelectRowAtIndexPath:(id)arg2; 79 | - (long long)numberOfSectionsInTableView:(id)arg1; 80 | - (long long)tableView:(id)arg1 numberOfRowsInSection:(long long)arg2; 81 | - (id)tableView:(id)arg1 cellForRowAtIndexPath:(id)arg2; 82 | - (id)recentCallAtTableViewIndex:(long long)arg1; 83 | - (long long)rowCountForCurrentTableMode; 84 | - (id)_indexPathsForCallsWithStatus:(unsigned int)arg1 includeUnknown:(_Bool)arg2; 85 | - (id)indexPathsForRecentCalls; 86 | - (_Bool)shouldSnapshot; 87 | - (void)savePreferences; 88 | - (void)setContentUnavailable:(_Bool)arg1 animated:(_Bool)arg2; 89 | - (void)setEditing:(_Bool)arg1 animated:(_Bool)arg2; 90 | - (void)viewDidDisappear:(_Bool)arg1; 91 | - (void)viewWillDisappear:(_Bool)arg1; 92 | - (void)viewDidAppear:(_Bool)arg1; 93 | - (void)viewWillAppear:(_Bool)arg1; 94 | - (void)viewDidLoad; 95 | - (void)loadView; 96 | - (void)didReceiveMemoryWarning; 97 | - (void)dealloc; 98 | - (void)commonInit; 99 | - (id)init; 100 | 101 | // Remaining properties 102 | @property(readonly, copy) NSString *debugDescription; 103 | @property(readonly, copy) NSString *description; 104 | @property(readonly) unsigned long long hash; 105 | @property(readonly) Class superclass; 106 | 107 | @end 108 | 109 | #endif /* MPRecentsTableViewController_h */ 110 | -------------------------------------------------------------------------------- /callkiller-gui/HistoryVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // HistoryVC.m 3 | // callkiller-gui 4 | // 5 | // Created by mac on 2018/8/1. 6 | // 7 | 8 | #import "HistoryVC.h" 9 | #import "statics.h" 10 | #import "AlertUtil.h" 11 | #import 12 | 13 | @interface LSBundleProxy 14 | @property (nonatomic, readonly) NSURL *dataContainerURL; 15 | + (id)bundleProxyForIdentifier:(id)arg1; 16 | @end 17 | 18 | @interface HistoryCell : UITableViewCell 19 | @property (weak, nonatomic) IBOutlet UILabel *phone; 20 | @property (weak, nonatomic) IBOutlet UILabel *date; 21 | @property (weak, nonatomic) IBOutlet UILabel *reason; 22 | 23 | @end 24 | 25 | @implementation HistoryCell 26 | @end 27 | 28 | @interface HistoryVC () { 29 | int _notifyToken; 30 | } 31 | 32 | @property (weak, nonatomic) IBOutlet UIBarButtonItem *trashButton; 33 | @property (weak, nonatomic) IBOutlet UITableView *tableview; 34 | @property (nonatomic) NSDateFormatter *dateFormatter; 35 | @property (nonatomic) id notificationHandler; 36 | 37 | @end 38 | 39 | @implementation HistoryVC 40 | 41 | - (void)viewDidLoad { 42 | [super viewDidLoad]; 43 | 44 | self.dateFormatter = [NSDateFormatter new]; 45 | [self.dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@"Asia/Shanghai"]]; 46 | self.dateFormatter.dateFormat = @"yyyy-MM-dd HH:mm:ss"; 47 | 48 | } 49 | 50 | - (void)viewDidAppear:(BOOL)animated { 51 | [super viewDidAppear:animated]; 52 | self.notificationHandler = [[NSNotificationCenter defaultCenter] addObserverForName:@"mp-history-added" object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) { 53 | [self.tableview reloadData]; 54 | }]; 55 | } 56 | 57 | - (void)viewDidDisappear:(BOOL)animated { 58 | [super viewDidDisappear:animated]; 59 | notify_cancel(_notifyToken); 60 | [[NSNotificationCenter defaultCenter] removeObserver:self.notificationHandler]; 61 | } 62 | 63 | - (void)didReceiveMemoryWarning { 64 | [super didReceiveMemoryWarning]; 65 | // Dispose of any resources that can be recreated. 66 | } 67 | 68 | - (IBAction)onTrash:(id)sender { 69 | [AlertUtil showQuery:NSLocalizedString(@"trash-history-alert-title", nil) message:NSLocalizedString(@"trash-history-alert-content", nil) isDanger:YES onConfirm:^{ 70 | [self.history removeAllObjects]; 71 | [self syncMPHistoryFile]; 72 | [self.tableview reloadData]; 73 | self.tableview.userInteractionEnabled = NO; 74 | [[GCDQueue mainQueue] queueBlock:^{ 75 | [self.navigationController popViewControllerAnimated:YES]; 76 | } afterDelay:0.4]; 77 | }]; 78 | } 79 | 80 | - (void) syncMPHistoryFile { 81 | LSBundleProxy *mobilephone = [LSBundleProxy bundleProxyForIdentifier:@"com.apple.mobilephone"]; 82 | NSString *mpHistoryFilePath = [NSString stringWithFormat:@"%@/Documents/%@", mobilephone.dataContainerURL.path, kMPHistoryFileName]; 83 | NSMutableString *content = [NSMutableString new]; 84 | 85 | for (int i=(int)self.history.count - 1; i>=0; i--) { 86 | NSDictionary *record = self.history[i]; 87 | NSData *data = [NSJSONSerialization dataWithJSONObject:record options:kNilOptions error:nil]; 88 | [content appendFormat:@"%@\n", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]]; 89 | } 90 | 91 | [content writeToFile:mpHistoryFilePath atomically:YES encoding:NSUTF8StringEncoding error:nil]; 92 | notify_post(kMPHistoryFileChangedNotification); 93 | [[NSNotificationCenter defaultCenter] postNotificationName:@"mp-history-deleted-by-user" object:nil]; 94 | } 95 | 96 | - (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView { 97 | return 1; 98 | } 99 | 100 | - (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 101 | return self.history.count; 102 | } 103 | 104 | - (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 105 | HistoryCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"]; 106 | NSDictionary *record = self.history[indexPath.row]; 107 | cell.phone.text = record[@"p"]; 108 | NSDate *date = [NSDate dateWithTimeIntervalSince1970:[record[@"d"] longValue]]; 109 | cell.date.text = [self.dateFormatter stringFromDate:date]; 110 | switch ([record[@"r"] intValue]) { 111 | case ReasonBlockedAsUnknownNumber: { 112 | cell.reason.text = NSLocalizedString(@"block-reason-unknown-number", nil); 113 | break; 114 | } 115 | case ReasonBlockedAsLandline: { 116 | cell.reason.text = NSLocalizedString(@"block-reason-landline", nil); 117 | break; 118 | } 119 | case ReasonBlockedAsMobile: { 120 | cell.reason.text = NSLocalizedString(@"block-reason-mobile", nil); 121 | break; 122 | } 123 | case ReasonBlockedAsBlacklist: { 124 | cell.reason.text = NSLocalizedString(@"block-reason-blacklist", nil); 125 | break; 126 | } 127 | case ReasonBlockedAsKeywords: { 128 | cell.reason.text = record[@"rd"]; 129 | break; 130 | } 131 | case ReasonBlockedAsSystemBlacklist: { 132 | cell.reason.text = NSLocalizedString(@"block-reason-system", nil); 133 | break; 134 | } 135 | default: 136 | cell.reason.text = NSLocalizedString(@"block-reason-unknown", nil); 137 | break; 138 | } 139 | return cell; 140 | } 141 | 142 | - (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath { 143 | NSMutableArray *actions = [NSMutableArray new]; 144 | [actions addObject:[UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDestructive title:NSLocalizedString(@"delete", nil) handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) { 145 | 146 | [self.history removeObjectAtIndex:indexPath.row]; 147 | [self syncMPHistoryFile]; 148 | [self.tableview deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; 149 | 150 | }]]; 151 | return actions; 152 | } 153 | 154 | @end 155 | -------------------------------------------------------------------------------- /statics/Preference.m: -------------------------------------------------------------------------------- 1 | // 2 | // Preference.m 3 | // statics 4 | // 5 | // Created by mac on 2018/7/18. 6 | // 7 | 8 | #import "Preference.h" 9 | #import "statics.h" 10 | #import 11 | 12 | #if TARGET_OS_SIMULATOR 13 | #define kCallKillerPreferenceFolder [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/callkiller"] 14 | #define kCallKillerPreferenceFilePathLegacy [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/callkiller-pref.json"] 15 | #define kCallKillerPreferenceFilePath [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/callkiller/callkiller-pref.json"] 16 | #else 17 | #define kCallKillerPreferenceFolder @"/var/mobile/callkiller" 18 | #define kCallKillerPreferenceFilePathLegacy @"/var/mobile/callkiller-pref.json" 19 | #define kCallKillerPreferenceFilePath @"/var/mobile/callkiller/callkiller-pref.json" 20 | #endif 21 | 22 | static BOOL didMigrate = NO; 23 | 24 | @interface LSBundleProxy 25 | @property (nonatomic, readonly) NSURL *dataContainerURL; 26 | + (id)bundleProxyForIdentifier:(id)arg1; 27 | @end 28 | 29 | @implementation Preference 30 | 31 | +(instancetype)sharedInstance { 32 | static Preference *instance = nil; 33 | static dispatch_once_t onceToken; 34 | dispatch_once(&onceToken, ^{ 35 | instance = [[self alloc] init]; 36 | [[NSFileManager defaultManager] createDirectoryAtPath:kCallKillerPreferenceFolder 37 | withIntermediateDirectories:YES 38 | attributes:nil 39 | error:nil]; 40 | instance->_pref = [[Preference load] mutableDeepCopy]; 41 | instance->_mpPref = [[Preference loadMPPref] mutableDeepCopy]; 42 | }); 43 | return instance; 44 | } 45 | 46 | -(NSMutableDictionary*)pref { 47 | return _pref; 48 | } 49 | 50 | -(void)save { 51 | _pref[kKeyPrefVersion] = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; 52 | NSError *err = nil; 53 | NSData *data = [NSJSONSerialization dataWithJSONObject:_pref options:kNilOptions error:&err]; 54 | if (data) { 55 | [data writeToFile:kCallKillerPreferenceFilePath options:NSDataWritingAtomic error:&err]; 56 | if (err) { 57 | Log("== pref json write to file failed: %@", err); 58 | } 59 | notify_post(kCallKillerPrefUpdatedNotification); 60 | } else { 61 | Log("== pref to json failed: %@", err); 62 | } 63 | } 64 | 65 | -(void)saveOnly { 66 | _pref[kKeyPrefVersion] = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; 67 | NSError *err = nil; 68 | NSData *data = [NSJSONSerialization dataWithJSONObject:_pref options:kNilOptions error:&err]; 69 | if (data) { 70 | [data writeToFile:kCallKillerPreferenceFilePath options:NSDataWritingAtomic error:&err]; 71 | if (err) { 72 | Log("== pref json write to file failed: %@", err); 73 | } 74 | } else { 75 | Log("== pref to json failed: %@", err); 76 | } 77 | } 78 | 79 | -(NSMutableDictionary*)mpPref { 80 | return _mpPref; 81 | } 82 | 83 | -(void)saveMPPref { 84 | _mpPref[kKeyPrefVersion] = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; 85 | NSError *err = nil; 86 | NSData *data = [NSJSONSerialization dataWithJSONObject:_mpPref options:kNilOptions error:&err]; 87 | if (data) { 88 | [data writeToFile:[Preference mpPrefFilePath] options:NSDataWritingAtomic error:&err]; 89 | if (err) { 90 | Log("== mppref json write to file failed: %@", err); 91 | } 92 | } else { 93 | Log("== mppref to json failed: %@", err); 94 | } 95 | } 96 | 97 | +(NSString*)mpPrefFilePath { 98 | LSBundleProxy *mobilephone = [LSBundleProxy bundleProxyForIdentifier:@"com.apple.mobilephone"]; 99 | return [NSString stringWithFormat:@"%@/Documents/%@", mobilephone.dataContainerURL.path, @"callkiller-pref.json"]; 100 | } 101 | 102 | +(NSDictionary*)load { 103 | [Preference migrate]; 104 | NSData *data = [NSData dataWithContentsOfFile:kCallKillerPreferenceFilePath]; 105 | if (data) { 106 | NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]; 107 | if (dict) 108 | return dict; 109 | } 110 | return @{ 111 | kKeyBypassContacts: @(YES), 112 | kKeyBlockUnknown: @(YES), 113 | kKeyIgnoredPrefixes: @[ 114 | @[@"12583?", @"^12583\\d\\d+", @"中国移动和多号"] 115 | ], 116 | kKeyBlackKeywords: @[ 117 | @"响一声", 118 | @"广告", 119 | @"推销", 120 | @"骚扰", 121 | @"诈骗", 122 | @"保险", 123 | @"理财", 124 | @"房产中介", 125 | ] 126 | }; 127 | } 128 | 129 | +(NSDictionary*)loadMPPref { 130 | NSData *data = [NSData dataWithContentsOfFile:[Preference mpPrefFilePath]]; 131 | if (data) { 132 | NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]; 133 | if (dict) 134 | return dict; 135 | } 136 | return @{ 137 | kKeyMPInjectionEnabled: @(YES), 138 | }; 139 | } 140 | 141 | /** 142 | /var/mobile/callkiller-pref.json --> /var/mobile/callkiller/callkiller-pref.json 143 | */ 144 | +(void)migrate { 145 | if (didMigrate) // do migrate only once for sb/app lifetime 146 | return; 147 | //Log("== migrate called from %@", [[NSBundle mainBundle] bundleIdentifier]); 148 | NSFileManager *mgr = [NSFileManager defaultManager]; 149 | BOOL oldPrefExist = [mgr fileExistsAtPath:kCallKillerPreferenceFilePathLegacy]; 150 | BOOL newPrefExist = [mgr fileExistsAtPath:kCallKillerPreferenceFilePath]; 151 | //Log("old pref exists: %@, new pref exists: %@", oldPrefExist ? @"Y" : @"N", newPrefExist ? @"Y" : @"N"); 152 | if (oldPrefExist && !newPrefExist) { 153 | //Log("== do migrate"); 154 | [mgr createDirectoryAtPath:kCallKillerPreferenceFolder withIntermediateDirectories:YES attributes:nil error:nil]; 155 | NSError *err = nil; 156 | [mgr moveItemAtPath:kCallKillerPreferenceFilePathLegacy toPath:kCallKillerPreferenceFilePath error:&err]; 157 | if (err) { 158 | //Log("== move old pref file to new place failed: %@", err); 159 | } 160 | } 161 | didMigrate = YES; 162 | } 163 | 164 | @end 165 | -------------------------------------------------------------------------------- /callkiller-gui/AFNetworking/AFSecurityPolicy.h: -------------------------------------------------------------------------------- 1 | // AFSecurityPolicy.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 | #import 24 | 25 | typedef NS_ENUM(NSUInteger, AFSSLPinningMode) { 26 | AFSSLPinningModeNone, 27 | AFSSLPinningModePublicKey, 28 | AFSSLPinningModeCertificate, 29 | }; 30 | 31 | /** 32 | `AFSecurityPolicy` evaluates server trust against pinned X.509 certificates and public keys over secure connections. 33 | 34 | Adding pinned SSL certificates to your app helps prevent man-in-the-middle attacks and other vulnerabilities. Applications dealing with sensitive customer data or financial information are strongly encouraged to route all communication over an HTTPS connection with SSL pinning configured and enabled. 35 | */ 36 | 37 | NS_ASSUME_NONNULL_BEGIN 38 | 39 | @interface AFSecurityPolicy : NSObject 40 | 41 | /** 42 | The criteria by which server trust should be evaluated against the pinned SSL certificates. Defaults to `AFSSLPinningModeNone`. 43 | */ 44 | @property (readonly, nonatomic, assign) AFSSLPinningMode SSLPinningMode; 45 | 46 | /** 47 | The certificates used to evaluate server trust according to the SSL pinning mode. 48 | 49 | By default, this property is set to any (`.cer`) certificates included in the target compiling AFNetworking. Note that if you are using AFNetworking as embedded framework, no certificates will be pinned by default. Use `certificatesInBundle` to load certificates from your target, and then create a new policy by calling `policyWithPinningMode:withPinnedCertificates`. 50 | 51 | Note that if pinning is enabled, `evaluateServerTrust:forDomain:` will return true if any pinned certificate matches. 52 | */ 53 | @property (nonatomic, strong, nullable) NSSet *pinnedCertificates; 54 | 55 | /** 56 | Whether or not to trust servers with an invalid or expired SSL certificates. Defaults to `NO`. 57 | */ 58 | @property (nonatomic, assign) BOOL allowInvalidCertificates; 59 | 60 | /** 61 | Whether or not to validate the domain name in the certificate's CN field. Defaults to `YES`. 62 | */ 63 | @property (nonatomic, assign) BOOL validatesDomainName; 64 | 65 | ///----------------------------------------- 66 | /// @name Getting Certificates from the Bundle 67 | ///----------------------------------------- 68 | 69 | /** 70 | Returns any certificates included in the bundle. If you are using AFNetworking as an embedded framework, you must use this method to find the certificates you have included in your app bundle, and use them when creating your security policy by calling `policyWithPinningMode:withPinnedCertificates`. 71 | 72 | @return The certificates included in the given bundle. 73 | */ 74 | + (NSSet *)certificatesInBundle:(NSBundle *)bundle; 75 | 76 | ///----------------------------------------- 77 | /// @name Getting Specific Security Policies 78 | ///----------------------------------------- 79 | 80 | /** 81 | Returns the shared default security policy, which does not allow invalid certificates, validates domain name, and does not validate against pinned certificates or public keys. 82 | 83 | @return The default security policy. 84 | */ 85 | + (instancetype)defaultPolicy; 86 | 87 | ///--------------------- 88 | /// @name Initialization 89 | ///--------------------- 90 | 91 | /** 92 | Creates and returns a security policy with the specified pinning mode. 93 | 94 | @param pinningMode The SSL pinning mode. 95 | 96 | @return A new security policy. 97 | */ 98 | + (instancetype)policyWithPinningMode:(AFSSLPinningMode)pinningMode; 99 | 100 | /** 101 | Creates and returns a security policy with the specified pinning mode. 102 | 103 | @param pinningMode The SSL pinning mode. 104 | @param pinnedCertificates The certificates to pin against. 105 | 106 | @return A new security policy. 107 | */ 108 | + (instancetype)policyWithPinningMode:(AFSSLPinningMode)pinningMode withPinnedCertificates:(NSSet *)pinnedCertificates; 109 | 110 | ///------------------------------ 111 | /// @name Evaluating Server Trust 112 | ///------------------------------ 113 | 114 | /** 115 | Whether or not the specified server trust should be accepted, based on the security policy. 116 | 117 | This method should be used when responding to an authentication challenge from a server. 118 | 119 | @param serverTrust The X.509 certificate trust of the server. 120 | @param domain The domain of serverTrust. If `nil`, the domain will not be validated. 121 | 122 | @return Whether or not to trust the server. 123 | */ 124 | - (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust 125 | forDomain:(nullable NSString *)domain; 126 | 127 | @end 128 | 129 | NS_ASSUME_NONNULL_END 130 | 131 | ///---------------- 132 | /// @name Constants 133 | ///---------------- 134 | 135 | /** 136 | ## SSL Pinning Modes 137 | 138 | The following constants are provided by `AFSSLPinningMode` as possible SSL pinning modes. 139 | 140 | enum { 141 | AFSSLPinningModeNone, 142 | AFSSLPinningModePublicKey, 143 | AFSSLPinningModeCertificate, 144 | } 145 | 146 | `AFSSLPinningModeNone` 147 | Do not used pinned certificates to validate servers. 148 | 149 | `AFSSLPinningModePublicKey` 150 | Validate host certificates against public keys of pinned certificates. 151 | 152 | `AFSSLPinningModeCertificate` 153 | Validate host certificates against pinned certificates. 154 | */ 155 | -------------------------------------------------------------------------------- /callkiller-gui/JGProgressHUD/JGProgressHUDRingIndicatorView.m: -------------------------------------------------------------------------------- 1 | // 2 | // JGProgressHUDRingIndicatorView.m 3 | // JGProgressHUD 4 | // 5 | // Created by Jonas Gessner on 20.7.14. 6 | // Copyright (c) 2014 Jonas Gessner. All rights reserved. 7 | // 8 | 9 | #import "JGProgressHUDRingIndicatorView.h" 10 | 11 | 12 | @interface JGProgressHUDRingIndicatorLayer : CALayer 13 | 14 | @property (nonatomic, assign) float progress; 15 | 16 | @property (nonatomic, weak) UIColor *ringColor; 17 | @property (nonatomic, weak) UIColor *ringBackgroundColor; 18 | 19 | @property (nonatomic, assign) BOOL roundProgressLine; 20 | 21 | @property (nonatomic, assign) CGFloat ringWidth; 22 | 23 | @end 24 | 25 | @implementation JGProgressHUDRingIndicatorLayer 26 | 27 | @dynamic progress, ringBackgroundColor, ringColor, ringWidth, roundProgressLine; 28 | 29 | + (BOOL)needsDisplayForKey:(NSString *)key { 30 | return ([key isEqualToString:@"progress"] || [key isEqualToString:@"ringColor"] || [key isEqualToString:@"ringBackgroundColor"] || [key isEqualToString:@"roundProgressLine"] || [key isEqualToString:@"ringWidth"] || [super needsDisplayForKey:key]); 31 | } 32 | 33 | - (id )actionForKey:(NSString *)key { 34 | if ([key isEqualToString:@"progress"]) { 35 | CABasicAnimation *progressAnimation = [CABasicAnimation animation]; 36 | progressAnimation.fromValue = [self.presentationLayer valueForKey:key]; 37 | 38 | progressAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 39 | 40 | return progressAnimation; 41 | } 42 | 43 | return [super actionForKey:key]; 44 | } 45 | 46 | - (void)drawInContext:(CGContextRef)ctx { 47 | UIGraphicsPushContext(ctx); 48 | 49 | CGRect rect = self.bounds; 50 | 51 | CGPoint center = CGPointMake(rect.origin.x + (CGFloat)floor(rect.size.width/2.0), rect.origin.y + (CGFloat)floor(rect.size.height/2.0)); 52 | CGFloat lineWidth = self.ringWidth; 53 | CGFloat radius = (CGFloat)floor(MIN(rect.size.width, rect.size.height)/2.0) - lineWidth; 54 | 55 | //Background 56 | [self.ringBackgroundColor setStroke]; 57 | 58 | UIBezierPath *borderPath = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:0.0 endAngle:2.0*(CGFloat)M_PI clockwise:NO]; 59 | 60 | [borderPath setLineWidth:lineWidth]; 61 | [borderPath stroke]; 62 | 63 | //Progress 64 | [self.ringColor setStroke]; 65 | 66 | if (self.progress > 0.0) { 67 | UIBezierPath *processPath = [UIBezierPath bezierPath]; 68 | 69 | [processPath setLineWidth:lineWidth]; 70 | [processPath setLineCapStyle:(self.roundProgressLine ? kCGLineCapRound : kCGLineCapSquare)]; 71 | 72 | CGFloat startAngle = -((CGFloat)M_PI / 2.0); 73 | CGFloat endAngle = startAngle + 2.0 * (CGFloat)M_PI * self.progress; 74 | 75 | [processPath addArcWithCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES]; 76 | 77 | [processPath stroke]; 78 | } 79 | 80 | UIGraphicsPopContext(); 81 | } 82 | 83 | @end 84 | 85 | 86 | @implementation JGProgressHUDRingIndicatorView 87 | 88 | #pragma mark - Initializers 89 | 90 | - (instancetype)init { 91 | self = [super initWithContentView:nil];; 92 | 93 | if (self) { 94 | self.layer.contentsScale = [UIScreen mainScreen].scale; 95 | [self.layer setNeedsDisplay]; 96 | 97 | self.ringWidth = 3.0; 98 | self.ringColor = [UIColor clearColor]; 99 | self.ringBackgroundColor = [UIColor clearColor]; 100 | } 101 | 102 | return self; 103 | } 104 | 105 | - (instancetype)initWithHUDStyle:(JGProgressHUDStyle)style { 106 | return [self init]; 107 | } 108 | 109 | - (instancetype)initWithContentView:(UIView *)contentView { 110 | return [self init]; 111 | } 112 | 113 | #pragma mark - Getters & Setters 114 | 115 | - (void)setRoundProgressLine:(BOOL)roundProgressLine { 116 | if (roundProgressLine == self.roundProgressLine) { 117 | return; 118 | } 119 | 120 | _roundProgressLine = roundProgressLine; 121 | 122 | [(JGProgressHUDRingIndicatorLayer *)self.layer setRoundProgressLine:self.roundProgressLine]; 123 | } 124 | 125 | - (void)setRingColor:(UIColor *)tintColor { 126 | if ([tintColor isEqual:self.ringColor]) { 127 | return; 128 | } 129 | 130 | _ringColor = tintColor; 131 | 132 | [(JGProgressHUDRingIndicatorLayer *)self.layer setRingColor:self.ringColor]; 133 | } 134 | 135 | - (void)setRingBackgroundColor:(UIColor *)backgroundTintColor { 136 | if ([backgroundTintColor isEqual:self.ringBackgroundColor]) { 137 | return; 138 | } 139 | 140 | _ringBackgroundColor = backgroundTintColor; 141 | 142 | [(JGProgressHUDRingIndicatorLayer *)self.layer setRingBackgroundColor:self.ringBackgroundColor]; 143 | } 144 | 145 | - (void)setRingWidth:(CGFloat)ringWidth { 146 | if (fequal(ringWidth, self.ringWidth)) { 147 | return; 148 | } 149 | 150 | _ringWidth = ringWidth; 151 | 152 | [(JGProgressHUDRingIndicatorLayer *)self.layer setRingWidth:self.ringWidth]; 153 | } 154 | 155 | - (void)setProgress:(float)progress animated:(BOOL)animated { 156 | if (fequal(self.progress, progress)) { 157 | return; 158 | } 159 | 160 | [super setProgress:progress animated:animated]; 161 | 162 | [CATransaction begin]; 163 | [CATransaction setAnimationDuration:(animated ? 0.3 : 0.0)]; 164 | 165 | [(JGProgressHUDRingIndicatorLayer *)self.layer setProgress:self.progress]; 166 | 167 | [CATransaction commit]; 168 | } 169 | 170 | #pragma mark - Overrides 171 | 172 | - (void)setUpForHUDStyle:(JGProgressHUDStyle)style vibrancyEnabled:(BOOL)vibrancyEnabled { 173 | [super setUpForHUDStyle:style vibrancyEnabled:vibrancyEnabled]; 174 | 175 | if (style == JGProgressHUDStyleDark) { 176 | self.ringColor = [UIColor colorWithWhite:1.0 alpha:1.0]; 177 | self.ringBackgroundColor = [UIColor colorWithWhite:0.0 alpha:1.0]; 178 | } 179 | else { 180 | self.ringColor = [UIColor blackColor]; 181 | if (style == JGProgressHUDStyleLight) { 182 | self.ringBackgroundColor = [UIColor colorWithWhite:0.85 alpha:1.0]; 183 | } 184 | else { 185 | self.ringBackgroundColor = [UIColor colorWithWhite:0.9 alpha:1.0]; 186 | } 187 | } 188 | } 189 | 190 | + (Class)layerClass { 191 | return [JGProgressHUDRingIndicatorLayer class]; 192 | } 193 | 194 | @end 195 | -------------------------------------------------------------------------------- /statics/fmdb/FMDatabaseAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // FMDatabaseAdditions.h 3 | // fmdb 4 | // 5 | // Created by August Mueller on 10/30/05. 6 | // Copyright 2005 Flying Meat Inc.. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "FMDatabase.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | /** Category of additions for `` class. 15 | 16 | ### See also 17 | 18 | - `` 19 | */ 20 | 21 | @interface FMDatabase (FMDatabaseAdditions) 22 | 23 | ///---------------------------------------- 24 | /// @name Return results of SQL to variable 25 | ///---------------------------------------- 26 | 27 | /** Return `int` value for query 28 | 29 | @param query The SQL query to be performed. 30 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. 31 | 32 | @return `int` value. 33 | 34 | @note This is not available from Swift. 35 | */ 36 | 37 | - (int)intForQuery:(NSString*)query, ...; 38 | 39 | /** Return `long` value for query 40 | 41 | @param query The SQL query to be performed. 42 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. 43 | 44 | @return `long` value. 45 | 46 | @note This is not available from Swift. 47 | */ 48 | 49 | - (long)longForQuery:(NSString*)query, ...; 50 | 51 | /** Return `BOOL` value for query 52 | 53 | @param query The SQL query to be performed. 54 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. 55 | 56 | @return `BOOL` value. 57 | 58 | @note This is not available from Swift. 59 | */ 60 | 61 | - (BOOL)boolForQuery:(NSString*)query, ...; 62 | 63 | /** Return `double` value for query 64 | 65 | @param query The SQL query to be performed. 66 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. 67 | 68 | @return `double` value. 69 | 70 | @note This is not available from Swift. 71 | */ 72 | 73 | - (double)doubleForQuery:(NSString*)query, ...; 74 | 75 | /** Return `NSString` value for query 76 | 77 | @param query The SQL query to be performed. 78 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. 79 | 80 | @return `NSString` value. 81 | 82 | @note This is not available from Swift. 83 | */ 84 | 85 | - (NSString * _Nullable)stringForQuery:(NSString*)query, ...; 86 | 87 | /** Return `NSData` value for query 88 | 89 | @param query The SQL query to be performed. 90 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. 91 | 92 | @return `NSData` value. 93 | 94 | @note This is not available from Swift. 95 | */ 96 | 97 | - (NSData * _Nullable)dataForQuery:(NSString*)query, ...; 98 | 99 | /** Return `NSDate` value for query 100 | 101 | @param query The SQL query to be performed. 102 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. 103 | 104 | @return `NSDate` value. 105 | 106 | @note This is not available from Swift. 107 | */ 108 | 109 | - (NSDate * _Nullable)dateForQuery:(NSString*)query, ...; 110 | 111 | 112 | // Notice that there's no dataNoCopyForQuery:. 113 | // That would be a bad idea, because we close out the result set, and then what 114 | // happens to the data that we just didn't copy? Who knows, not I. 115 | 116 | 117 | ///-------------------------------- 118 | /// @name Schema related operations 119 | ///-------------------------------- 120 | 121 | /** Does table exist in database? 122 | 123 | @param tableName The name of the table being looked for. 124 | 125 | @return `YES` if table found; `NO` if not found. 126 | */ 127 | 128 | - (BOOL)tableExists:(NSString*)tableName; 129 | 130 | /** The schema of the database. 131 | 132 | This will be the schema for the entire database. For each entity, each row of the result set will include the following fields: 133 | 134 | - `type` - The type of entity (e.g. table, index, view, or trigger) 135 | - `name` - The name of the object 136 | - `tbl_name` - The name of the table to which the object references 137 | - `rootpage` - The page number of the root b-tree page for tables and indices 138 | - `sql` - The SQL that created the entity 139 | 140 | @return `FMResultSet` of schema; `nil` on error. 141 | 142 | @see [SQLite File Format](http://www.sqlite.org/fileformat.html) 143 | */ 144 | 145 | - (FMResultSet * _Nullable)getSchema; 146 | 147 | /** The schema of the database. 148 | 149 | This will be the schema for a particular table as report by SQLite `PRAGMA`, for example: 150 | 151 | PRAGMA table_info('employees') 152 | 153 | This will report: 154 | 155 | - `cid` - The column ID number 156 | - `name` - The name of the column 157 | - `type` - The data type specified for the column 158 | - `notnull` - whether the field is defined as NOT NULL (i.e. values required) 159 | - `dflt_value` - The default value for the column 160 | - `pk` - Whether the field is part of the primary key of the table 161 | 162 | @param tableName The name of the table for whom the schema will be returned. 163 | 164 | @return `FMResultSet` of schema; `nil` on error. 165 | 166 | @see [table_info](http://www.sqlite.org/pragma.html#pragma_table_info) 167 | */ 168 | 169 | - (FMResultSet * _Nullable)getTableSchema:(NSString*)tableName; 170 | 171 | /** Test to see if particular column exists for particular table in database 172 | 173 | @param columnName The name of the column. 174 | 175 | @param tableName The name of the table. 176 | 177 | @return `YES` if column exists in table in question; `NO` otherwise. 178 | */ 179 | 180 | - (BOOL)columnExists:(NSString*)columnName inTableWithName:(NSString*)tableName; 181 | 182 | /** Test to see if particular column exists for particular table in database 183 | 184 | @param columnName The name of the column. 185 | 186 | @param tableName The name of the table. 187 | 188 | @return `YES` if column exists in table in question; `NO` otherwise. 189 | 190 | @see columnExists:inTableWithName: 191 | 192 | @warning Deprecated - use `` instead. 193 | */ 194 | 195 | - (BOOL)columnExists:(NSString*)tableName columnName:(NSString*)columnName __deprecated_msg("Use columnExists:inTableWithName: instead"); 196 | 197 | 198 | /** Validate SQL statement 199 | 200 | This validates SQL statement by performing `sqlite3_prepare_v2`, but not returning the results, but instead immediately calling `sqlite3_finalize`. 201 | 202 | @param sql The SQL statement being validated. 203 | 204 | @param error This is a pointer to a `NSError` object that will receive the autoreleased `NSError` object if there was any error. If this is `nil`, no `NSError` result will be returned. 205 | 206 | @return `YES` if validation succeeded without incident; `NO` otherwise. 207 | 208 | */ 209 | 210 | - (BOOL)validateSQL:(NSString*)sql error:(NSError * _Nullable *)error; 211 | 212 | 213 | ///----------------------------------- 214 | /// @name Application identifier tasks 215 | ///----------------------------------- 216 | 217 | /** Retrieve application ID 218 | 219 | @return The `uint32_t` numeric value of the application ID. 220 | 221 | @see setApplicationID: 222 | */ 223 | 224 | @property (nonatomic) uint32_t applicationID; 225 | 226 | #if TARGET_OS_MAC && !TARGET_OS_IPHONE 227 | 228 | /** Retrieve application ID string 229 | 230 | @see setApplicationIDString: 231 | */ 232 | 233 | @property (nonatomic, retain) NSString *applicationIDString; 234 | 235 | #endif 236 | 237 | ///----------------------------------- 238 | /// @name user version identifier tasks 239 | ///----------------------------------- 240 | 241 | /** Retrieve user version 242 | 243 | @see setUserVersion: 244 | */ 245 | 246 | @property (nonatomic) uint32_t userVersion; 247 | 248 | @end 249 | 250 | NS_ASSUME_NONNULL_END 251 | -------------------------------------------------------------------------------- /callkiller-gui/IgnoredPrefixVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // IgnoredPrefixVC.m 3 | // callkiller-gui 4 | // 5 | // Created by mac on 2018/8/14. 6 | // 7 | 8 | #import "IgnoredPrefixVC.h" 9 | #import "Preference.h" 10 | #import "AlertUtil.h" 11 | 12 | @interface IgnoredPrefixVC () 13 | @property (weak, nonatomic) IBOutlet UIBarButtonItem *trashButton; 14 | @property (weak, nonatomic) IBOutlet UITableView *tableview; 15 | @property (weak, nonatomic) UIAlertAction *alertAction; 16 | @end 17 | 18 | @implementation IgnoredPrefixVC 19 | 20 | - (void)viewDidLoad { 21 | [super viewDidLoad]; 22 | 23 | NSDictionary *pref = [[Preference sharedInstance] pref]; 24 | NSArray *list = pref[kKeyIgnoredPrefixes]; 25 | self.trashButton.enabled = list.count > 0; 26 | } 27 | 28 | - (void)didReceiveMemoryWarning { 29 | [super didReceiveMemoryWarning]; 30 | // Dispose of any resources that can be recreated. 31 | } 32 | - (IBAction)onTrash:(id)sender { 33 | [AlertUtil showQuery:NSLocalizedString(@"del-all-prefixes-prompt", nil) message:nil isDanger:YES onConfirm:^{ 34 | NSMutableDictionary *pref = [[Preference sharedInstance] pref]; 35 | NSMutableArray *list = pref[kKeyIgnoredPrefixes]; 36 | [list removeAllObjects]; 37 | [[Preference sharedInstance] save]; 38 | [self.tableview reloadData]; 39 | self.trashButton.enabled = NO; 40 | }]; 41 | } 42 | - (IBAction)onAdd:(id)sender { 43 | UIAlertController *alert = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"add-prefix-title", nil) message:NSLocalizedString(@"add-prefix-content", nil) preferredStyle:UIAlertControllerStyleAlert]; 44 | 45 | [alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"cancel", nil) style:UIAlertActionStyleCancel handler:nil]]; 46 | UIAlertAction *confirm = [UIAlertAction actionWithTitle:NSLocalizedString(@"ok", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { 47 | NSString *number = alert.textFields[0].text; 48 | NSArray *words = [number componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; 49 | number = [words componentsJoinedByString:@""]; 50 | if (number.length) { 51 | NSString *pattern = [number stringByReplacingOccurrencesOfString:@"?" withString:@"\\d"]; 52 | pattern = [NSString stringWithFormat:@"^%@\\d+", pattern]; 53 | 54 | NSMutableDictionary *pref = [[Preference sharedInstance] pref]; 55 | NSMutableArray *prefixes = pref[kKeyIgnoredPrefixes]; 56 | if (!prefixes) { 57 | prefixes = [NSMutableArray new]; 58 | pref[kKeyIgnoredPrefixes] = prefixes; 59 | } 60 | for (NSArray *item in prefixes) { 61 | if ([item[0] isEqualToString:number]) { 62 | [AlertUtil showInfo:NSLocalizedString(@"duplicated-entry", nil) message:nil]; 63 | return; 64 | } 65 | } 66 | [prefixes addObject:@[number, pattern, [alert.textFields[1].text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]]]; 67 | [[Preference sharedInstance] save]; 68 | [self.tableview reloadData]; 69 | self.trashButton.enabled = YES; 70 | } 71 | }]; 72 | confirm.enabled = NO; 73 | self.alertAction = confirm; 74 | [alert addAction:confirm]; 75 | [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { 76 | textField.keyboardType = UIKeyboardTypeASCIICapable; 77 | textField.delegate = self; 78 | }]; 79 | [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { 80 | textField.placeholder = NSLocalizedString(@"comment-optional", nil); 81 | }]; 82 | [UIApplication.sharedApplication.keyWindow.rootViewController presentViewController:alert animated:YES completion:nil]; 83 | } 84 | 85 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 86 | NSDictionary *pref = [[Preference sharedInstance] pref]; 87 | NSArray *list = pref[kKeyIgnoredPrefixes]; 88 | return list.count; 89 | } 90 | 91 | - (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 92 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"]; 93 | NSDictionary *pref = [[Preference sharedInstance] pref]; 94 | NSArray *list = pref[kKeyIgnoredPrefixes]; 95 | cell.textLabel.text = list[indexPath.row][0]; 96 | cell.detailTextLabel.text = list[indexPath.row][2]; 97 | return cell; 98 | } 99 | 100 | - (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath { 101 | NSMutableArray *actions = [NSMutableArray new]; 102 | 103 | [actions addObject:[UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:NSLocalizedString(@"comment", nil) handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) { 104 | NSMutableDictionary *pref = [[Preference sharedInstance] pref]; 105 | NSMutableArray *list = pref[kKeyIgnoredPrefixes]; 106 | NSMutableArray *item = [list[indexPath.row] mutableCopy]; 107 | 108 | UIAlertController *alert = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"edit-comment", nil) message:nil preferredStyle:UIAlertControllerStyleAlert]; 109 | [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { 110 | textField.text = item[2]; 111 | }]; 112 | [alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"cancel", nil) style:UIAlertActionStyleCancel handler:nil]]; 113 | [alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"ok", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { 114 | item[2] = [alert.textFields[0].text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; 115 | list[indexPath.row] = item; 116 | [[Preference sharedInstance] saveOnly]; // 无需通知SpringBoard 117 | [self.tableview reloadData]; 118 | }]]; 119 | [UIApplication.sharedApplication.keyWindow.rootViewController presentViewController:alert animated:YES completion:nil]; 120 | [tableView setEditing:NO animated:NO]; 121 | 122 | if (list.count == 0) { 123 | self.trashButton.enabled = NO; 124 | } 125 | }]]; 126 | 127 | [actions addObject:[UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDestructive title:NSLocalizedString(@"delete", nil) handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) { 128 | NSMutableDictionary *pref = [[Preference sharedInstance] pref]; 129 | NSMutableArray *list = pref[kKeyIgnoredPrefixes]; 130 | [list removeObjectAtIndex:indexPath.row]; 131 | [[Preference sharedInstance] save]; 132 | [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; 133 | [tableView setEditing:NO animated:NO]; 134 | 135 | if (list.count == 0) { 136 | self.trashButton.enabled = NO; 137 | } 138 | }]]; 139 | return actions; 140 | } 141 | 142 | - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { 143 | NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789? "] invertedSet]; 144 | NSString *filteredstring = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:@""]; 145 | BOOL allow = [string isEqualToString:filteredstring]; 146 | if (allow) { 147 | NSString *newText = [textField.text stringByReplacingCharactersInRange:range withString:string]; 148 | self.alertAction.enabled = newText.length > 0; 149 | } 150 | return allow; 151 | } 152 | 153 | @end 154 | -------------------------------------------------------------------------------- /statics/fmdb/FMDatabaseAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // FMDatabaseAdditions.m 3 | // fmdb 4 | // 5 | // Created by August Mueller on 10/30/05. 6 | // Copyright 2005 Flying Meat Inc.. All rights reserved. 7 | // 8 | 9 | #import "FMDatabase.h" 10 | #import "FMDatabaseAdditions.h" 11 | #import "TargetConditionals.h" 12 | 13 | #if FMDB_SQLITE_STANDALONE 14 | #import 15 | #else 16 | #import 17 | #endif 18 | 19 | @interface FMDatabase (PrivateStuff) 20 | - (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray * _Nullable)arrayArgs orDictionary:(NSDictionary * _Nullable)dictionaryArgs orVAList:(va_list)args; 21 | @end 22 | 23 | @implementation FMDatabase (FMDatabaseAdditions) 24 | 25 | #define RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(type, sel) \ 26 | va_list args; \ 27 | va_start(args, query); \ 28 | FMResultSet *resultSet = [self executeQuery:query withArgumentsInArray:0x00 orDictionary:0x00 orVAList:args]; \ 29 | va_end(args); \ 30 | if (![resultSet next]) { return (type)0; } \ 31 | type ret = [resultSet sel:0]; \ 32 | [resultSet close]; \ 33 | [resultSet setParentDB:nil]; \ 34 | return ret; 35 | 36 | 37 | - (NSString *)stringForQuery:(NSString*)query, ... { 38 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSString *, stringForColumnIndex); 39 | } 40 | 41 | - (int)intForQuery:(NSString*)query, ... { 42 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(int, intForColumnIndex); 43 | } 44 | 45 | - (long)longForQuery:(NSString*)query, ... { 46 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(long, longForColumnIndex); 47 | } 48 | 49 | - (BOOL)boolForQuery:(NSString*)query, ... { 50 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(BOOL, boolForColumnIndex); 51 | } 52 | 53 | - (double)doubleForQuery:(NSString*)query, ... { 54 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(double, doubleForColumnIndex); 55 | } 56 | 57 | - (NSData*)dataForQuery:(NSString*)query, ... { 58 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSData *, dataForColumnIndex); 59 | } 60 | 61 | - (NSDate*)dateForQuery:(NSString*)query, ... { 62 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSDate *, dateForColumnIndex); 63 | } 64 | 65 | 66 | - (BOOL)tableExists:(NSString*)tableName { 67 | 68 | tableName = [tableName lowercaseString]; 69 | 70 | FMResultSet *rs = [self executeQuery:@"select [sql] from sqlite_master where [type] = 'table' and lower(name) = ?", tableName]; 71 | 72 | //if at least one next exists, table exists 73 | BOOL returnBool = [rs next]; 74 | 75 | //close and free object 76 | [rs close]; 77 | 78 | return returnBool; 79 | } 80 | 81 | /* 82 | get table with list of tables: result colums: type[STRING], name[STRING],tbl_name[STRING],rootpage[INTEGER],sql[STRING] 83 | check if table exist in database (patch from OZLB) 84 | */ 85 | - (FMResultSet * _Nullable)getSchema { 86 | 87 | //result colums: type[STRING], name[STRING],tbl_name[STRING],rootpage[INTEGER],sql[STRING] 88 | FMResultSet *rs = [self executeQuery:@"SELECT type, name, tbl_name, rootpage, sql FROM (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master) WHERE type != 'meta' AND name NOT LIKE 'sqlite_%' ORDER BY tbl_name, type DESC, name"]; 89 | 90 | return rs; 91 | } 92 | 93 | /* 94 | get table schema: result colums: cid[INTEGER], name,type [STRING], notnull[INTEGER], dflt_value[],pk[INTEGER] 95 | */ 96 | - (FMResultSet * _Nullable)getTableSchema:(NSString*)tableName { 97 | 98 | //result colums: cid[INTEGER], name,type [STRING], notnull[INTEGER], dflt_value[],pk[INTEGER] 99 | FMResultSet *rs = [self executeQuery:[NSString stringWithFormat: @"pragma table_info('%@')", tableName]]; 100 | 101 | return rs; 102 | } 103 | 104 | - (BOOL)columnExists:(NSString*)columnName inTableWithName:(NSString*)tableName { 105 | 106 | BOOL returnBool = NO; 107 | 108 | tableName = [tableName lowercaseString]; 109 | columnName = [columnName lowercaseString]; 110 | 111 | FMResultSet *rs = [self getTableSchema:tableName]; 112 | 113 | //check if column is present in table schema 114 | while ([rs next]) { 115 | if ([[[rs stringForColumn:@"name"] lowercaseString] isEqualToString:columnName]) { 116 | returnBool = YES; 117 | break; 118 | } 119 | } 120 | 121 | //If this is not done FMDatabase instance stays out of pool 122 | [rs close]; 123 | 124 | return returnBool; 125 | } 126 | 127 | 128 | 129 | - (uint32_t)applicationID { 130 | #if SQLITE_VERSION_NUMBER >= 3007017 131 | uint32_t r = 0; 132 | 133 | FMResultSet *rs = [self executeQuery:@"pragma application_id"]; 134 | 135 | if ([rs next]) { 136 | r = (uint32_t)[rs longLongIntForColumnIndex:0]; 137 | } 138 | 139 | [rs close]; 140 | 141 | return r; 142 | #else 143 | NSString *errorMessage = NSLocalizedString(@"Application ID functions require SQLite 3.7.17", nil); 144 | if (self.logsErrors) NSLog(@"%@", errorMessage); 145 | return 0; 146 | #endif 147 | } 148 | 149 | - (void)setApplicationID:(uint32_t)appID { 150 | #if SQLITE_VERSION_NUMBER >= 3007017 151 | NSString *query = [NSString stringWithFormat:@"pragma application_id=%d", appID]; 152 | FMResultSet *rs = [self executeQuery:query]; 153 | [rs next]; 154 | [rs close]; 155 | #else 156 | NSString *errorMessage = NSLocalizedString(@"Application ID functions require SQLite 3.7.17", nil); 157 | if (self.logsErrors) NSLog(@"%@", errorMessage); 158 | #endif 159 | } 160 | 161 | 162 | #if TARGET_OS_MAC && !TARGET_OS_IPHONE 163 | 164 | - (NSString*)applicationIDString { 165 | #if SQLITE_VERSION_NUMBER >= 3007017 166 | NSString *s = NSFileTypeForHFSTypeCode([self applicationID]); 167 | 168 | assert([s length] == 6); 169 | 170 | s = [s substringWithRange:NSMakeRange(1, 4)]; 171 | 172 | 173 | return s; 174 | #else 175 | NSString *errorMessage = NSLocalizedString(@"Application ID functions require SQLite 3.7.17", nil); 176 | if (self.logsErrors) NSLog(@"%@", errorMessage); 177 | return nil; 178 | #endif 179 | } 180 | 181 | - (void)setApplicationIDString:(NSString*)s { 182 | #if SQLITE_VERSION_NUMBER >= 3007017 183 | if ([s length] != 4) { 184 | NSLog(@"setApplicationIDString: string passed is not exactly 4 chars long. (was %ld)", [s length]); 185 | } 186 | 187 | [self setApplicationID:NSHFSTypeCodeFromFileType([NSString stringWithFormat:@"'%@'", s])]; 188 | #else 189 | NSString *errorMessage = NSLocalizedString(@"Application ID functions require SQLite 3.7.17", nil); 190 | if (self.logsErrors) NSLog(@"%@", errorMessage); 191 | #endif 192 | } 193 | 194 | #endif 195 | 196 | - (uint32_t)userVersion { 197 | uint32_t r = 0; 198 | 199 | FMResultSet *rs = [self executeQuery:@"pragma user_version"]; 200 | 201 | if ([rs next]) { 202 | r = (uint32_t)[rs longLongIntForColumnIndex:0]; 203 | } 204 | 205 | [rs close]; 206 | return r; 207 | } 208 | 209 | - (void)setUserVersion:(uint32_t)version { 210 | NSString *query = [NSString stringWithFormat:@"pragma user_version = %d", version]; 211 | FMResultSet *rs = [self executeQuery:query]; 212 | [rs next]; 213 | [rs close]; 214 | } 215 | 216 | #pragma clang diagnostic push 217 | #pragma clang diagnostic ignored "-Wdeprecated-implementations" 218 | 219 | - (BOOL)columnExists:(NSString*)tableName columnName:(NSString*)columnName __attribute__ ((deprecated)) { 220 | return [self columnExists:columnName inTableWithName:tableName]; 221 | } 222 | 223 | #pragma clang diagnostic pop 224 | 225 | - (BOOL)validateSQL:(NSString*)sql error:(NSError**)error { 226 | sqlite3_stmt *pStmt = NULL; 227 | BOOL validationSucceeded = YES; 228 | 229 | int rc = sqlite3_prepare_v2([self sqliteHandle], [sql UTF8String], -1, &pStmt, 0); 230 | if (rc != SQLITE_OK) { 231 | validationSucceeded = NO; 232 | if (error) { 233 | *error = [NSError errorWithDomain:NSCocoaErrorDomain 234 | code:[self lastErrorCode] 235 | userInfo:[NSDictionary dictionaryWithObject:[self lastErrorMessage] 236 | forKey:NSLocalizedDescriptionKey]]; 237 | } 238 | } 239 | 240 | sqlite3_finalize(pStmt); 241 | 242 | return validationSucceeded; 243 | } 244 | 245 | @end 246 | -------------------------------------------------------------------------------- /callkiller/CHRecentCall.h: -------------------------------------------------------------------------------- 1 | // 2 | // CHRecentCall.h 3 | // callkiller 4 | // 5 | // Created by mac on 2018/7/28. 6 | // 7 | 8 | #ifndef CHRecentCall_h 9 | #define CHRecentCall_h 10 | 11 | @interface CHRecentCall// : CHSynchronizable { 12 | // NSString * _addressBookCallerIDMultiValueId; 13 | // NSString * _addressBookRecordId; 14 | // NSValue * _addressBookRecordRef; 15 | // BOOL _answered; 16 | // NSNumber * _bytesOfDataUsed; 17 | // unsigned int _callCategory; 18 | // NSMutableArray * _callOccurrences; 19 | // unsigned int _callStatus; 20 | // unsigned int _callType; 21 | // NSString * _callerId; 22 | // unsigned int _callerIdAvailability; 23 | // NSString * _callerIdFormatted; 24 | // BOOL _callerIdIsBlocked; 25 | // NSString * _callerIdLabel; 26 | // NSString * _callerIdLocation; 27 | // NSString * _callerName; 28 | // NSString * _callerNetworkFirstName; 29 | // NSString * _callerNetworkName; 30 | // NSString * _callerNetworkSecondName; 31 | // NSString * _clientAddressBookRecordId; 32 | // NSDate * _date; 33 | // NSString * _devicePhoneId; 34 | // NSNumber * _disconnectedCause; 35 | // double _duration; 36 | // int _handleType; 37 | // NSString * _isoCountryCode; 38 | // int _mediaType; 39 | // NSString * _mobileCountryCode; 40 | // NSString * _mobileNetworkCode; 41 | // BOOL _mobileOriginated; 42 | // BOOL _multiCall; 43 | // * _phoneBookManager; 44 | // BOOL _read; 45 | // NSString * _serviceProvider; 46 | // int _ttyType; 47 | // NSString * _uniqueId; 48 | // unsigned int _unreadCount; 49 | //} 50 | 51 | @property (nonatomic, copy) NSString *addressBookCallerIDMultiValueId; 52 | @property (nonatomic, copy) NSString *addressBookRecordId; 53 | @property (copy) NSValue *addressBookRecordRef; 54 | @property BOOL answered; 55 | @property (copy) NSNumber *bytesOfDataUsed; 56 | @property (nonatomic) unsigned int callCategory; 57 | @property (nonatomic, retain) NSMutableArray *callOccurrences; 58 | @property unsigned int callStatus; 59 | @property (nonatomic) unsigned int callType; 60 | @property (copy) NSString *callerId; 61 | @property (nonatomic) unsigned int callerIdAvailability; 62 | @property (getter=callerIdForDisplay, nonatomic, copy) NSString *callerIdFormatted; 63 | @property BOOL callerIdIsBlocked; 64 | @property (nonatomic, copy) NSString *callerIdLabel; 65 | @property (nonatomic, copy) NSString *callerIdLocation; 66 | @property (nonatomic, copy) NSString *callerName; 67 | @property (copy) NSString *callerNetworkFirstName; 68 | @property (nonatomic, copy) NSString *callerNetworkName; 69 | @property (copy) NSString *callerNetworkSecondName; 70 | @property (copy) NSString *clientAddressBookRecordId; 71 | @property (copy) NSDate *date; 72 | @property (copy) NSString *devicePhoneId; 73 | @property (copy) NSNumber *disconnectedCause; 74 | @property double duration; 75 | @property (nonatomic) int handleType; 76 | @property (copy) NSString *isoCountryCode; 77 | @property (nonatomic) int mediaType; 78 | @property (copy) NSString *mobileCountryCode; 79 | @property (copy) NSString *mobileNetworkCode; 80 | @property BOOL mobileOriginated; 81 | @property BOOL multiCall; 82 | //@property (retain) *phoneBookManager; 83 | @property (nonatomic) BOOL read; 84 | @property (nonatomic, copy) NSString *serviceProvider; 85 | @property (nonatomic) int ttyType; 86 | @property (copy) NSString *uniqueId; 87 | @property unsigned int unreadCount; 88 | 89 | + (id)callCategoryAsString:(unsigned int)arg1; 90 | + (id)callHandleTypeAsString:(int)arg1; 91 | + (id)callMediaTypeAsString:(int)arg1; 92 | + (id)callStatusAsString:(unsigned int)arg1; 93 | + (id)callTTYTypeAsString:(int)arg1; 94 | + (id)callTypeAsString:(unsigned int)arg1; 95 | + (unsigned int)categoryForCallType:(unsigned int)arg1; 96 | + (unsigned int)categoryForMediaType:(int)arg1 andTTYType:(int)arg2; 97 | + (unsigned int)getCallTypeForCategory:(unsigned int)arg1 andServiceProvider:(id)arg2; 98 | + (id)getLocationForCallerId:(id)arg1 andIsoCountryCode:(id)arg2; 99 | + (int)handleTypeForCallerId:(id)arg1; 100 | + (int)mediaTypeForCallCategory:(unsigned int)arg1; 101 | + (id)serviceProviderForCallType:(unsigned int)arg1; 102 | + (BOOL)supportsSecureCoding; 103 | + (int)ttyTypeForCallCategory:(unsigned int)arg1; 104 | 105 | //- (void).cxx_destruct; 106 | - (void)addOccurrencesFromArraySync:(id)arg1; 107 | - (id)addressBookCallerIDMultiValueId; 108 | - (id)addressBookCallerIDMultiValueIdSync; 109 | - (void)addressBookChanged; 110 | - (id)addressBookRecordId; 111 | - (id)addressBookRecordIdSync; 112 | - (id)addressBookRecordRef; 113 | - (id)addressBookRecordRefSync; 114 | - (BOOL)answered; 115 | - (id)bytesOfDataUsed; 116 | - (unsigned int)callCategory; 117 | - (id)callOccurrences; 118 | - (id)callOccurrencesAsStringSync; 119 | - (id)callOccurrencesSync; 120 | - (unsigned int)callStatus; 121 | - (unsigned int)callType; 122 | - (id)callerId; 123 | - (unsigned int)callerIdAvailability; 124 | - (id)callerIdForDisplay; 125 | - (id)callerIdForDisplaySync; 126 | - (BOOL)callerIdIsBlocked; 127 | - (BOOL)callerIdIsEmailAddress; 128 | - (BOOL)callerIdIsEmailAddressSync; 129 | - (id)callerIdLabel; 130 | - (id)callerIdLabelSync; 131 | - (id)callerIdLocation; 132 | - (id)callerIdLocationSync; 133 | - (id)callerIdSubStringForDisplay; 134 | - (id)callerName; 135 | - (id)callerNameForDisplay; 136 | - (id)callerNameForDisplaySync; 137 | - (id)callerNameSync; 138 | - (id)callerNetworkFirstName; 139 | - (id)callerNetworkName; 140 | - (id)callerNetworkSecondName; 141 | - (BOOL)canCoalesceSyncWithCall:(id)arg1 withStrategy:(id)arg2; 142 | - (BOOL)canCoalesceSyncWithCollapseIfEqualStrategyWithCall:(id)arg1; 143 | - (BOOL)canCoalesceSyncWithRecentsStrategyWithCall:(id)arg1; 144 | - (BOOL)canCoalesceWithCall:(id)arg1 withStrategy:(id)arg2; 145 | - (id)clientAddressBookRecordId; 146 | - (BOOL)coalesceWithCall:(id)arg1 withStrategy:(id)arg2; 147 | - (id)coalescingHash; 148 | //- (id)copyWithZone:(struct _NSZone { }*)arg1; 149 | - (void)createOccurrenceArraySync; 150 | - (id)date; 151 | - (void)dealloc; 152 | - (id)description; 153 | - (id)descriptionInDepth; 154 | - (id)devicePhoneId; 155 | - (id)disconnectedCause; 156 | - (double)duration; 157 | - (void)encodeWithCoder:(id)arg1; 158 | - (void)fetchAndSetAddressBookIdsSync; 159 | - (void)fixCallTypeInfo; 160 | - (id)getLocalizedStringSync:(id)arg1; 161 | - (void)handleCurrentLocaleDidChangeNotification:(id)arg1; 162 | - (int)handleType; 163 | - (int)handleTypeSync; 164 | - (id)init; 165 | - (id)initWithCoder:(id)arg1; 166 | - (id)initWithQueue:(id)arg1; 167 | - (BOOL)isAddressBookContactASuggestion; 168 | - (BOOL)isAddressBookContactASuggestionSync; 169 | - (BOOL)isEqual:(id)arg1; 170 | - (id)isoCountryCode; 171 | - (int)mediaType; 172 | - (id)mobileCountryCode; 173 | - (id)mobileNetworkCode; 174 | - (BOOL)mobileOriginated; 175 | - (BOOL)multiCall; 176 | - (unsigned int)numberOfOccurrences; 177 | - (unsigned int)numberOfOccurrencesSync; 178 | - (id)phoneBookManager; 179 | - (BOOL)read; 180 | - (void)registerForCurrentLocaleDidChangeNotification; 181 | - (BOOL)representsCallAtDate:(id)arg1; 182 | - (id)serviceProvider; 183 | - (void)setAddressBookCallerIDMultiValueId:(id)arg1; 184 | - (void)setAddressBookRecordId:(id)arg1; 185 | - (void)setAddressBookRecordRef:(id)arg1; 186 | - (void)setAnswered:(BOOL)arg1; 187 | - (void)setBytesOfDataUsed:(id)arg1; 188 | - (void)setCallCategory:(unsigned int)arg1; 189 | - (void)setCallOccurrences:(id)arg1; 190 | - (void)setCallStatus:(unsigned int)arg1; 191 | - (void)setCallType:(unsigned int)arg1; 192 | - (void)setCallerId:(id)arg1; 193 | - (void)setCallerIdAvailability:(unsigned int)arg1; 194 | - (void)setCallerIdFormatted:(id)arg1; 195 | - (void)setCallerIdIsBlocked:(BOOL)arg1; 196 | - (void)setCallerIdLabel:(id)arg1; 197 | - (void)setCallerIdLocation:(id)arg1; 198 | - (void)setCallerName:(id)arg1; 199 | - (void)setCallerNetworkFirstName:(id)arg1; 200 | - (void)setCallerNetworkName:(id)arg1; 201 | - (void)setCallerNetworkSecondName:(id)arg1; 202 | - (void)setClientAddressBookRecordId:(id)arg1; 203 | - (void)setDate:(id)arg1; 204 | - (void)setDevicePhoneId:(id)arg1; 205 | - (void)setDisconnectedCause:(id)arg1; 206 | - (void)setDuration:(double)arg1; 207 | - (void)setHandleType:(int)arg1; 208 | - (void)setIsoCountryCode:(id)arg1; 209 | - (void)setMediaType:(int)arg1; 210 | - (void)setMobileCountryCode:(id)arg1; 211 | - (void)setMobileNetworkCode:(id)arg1; 212 | - (void)setMobileOriginated:(BOOL)arg1; 213 | - (void)setMultiCall:(BOOL)arg1; 214 | - (void)setPhoneBookManager:(id)arg1; 215 | - (void)setRead:(BOOL)arg1; 216 | - (void)setServiceProvider:(id)arg1; 217 | - (void)setTtyType:(int)arg1; 218 | - (void)setUniqueId:(id)arg1; 219 | - (void)setUnreadCount:(unsigned int)arg1; 220 | - (int)ttyType; 221 | - (id)uniqueId; 222 | - (unsigned int)unreadCount; 223 | - (void)updateTTYAndMediaType; 224 | 225 | @end 226 | 227 | #endif /* CHRecentCall_h */ 228 | -------------------------------------------------------------------------------- /callkiller-gui/AFNetworking/AFNetworkReachabilityManager.h: -------------------------------------------------------------------------------- 1 | // AFNetworkReachabilityManager.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 | #if !TARGET_OS_WATCH 25 | #import 26 | 27 | typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) { 28 | AFNetworkReachabilityStatusUnknown = -1, 29 | AFNetworkReachabilityStatusNotReachable = 0, 30 | AFNetworkReachabilityStatusReachableViaWWAN = 1, 31 | AFNetworkReachabilityStatusReachableViaWiFi = 2, 32 | }; 33 | 34 | NS_ASSUME_NONNULL_BEGIN 35 | 36 | /** 37 | `AFNetworkReachabilityManager` monitors the reachability of domains, and addresses for both WWAN and WiFi network interfaces. 38 | 39 | Reachability can be used to determine background information about why a network operation failed, or to trigger a network operation retrying when a connection is established. It should not be used to prevent a user from initiating a network request, as it's possible that an initial request may be required to establish reachability. 40 | 41 | See Apple's Reachability Sample Code ( https://developer.apple.com/library/ios/samplecode/reachability/ ) 42 | 43 | @warning Instances of `AFNetworkReachabilityManager` must be started with `-startMonitoring` before reachability status can be determined. 44 | */ 45 | @interface AFNetworkReachabilityManager : NSObject 46 | 47 | /** 48 | The current network reachability status. 49 | */ 50 | @property (readonly, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus; 51 | 52 | /** 53 | Whether or not the network is currently reachable. 54 | */ 55 | @property (readonly, nonatomic, assign, getter = isReachable) BOOL reachable; 56 | 57 | /** 58 | Whether or not the network is currently reachable via WWAN. 59 | */ 60 | @property (readonly, nonatomic, assign, getter = isReachableViaWWAN) BOOL reachableViaWWAN; 61 | 62 | /** 63 | Whether or not the network is currently reachable via WiFi. 64 | */ 65 | @property (readonly, nonatomic, assign, getter = isReachableViaWiFi) BOOL reachableViaWiFi; 66 | 67 | ///--------------------- 68 | /// @name Initialization 69 | ///--------------------- 70 | 71 | /** 72 | Returns the shared network reachability manager. 73 | */ 74 | + (instancetype)sharedManager; 75 | 76 | /** 77 | Creates and returns a network reachability manager with the default socket address. 78 | 79 | @return An initialized network reachability manager, actively monitoring the default socket address. 80 | */ 81 | + (instancetype)manager; 82 | 83 | /** 84 | Creates and returns a network reachability manager for the specified domain. 85 | 86 | @param domain The domain used to evaluate network reachability. 87 | 88 | @return An initialized network reachability manager, actively monitoring the specified domain. 89 | */ 90 | + (instancetype)managerForDomain:(NSString *)domain; 91 | 92 | /** 93 | Creates and returns a network reachability manager for the socket address. 94 | 95 | @param address The socket address (`sockaddr_in6`) used to evaluate network reachability. 96 | 97 | @return An initialized network reachability manager, actively monitoring the specified socket address. 98 | */ 99 | + (instancetype)managerForAddress:(const void *)address; 100 | 101 | /** 102 | Initializes an instance of a network reachability manager from the specified reachability object. 103 | 104 | @param reachability The reachability object to monitor. 105 | 106 | @return An initialized network reachability manager, actively monitoring the specified reachability. 107 | */ 108 | - (instancetype)initWithReachability:(SCNetworkReachabilityRef)reachability NS_DESIGNATED_INITIALIZER; 109 | 110 | /** 111 | * Unavailable initializer 112 | */ 113 | + (instancetype)new NS_UNAVAILABLE; 114 | 115 | /** 116 | * Unavailable initializer 117 | */ 118 | - (instancetype)init NS_UNAVAILABLE; 119 | 120 | ///-------------------------------------------------- 121 | /// @name Starting & Stopping Reachability Monitoring 122 | ///-------------------------------------------------- 123 | 124 | /** 125 | Starts monitoring for changes in network reachability status. 126 | */ 127 | - (void)startMonitoring; 128 | 129 | /** 130 | Stops monitoring for changes in network reachability status. 131 | */ 132 | - (void)stopMonitoring; 133 | 134 | ///------------------------------------------------- 135 | /// @name Getting Localized Reachability Description 136 | ///------------------------------------------------- 137 | 138 | /** 139 | Returns a localized string representation of the current network reachability status. 140 | */ 141 | - (NSString *)localizedNetworkReachabilityStatusString; 142 | 143 | ///--------------------------------------------------- 144 | /// @name Setting Network Reachability Change Callback 145 | ///--------------------------------------------------- 146 | 147 | /** 148 | Sets a callback to be executed when the network availability of the `baseURL` host changes. 149 | 150 | @param block A block object to be executed when the network availability of the `baseURL` host changes.. This block has no return value and takes a single argument which represents the various reachability states from the device to the `baseURL`. 151 | */ 152 | - (void)setReachabilityStatusChangeBlock:(nullable void (^)(AFNetworkReachabilityStatus status))block; 153 | 154 | @end 155 | 156 | ///---------------- 157 | /// @name Constants 158 | ///---------------- 159 | 160 | /** 161 | ## Network Reachability 162 | 163 | The following constants are provided by `AFNetworkReachabilityManager` as possible network reachability statuses. 164 | 165 | enum { 166 | AFNetworkReachabilityStatusUnknown, 167 | AFNetworkReachabilityStatusNotReachable, 168 | AFNetworkReachabilityStatusReachableViaWWAN, 169 | AFNetworkReachabilityStatusReachableViaWiFi, 170 | } 171 | 172 | `AFNetworkReachabilityStatusUnknown` 173 | The `baseURL` host reachability is not known. 174 | 175 | `AFNetworkReachabilityStatusNotReachable` 176 | The `baseURL` host cannot be reached. 177 | 178 | `AFNetworkReachabilityStatusReachableViaWWAN` 179 | The `baseURL` host can be reached via a cellular connection, such as EDGE or GPRS. 180 | 181 | `AFNetworkReachabilityStatusReachableViaWiFi` 182 | The `baseURL` host can be reached via a Wi-Fi connection. 183 | 184 | ### Keys for Notification UserInfo Dictionary 185 | 186 | Strings that are used as keys in a `userInfo` dictionary in a network reachability status change notification. 187 | 188 | `AFNetworkingReachabilityNotificationStatusItem` 189 | A key in the userInfo dictionary in a `AFNetworkingReachabilityDidChangeNotification` notification. 190 | The corresponding value is an `NSNumber` object representing the `AFNetworkReachabilityStatus` value for the current reachability status. 191 | */ 192 | 193 | ///-------------------- 194 | /// @name Notifications 195 | ///-------------------- 196 | 197 | /** 198 | Posted when network reachability changes. 199 | This notification assigns no notification object. The `userInfo` dictionary contains an `NSNumber` object under the `AFNetworkingReachabilityNotificationStatusItem` key, representing the `AFNetworkReachabilityStatus` value for the current network reachability. 200 | 201 | @warning In order for network reachability to be monitored, include the `SystemConfiguration` framework in the active target's "Link Binary With Library" build phase, and add `#import ` to the header prefix of the project (`Prefix.pch`). 202 | */ 203 | FOUNDATION_EXPORT NSString * const AFNetworkingReachabilityDidChangeNotification; 204 | FOUNDATION_EXPORT NSString * const AFNetworkingReachabilityNotificationStatusItem; 205 | 206 | ///-------------------- 207 | /// @name Functions 208 | ///-------------------- 209 | 210 | /** 211 | Returns a localized string representation of an `AFNetworkReachabilityStatus` value. 212 | */ 213 | FOUNDATION_EXPORT NSString * AFStringFromNetworkReachabilityStatus(AFNetworkReachabilityStatus status); 214 | 215 | NS_ASSUME_NONNULL_END 216 | #endif 217 | -------------------------------------------------------------------------------- /callkiller-gui/cities.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "name":"直辖市", 3 | "group":"zhixiashi", 4 | "cities":{ 5 | "010":"北京", 6 | "021":"上海", 7 | "022":"天津", 8 | "023":"重庆" 9 | } 10 | }, 11 | { 12 | "name":"河北", 13 | "group":"hebei", 14 | "cities":{ 15 | "0311":"石家庄", 16 | "0312":"保定", 17 | "0313":"张家口", 18 | "0314":"承德", 19 | "0315":"唐山", 20 | "0316":"廊坊", 21 | "0317":"沧州", 22 | "0318":"衡水", 23 | "0319":"邢台", 24 | "0310":"邯郸", 25 | "0335":"秦皇岛" 26 | } 27 | }, 28 | { 29 | "name":"山西", 30 | "group":"shan1xi", 31 | "cities":{ 32 | "0349":"朔州", 33 | "0351":"太原", 34 | "0352":"大同", 35 | "0353":"阳泉", 36 | "0354":"晋中", 37 | "0355":"长治", 38 | "0356":"晋城", 39 | "0357":"临汾", 40 | "0358":"吕梁", 41 | "0359":"运城", 42 | "0350":"忻州" 43 | } 44 | }, 45 | { 46 | "name":"河南", 47 | "group":"henan", 48 | "cities":{ 49 | "0371":"郑州、开封", 50 | "0372":"安阳", 51 | "0373":"新乡", 52 | "0374":"许昌", 53 | "0375":"平顶山", 54 | "0376":"信阳", 55 | "0377":"南阳", 56 | "0379":"洛阳", 57 | "0370":"商丘", 58 | "0391":"焦作、济源", 59 | "0392":"鹤壁", 60 | "0393":"濮阳", 61 | "0394":"周口", 62 | "0395":"漯河", 63 | "0396":"驻马店", 64 | "0398":"三门峡" 65 | } 66 | }, 67 | { 68 | "name":"辽宁", 69 | "group":"liaoning", 70 | "cities":{ 71 | "024":"沈阳", 72 | "0411":"大连", 73 | "0412":"鞍山", 74 | "0415":"丹东", 75 | "0416":"锦州", 76 | "0417":"营口", 77 | "0418":"阜新", 78 | "0419":"辽阳", 79 | "0421":"朝阳", 80 | "0427":"盘锦", 81 | "0429":"葫芦岛" 82 | } 83 | }, 84 | { 85 | "name":"吉林", 86 | "group":"jilin", 87 | "cities":{ 88 | "0431":"长春", 89 | "0432":"吉林", 90 | "0433":"延边", 91 | "0434":"四平", 92 | "0435":"通化", 93 | "0436":"白城", 94 | "0437":"辽源", 95 | "0438":"松原", 96 | "0439":"白山" 97 | } 98 | }, 99 | { 100 | "name":"黑龙江", 101 | "group":"heilongjiang", 102 | "cities":{ 103 | "0451":"哈尔滨", 104 | "0452":"齐齐哈尔", 105 | "0453":"牡丹江", 106 | "0454":"佳木斯", 107 | "0455":"绥化", 108 | "0456":"黑河", 109 | "0457":"大兴安岭", 110 | "0458":"伊春", 111 | "0459":"大庆", 112 | "0464":"七台河", 113 | "0467":"鸡西", 114 | "0468":"鹤岗", 115 | "0469":"双鸭山" 116 | } 117 | }, 118 | { 119 | "name":"内蒙古", 120 | "group":"neimenggu", 121 | "cities":{ 122 | "0471":"呼和浩特", 123 | "0472":"包头", 124 | "0473":"乌海", 125 | "0474":"乌兰察布", 126 | "0475":"通辽", 127 | "0476":"赤峰", 128 | "0477":"鄂尔多斯", 129 | "0478":"巴彦淖尔", 130 | "0479":"锡林郭勒", 131 | "0470":"呼伦贝尔", 132 | "0482":"兴安", 133 | "0483":"阿拉善" 134 | } 135 | }, 136 | { 137 | "name":"江苏", 138 | "group":"neidou", 139 | "cities":{ 140 | "025":"南京", 141 | "0511":"镇江", 142 | "0512":"苏州", 143 | "0513":"南通", 144 | "0514":"扬州", 145 | "0515":"盐城", 146 | "0516":"徐州", 147 | "0517":"淮安", 148 | "0518":"连云港", 149 | "0519":"常州", 150 | "0510":"无锡", 151 | "0523":"泰州", 152 | "0527":"宿迁" 153 | } 154 | }, 155 | { 156 | "name":"山东", 157 | "group":"shandong", 158 | "cities":{ 159 | "0531":"济南", 160 | "0532":"青岛", 161 | "0533":"淄博", 162 | "0534":"德州", 163 | "0535":"烟台", 164 | "0536":"潍坊", 165 | "0537":"济宁", 166 | "0538":"泰安", 167 | "0539":"临沂", 168 | "0530":"菏泽", 169 | "0543":"滨州", 170 | "0546":"东营", 171 | "0631":"威海", 172 | "0632":"枣庄", 173 | "0633":"日照", 174 | "0634":"莱芜", 175 | "0635":"聊城" 176 | } 177 | }, 178 | { 179 | "name":"安徽", 180 | "group":"anhui", 181 | "cities":{ 182 | "0551":"合肥", 183 | "0552":"蚌埠", 184 | "0553":"芜湖", 185 | "0554":"淮南", 186 | "0555":"马鞍山", 187 | "0556":"安庆", 188 | "0557":"宿州", 189 | "0558":"阜阳、亳州", 190 | "0559":"黄山", 191 | "0550":"滁州", 192 | "0561":"淮北", 193 | "0562":"铜陵", 194 | "0563":"宣城", 195 | "0564":"六安", 196 | "0566":"池州" 197 | } 198 | }, 199 | { 200 | "name":"浙江", 201 | "group":"zhejiang", 202 | "cities":{ 203 | "0571":"杭州", 204 | "0572":"湖州", 205 | "0573":"嘉兴", 206 | "0574":"宁波", 207 | "0575":"绍兴", 208 | "0576":"台州", 209 | "0577":"温州", 210 | "0578":"丽水", 211 | "0579":"金华", 212 | "0570":"衢州", 213 | "0580":"舟山" 214 | } 215 | }, 216 | { 217 | "name":"福建", 218 | "group":"fujian", 219 | "cities":{ 220 | "0591":"福州", 221 | "0592":"厦门", 222 | "0593":"宁德", 223 | "0594":"莆田", 224 | "0595":"泉州", 225 | "0596":"漳州", 226 | "0597":"龙岩", 227 | "0598":"三明", 228 | "0599":"南平" 229 | } 230 | }, 231 | { 232 | "name":"湖北", 233 | "group":"hubei", 234 | "cities":{ 235 | "027":"武汉", 236 | "0711":"鄂州", 237 | "0712":"孝感", 238 | "0713":"黄冈", 239 | "0714":"黄石", 240 | "0715":"咸宁", 241 | "0716":"荆州", 242 | "0717":"宜昌", 243 | "0718":"恩施", 244 | "0719":"十堰", 245 | "0710":"襄阳", 246 | "0722":"随州", 247 | "0724":"荆门", 248 | "0728":"仙桃、天门、潜江" 249 | } 250 | }, 251 | { 252 | "name":"湖南", 253 | "group":"hunan", 254 | "cities":{ 255 | "0731":"长沙、湘潭、株洲", 256 | "0734":"衡阳", 257 | "0735":"郴州", 258 | "0736":"常德", 259 | "0737":"益阳", 260 | "0738":"娄底", 261 | "0739":"邵阳", 262 | "0730":"岳阳", 263 | "0743":"湘西", 264 | "0744":"张家界", 265 | "0745":"怀化", 266 | "0746":"永州" 267 | } 268 | }, 269 | { 270 | "name":"广东", 271 | "group":"guangdong", 272 | "cities":{ 273 | "020":"广州", 274 | "0662":"阳江", 275 | "0663":"揭阳", 276 | "0668":"茂名", 277 | "0660":"汕尾", 278 | "0751":"韶关", 279 | "0752":"惠州", 280 | "0753":"梅州", 281 | "0754":"汕头", 282 | "0755":"深圳", 283 | "0756":"珠海", 284 | "0757":"佛山", 285 | "0758":"肇庆", 286 | "0759":"湛江", 287 | "0750":"江门", 288 | "0762":"河源", 289 | "0763":"清远", 290 | "0766":"云浮", 291 | "0768":"潮州", 292 | "0769":"东莞", 293 | "0760":"中山" 294 | } 295 | }, 296 | { 297 | "name":"广西", 298 | "group":"guangxi", 299 | "cities":{ 300 | "0771":"南宁、崇左", 301 | "0772":"柳州、来宾", 302 | "0773":"桂林", 303 | "0774":"梧州、贺州", 304 | "0775":"贵港、玉林", 305 | "0776":"百色", 306 | "0777":"钦州", 307 | "0778":"河池", 308 | "0779":"北海", 309 | "0770":"防城港" 310 | } 311 | }, 312 | { 313 | "name":"江西", 314 | "group":"jiangxi", 315 | "cities":{ 316 | "0791":"南昌", 317 | "0792":"九江", 318 | "0793":"上饶", 319 | "0794":"抚州", 320 | "0795":"宜春", 321 | "0796":"吉安", 322 | "0797":"赣州", 323 | "0798":"景德镇", 324 | "0799":"萍乡", 325 | "0790":"新余", 326 | "0701":"鹰潭" 327 | } 328 | }, 329 | { 330 | "name":"四川", 331 | "group":"sichuan", 332 | "cities":{ 333 | "028":"成都", 334 | "0812":"攀枝花", 335 | "0813":"自贡", 336 | "0816":"绵阳", 337 | "0817":"南充", 338 | "0818":"达州", 339 | "0825":"遂宁", 340 | "0826":"广安", 341 | "0827":"巴中", 342 | "0831":"宜宾", 343 | "0832":"内江", 344 | "0833":"乐山", 345 | "0834":"凉山", 346 | "0835":"雅安", 347 | "0836":"甘孜", 348 | "0837":"阿坝", 349 | "0838":"德阳", 350 | "0839":"广元", 351 | "0830":"泸州" 352 | } 353 | }, 354 | { 355 | "name":"贵州", 356 | "group":"guizhou", 357 | "cities":{ 358 | "0851":"贵阳、遵义、安顺", 359 | "0854":"黔南", 360 | "0855":"黔东南", 361 | "0856":"铜仁", 362 | "0857":"毕节", 363 | "0858":"六盘水", 364 | "0859":"黔西南" 365 | } 366 | }, 367 | { 368 | "name":"云南", 369 | "group":"yunnan", 370 | "cities":{ 371 | "0691":"西双版纳", 372 | "0692":"德宏", 373 | "0871":"昆明", 374 | "0872":"大理", 375 | "0873":"红河", 376 | "0874":"曲靖", 377 | "0875":"保山", 378 | "0876":"文山", 379 | "0877":"玉溪", 380 | "0878":"楚雄", 381 | "0879":"普洱", 382 | "0870":"昭通", 383 | "0883":"临沧", 384 | "0886":"怒江", 385 | "0887":"迪庆", 386 | "0888":"丽江" 387 | } 388 | }, 389 | { 390 | "name":"西藏", 391 | "group":"xizang", 392 | "cities":{ 393 | "0891":"拉萨", 394 | "0892":"日喀则", 395 | "0893":"山南", 396 | "0894":"林芝", 397 | "0895":"昌都", 398 | "0896":"那曲", 399 | "0897":"阿里" 400 | } 401 | }, 402 | { 403 | "name":"海南", 404 | "group":"hainan", 405 | "cities":{ 406 | "0898":"全省" 407 | } 408 | }, 409 | { 410 | "name":"陕西", 411 | "group":"shan3xi", 412 | "cities":{ 413 | "029":"西安", 414 | "0911":"延安", 415 | "0912":"榆林", 416 | "0913":"渭南", 417 | "0914":"商洛", 418 | "0915":"安康", 419 | "0916":"汉中", 420 | "0917":"宝鸡", 421 | "0919":"铜川" 422 | } 423 | }, 424 | { 425 | "name":"甘肃", 426 | "group":"gansu", 427 | "cities":{ 428 | "0931":"兰州", 429 | "0932":"定西", 430 | "0933":"平凉", 431 | "0934":"庆阳", 432 | "0935":"武威、金昌", 433 | "0936":"张掖", 434 | "0937":"酒泉、嘉峪关", 435 | "0938":"天水", 436 | "0939":"陇南", 437 | "0930":"临夏", 438 | "0941":"甘南", 439 | "0943":"白银" 440 | } 441 | }, 442 | { 443 | "name":"宁夏", 444 | "group":"ningxia", 445 | "cities":{ 446 | "0951":"银川", 447 | "0952":"石嘴山", 448 | "0953":"吴忠", 449 | "0954":"固原", 450 | "0955":"中卫" 451 | } 452 | }, 453 | { 454 | "name":"青海", 455 | "group":"qinghai", 456 | "cities":{ 457 | "0971":"西宁", 458 | "0972":"海东", 459 | "0973":"黄南", 460 | "0974":"海南藏族自治州", 461 | "0975":"果洛", 462 | "0976":"玉树", 463 | "0977":"海西", 464 | "0979":"格尔木", 465 | "0970":"海北" 466 | } 467 | }, 468 | { 469 | "name":"新疆", 470 | "group":"xinjiang", 471 | "cities":{ 472 | "0991":"乌鲁木齐", 473 | "0992":"奎屯、乌苏、独山子", 474 | "0993":"石河子", 475 | "0994":"昌吉", 476 | "0995":"吐鲁番", 477 | "0996":"巴音郭楞", 478 | "0997":"阿克苏", 479 | "0998":"喀什", 480 | "0999":"伊犁", 481 | "0990":"克拉玛依", 482 | "0901":"塔城地区", 483 | "0902":"哈密", 484 | "0903":"和田地区", 485 | "0906":"阿勒泰地区", 486 | "0908":"克孜勒苏柯尔克孜", 487 | "0909":"博尔塔拉" 488 | } 489 | }] 490 | --------------------------------------------------------------------------------