Warning, /network/kdeconnect-ios/KDE Connect/KDE Connect/ObjC Backend/NetworkPackage.m is written in an unsupported language. File is not indexed.
0001 /* 0002 * SPDX-FileCopyrightText: 2014 YANG Qiao <yangqiao0505@me.com> 0003 * 2020 Weixuan Xiao <veyx.shaw@gmail.com> 0004 * 2021 Lucas Wang <lucas.wang@tuta.io> 0005 * 0006 * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0007 */ 0008 0009 // Original header below://Copyright 27/4/14 YANG Qiao yangqiao0505@me.com 0010 //kdeconnect is distributed under two licenses. 0011 // 0012 //* The Mozilla Public License (MPL) v2.0 0013 // 0014 //or 0015 // 0016 //* The General Public License (GPL) v2.1 0017 // 0018 //---------------------------------------------------------------------- 0019 // 0020 //Software distributed under these licenses is distributed on an "AS 0021 //IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 0022 //implied. See the License for the specific language governing rights 0023 //and limitations under the License. 0024 //kdeconnect is distributed under both the GPL and the MPL. The MPL 0025 //notice, reproduced below, covers the use of either of the licenses. 0026 // 0027 //--------------------------------------------------------------------- 0028 0029 #import "NetworkPackage.h" 0030 #import "Device.h" 0031 #import "KDE_Connect-Swift.h" 0032 #import "KeychainItemWrapper.h" 0033 @import UIKit; 0034 0035 @import os.log; 0036 0037 #define LFDATA [NSData dataWithBytes:"\x0A" length:1] 0038 0039 __strong static NSString* _UUID; 0040 0041 #pragma mark Implementation 0042 @implementation NetworkPackage 0043 0044 - (NetworkPackage*) initWithType:(NetworkPackageType)type 0045 { 0046 if ((self=[super init])) 0047 { 0048 _Id=[NSNumber numberWithLong:[[NSDate date] timeIntervalSince1970]]; 0049 self.type=type; 0050 _Body=[NSMutableDictionary dictionary]; 0051 } 0052 return self; 0053 } 0054 0055 @synthesize _Id; 0056 @synthesize type; 0057 @synthesize _Body; 0058 @synthesize _PayloadSize; 0059 0060 #pragma mark create Package 0061 + (NetworkPackage *)createIdentityPackageWithTCPPort:(uint16_t)tcpPort { 0062 NetworkPackage* np=[[NetworkPackage alloc] initWithType:NetworkPackageTypeIdentity]; 0063 [np setObject:[NetworkPackage getUUID] forKey:@"deviceId"]; 0064 NSString* deviceName=[[NSUserDefaults standardUserDefaults] stringForKey:@"deviceName"]; 0065 if (deviceName == nil) { 0066 deviceName=[UIDevice currentDevice].name; 0067 } 0068 [np setObject:deviceName forKey:@"deviceName"]; 0069 [np setInteger:ProtocolVersion forKey:@"protocolVersion"]; 0070 [np setObject:[Device DeviceType2Str:Device.currentDeviceType] forKey:@"deviceType"]; 0071 [np setInteger:tcpPort forKey:@"tcpPort"]; 0072 0073 // TODO: Instead of @[] actually import what plugins are available, UserDefaults to store maybe? 0074 // For now, manually putting everything in to trick the other device to sending the iOS host the 0075 // identity packets so debugging is easier 0076 [np setObject:@[NetworkPackageTypePing, 0077 NetworkPackageTypeShare, 0078 NetworkPackageTypeShareRequestUpdate, 0079 NetworkPackageTypeFindMyPhoneRequest, 0080 NetworkPackageTypeBatteryRequest, 0081 NetworkPackageTypeBattery, 0082 NetworkPackageTypeClipboard, 0083 NetworkPackageTypeClipboardConnect, 0084 NetworkPackageTypeRunCommand 0085 ] forKey:@"incomingCapabilities"]; 0086 [np setObject:@[NetworkPackageTypePing, 0087 NetworkPackageTypeShare, 0088 NetworkPackageTypeShareRequestUpdate, 0089 NetworkPackageTypeFindMyPhoneRequest, 0090 NetworkPackageTypeBatteryRequest, 0091 NetworkPackageTypeBattery, 0092 NetworkPackageTypeClipboard, 0093 NetworkPackageTypeClipboardConnect, 0094 NetworkPackageTypeMousePadRequest, 0095 NetworkPackageTypePresenter, 0096 NetworkPackageTypeRunCommandRequest 0097 ] forKey:@"outgoingCapabilities"]; 0098 0099 if ([[SelfDeviceData shared] isDebuggingNetworkPackage]) { 0100 [np setObject:[NetworkPackage allPackageTypes] forKey:@"incomingCapabilities"]; 0101 [np setObject:[NetworkPackage allPackageTypes] forKey:@"outgoingCapabilities"]; 0102 } 0103 0104 // FIXME: Remove object 0105 // [np setObject:[[PluginFactory sharedInstance] getSupportedIncomingInterfaces] forKey:@"SupportedIncomingInterfaces"]; 0106 // [np setObject:[[PluginFactory sharedInstance] getSupportedOutgoingInterfaces] forKey:@"SupportedOutgoingInterfaces"]; 0107 // 0108 return np; 0109 } 0110 0111 //Never touch these! 0112 + (NSString*) getUUID 0113 { 0114 if (!_UUID) { 0115 NSString* group = @"5433B4KXM8.org.kde.kdeconnect"; 0116 KeychainItemWrapper* wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"org.kde.kdeconnect-ios" accessGroup:group]; 0117 _UUID = [wrapper objectForKey:(__bridge id)(kSecValueData)]; 0118 if (!_UUID || [_UUID length] < 1) { 0119 // FIXME: identifierForVendor might be nil 0120 // Documentation reads: 0121 // If the value is nil, wait and get the value again later. 0122 // This happens, for example, after the device has been restarted 0123 // but before the user has unlocked the device. 0124 _UUID = [[[UIDevice currentDevice] identifierForVendor] UUIDString]; 0125 _UUID = [_UUID stringByReplacingOccurrencesOfString:@"-" withString:@""]; 0126 _UUID = [_UUID stringByReplacingOccurrencesOfString:@"_" withString:@""]; 0127 [wrapper setObject:_UUID forKey:(__bridge id)(kSecValueData)]; 0128 } 0129 } 0130 os_log_t logger = os_log_create([NSString kdeConnectOSLogSubsystem].UTF8String, 0131 NSStringFromClass([self class]).UTF8String); 0132 os_log_type_t debugLogLevel; 0133 if ([[SelfDeviceData shared] isDebuggingNetworkPackage]) { 0134 debugLogLevel = OS_LOG_TYPE_INFO; 0135 } else { 0136 debugLogLevel = OS_LOG_TYPE_DEBUG; 0137 } 0138 os_log_with_type(logger, debugLogLevel, "Get UUID %{mask.hash}@", _UUID); 0139 return _UUID; 0140 } 0141 0142 + (NetworkPackage*) createPairPackage 0143 { 0144 NetworkPackage* np=[[NetworkPackage alloc] initWithType:NetworkPackageTypePair]; 0145 [np setBool:YES forKey:@"pair"]; 0146 0147 return np; 0148 } 0149 0150 // 0151 - (BOOL) bodyHasKey:(NSString*)key 0152 { 0153 // FIXME: this implementation is most likely inaccurate; 0154 // might have bug when key starts with "@" because for valueForKey: 0155 // If key does not start with “@”, invokes `objectForKey:`. 0156 // If key does start with “@”, strips the “@” and 0157 // invokes [super valueForKey:] with the rest of the key. 0158 if ([self._Body valueForKey:key]!=nil) { 0159 return true; 0160 } 0161 return false; 0162 }; 0163 0164 - (void)setBool:(BOOL)value forKey:(NSString*)key { 0165 [self setObject:[NSNumber numberWithBool:value] forKey:key]; 0166 } 0167 0168 - (void)setFloat:(float)value forKey:(NSString*)key { 0169 [self setObject:[NSNumber numberWithFloat:value] forKey:key]; 0170 } 0171 0172 - (void)setInteger:(NSInteger)value forKey:(NSString*)key { 0173 [self setObject:[NSNumber numberWithInteger:value] forKey:key]; 0174 } 0175 0176 - (void)setDouble:(double)value forKey:(NSString*)key { 0177 [self setObject:[NSNumber numberWithDouble:value] forKey:key]; 0178 } 0179 0180 - (void)setObject:(id)value forKey:(NSString *)key{ 0181 [_Body setObject:value forKey:key]; 0182 } 0183 0184 - (BOOL)boolForKey:(NSString*)key { 0185 return [[self objectForKey:key] boolValue]; 0186 } 0187 0188 - (float)floatForKey:(NSString*)key { 0189 return [[self objectForKey:key] floatValue]; 0190 } 0191 - (NSInteger)integerForKey:(NSString*)key { 0192 return [[self objectForKey:key] integerValue]; 0193 } 0194 0195 - (double)doubleForKey:(NSString*)key { 0196 return [[self objectForKey:key] doubleValue]; 0197 } 0198 0199 - (id)objectForKey:(NSString *)key{ 0200 return [_Body objectForKey:key]; 0201 } 0202 0203 #pragma mark Serialize 0204 - (NSData*) serialize 0205 { 0206 NSArray* keys=[NSArray arrayWithObjects:@"id",@"type",@"body", nil]; 0207 NSArray* values=[NSArray arrayWithObjects:[self _Id],self.type,[self _Body], nil]; 0208 NSMutableDictionary* info=[NSMutableDictionary dictionaryWithObjects:values forKeys:keys]; 0209 if (_payloadPath) { 0210 // TODO: is checking _PayloadSize == 0 then changing it to -1 necessary? 0211 // what about empty files e.g. `.gitkeep`? 0212 [info setObject:[NSNumber numberWithLong:(_PayloadSize?_PayloadSize:-1)] forKey:@"payloadSize"]; 0213 [info setObject:_payloadTransferInfo forKey:@"payloadTransferInfo"]; 0214 } 0215 NSError* err=nil; 0216 NSMutableData* jsonData=[[NSMutableData alloc] initWithData:[NSJSONSerialization dataWithJSONObject:info options:0 error:&err]]; 0217 if (err) { 0218 os_log_t logger = os_log_create([NSString kdeConnectOSLogSubsystem].UTF8String, 0219 NSStringFromClass([self class]).UTF8String); 0220 os_log_with_type(logger, OS_LOG_TYPE_FAULT, "NP serialize error"); 0221 return nil; 0222 } 0223 [jsonData appendData:LFDATA]; 0224 return jsonData; 0225 } 0226 0227 + (NetworkPackage*) unserialize:(NSData*)data 0228 { 0229 NetworkPackage* np=[[NetworkPackage alloc] init]; 0230 NSError* err=nil; 0231 NSDictionary* info=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&err]; 0232 0233 // FIXME: add missing null check 0234 [np set_Id:[info valueForKey:@"id"]]; 0235 np.type = [info valueForKey:@"type"]; 0236 [np set_Body:[info valueForKey:@"body"]]; 0237 [np set_PayloadSize:[[info valueForKey:@"payloadSize"]longValue]]; 0238 [np setPayloadTransferInfo:[info valueForKey:@"payloadTransferInfo"]]; 0239 0240 // NSLog(@"Parsed id: %@, type: %@", [info valueForKey:@"id"], [info valueForKey:@"type"]); 0241 0242 //TO-DO should change for laptop 0243 if ([np _PayloadSize]==-1) { 0244 NSInteger temp; 0245 long size=(temp=[np integerForKey:@"size"])?temp:-1; 0246 [np set_PayloadSize:size]; 0247 } 0248 [np setPayloadTransferInfo:[info valueForKey:@"payloadTransferInfo"]]; 0249 0250 // FIXME: error check too late 0251 if (err) { 0252 return nil; 0253 } 0254 return np; 0255 } 0256 0257 @end 0258 0259 #pragma mark - Package Types 0260 0261 NetworkPackageType const NetworkPackageTypeIdentity = @"kdeconnect.identity"; 0262 NetworkPackageType const NetworkPackageTypeEncrypted = @"kdeconnect.encrypted"; 0263 NetworkPackageType const NetworkPackageTypePair = @"kdeconnect.pair"; 0264 NetworkPackageType const NetworkPackageTypePing = @"kdeconnect.ping"; 0265 0266 NetworkPackageType const NetworkPackageTypeMPRIS = @"kdeconnect.mpris"; 0267 0268 NetworkPackageType const NetworkPackageTypeShare = @"kdeconnect.share.request"; 0269 NetworkPackageType const NetworkPackageTypeShareRequestUpdate = @"kdeconnect.share.request.update"; 0270 NetworkPackageType const NetworkPackageTypeShareInternal = @"kdeconnect.share"; 0271 0272 NetworkPackageType const NetworkPackageTypeClipboard = @"kdeconnect.clipboard"; 0273 NetworkPackageType const NetworkPackageTypeClipboardConnect = @"kdeconnect.clipboard.connect"; 0274 0275 NetworkPackageType const NetworkPackageTypeBattery = @"kdeconnect.battery"; 0276 NetworkPackageType const NetworkPackageTypeCalendar = @"kdeconnect.calendar"; 0277 // NetworkPackageType const NetworkPackageTypeReminder = @"kdeconnect.reminder"; 0278 NetworkPackageType const NetworkPackageTypeContact = @"kdeconnect.contact"; 0279 0280 NetworkPackageType const NetworkPackageTypeBatteryRequest = @"kdeconnect.battery.request"; 0281 NetworkPackageType const NetworkPackageTypeFindMyPhoneRequest = @"kdeconnect.findmyphone.request"; 0282 0283 NetworkPackageType const NetworkPackageTypeMousePadRequest = @"kdeconnect.mousepad.request"; 0284 NetworkPackageType const NetworkPackageTypeMousePadKeyboardState = @"kdeconnect.mousepad.keyboardstate"; 0285 NetworkPackageType const NetworkPackageTypeMousePadEcho = @"kdeconnect.mousepad.echo"; 0286 0287 NetworkPackageType const NetworkPackageTypePresenter = @"kdeconnect.presenter"; 0288 0289 NetworkPackageType const NetworkPackageTypeRunCommandRequest = @"kdeconnect.runcommand.request"; 0290 NetworkPackageType const NetworkPackageTypeRunCommand = @"kdeconnect.runcommand";