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";