Support receiving links and properly reject unsupported attachments

closes #52, closes #73, closes #16, closes #3, closes #8
This commit is contained in:
Grishka
2023-09-26 04:58:09 +03:00
parent df43d58045
commit 61d2a49712
6 changed files with 77 additions and 32 deletions

View File

@@ -10,6 +10,7 @@ import Network
import CryptoKit
import CommonCrypto
import System
import AppKit
import SwiftECC
import BigInt
@@ -20,6 +21,8 @@ class InboundNearbyConnection: NearbyConnection{
public var delegate:InboundNearbyConnectionDelegate?
private var cipherCommitment:Data?
private var textPayloadID:Int64=0
enum State{
case initial, receivedConnectionRequest, sentUkeyServerInit, receivedUkeyClientFinish, sentConnectionResponse, sentPairedKeyResult, receivedPairedKeyResult, waitingForUserConsent, receivingFiles, disconnected
}
@@ -114,6 +117,17 @@ class InboundNearbyConnection: NearbyConnection{
}
}
override func processBytesPayload(payload: Data, id: Int64) throws -> Bool {
if id==textPayloadID{
if let urlStr=String(data: payload, encoding: .utf8), let url=URL(string: urlStr){
NSWorkspace.shared.open(url)
}
try sendDisconnectionAndDisconnect()
return true
}
return false
}
private func processConnectionRequestFrame(_ frame:Location_Nearby_Connections_OfflineFrame) throws{
guard frame.hasV1 && frame.v1.hasConnectionRequest && frame.v1.connectionRequest.hasEndpointInfo else { throw NearbyError.requiredFieldMissing }
guard case .connectionRequest = frame.v1.type else { throw NearbyError.protocolError("Unexpected frame type \(frame.v1.type)") }
@@ -259,31 +273,46 @@ class InboundNearbyConnection: NearbyConnection{
private func processIntroductionFrame(_ frame:Sharing_Nearby_Frame) throws{
guard frame.hasV1, frame.v1.hasIntroduction else { throw NearbyError.requiredFieldMissing }
currentState = .waitingForUserConsent
let downloadsDirectory=(try FileManager.default.url(for: .downloadsDirectory, in: .userDomainMask, appropriateFor: nil, create: true)).resolvingSymlinksInPath()
for file in frame.v1.introduction.fileMetadata{
var dest=downloadsDirectory.appendingPathComponent(file.name)
if FileManager.default.fileExists(atPath: dest.path){
var counter=1
var path:String
let ext=dest.pathExtension
let baseUrl=dest.deletingPathExtension()
repeat{
path="\(baseUrl.path) (\(counter))"
if !ext.isEmpty{
path+=".\(ext)"
}
counter+=1
}while FileManager.default.fileExists(atPath: path)
dest=URL(fileURLWithPath: path)
if frame.v1.introduction.fileMetadata.count>0 && frame.v1.introduction.textMetadata.isEmpty{
let downloadsDirectory=(try FileManager.default.url(for: .downloadsDirectory, in: .userDomainMask, appropriateFor: nil, create: true)).resolvingSymlinksInPath()
for file in frame.v1.introduction.fileMetadata{
var dest=downloadsDirectory.appendingPathComponent(file.name)
if FileManager.default.fileExists(atPath: dest.path){
var counter=1
var path:String
let ext=dest.pathExtension
let baseUrl=dest.deletingPathExtension()
repeat{
path="\(baseUrl.path) (\(counter))"
if !ext.isEmpty{
path+=".\(ext)"
}
counter+=1
}while FileManager.default.fileExists(atPath: path)
dest=URL(fileURLWithPath: path)
}
let info=InternalFileInfo(meta: FileMetadata(name: file.name, size: file.size, mimeType: file.mimeType),
payloadID: file.payloadID,
destinationURL: dest)
transferredFiles[file.payloadID]=info
}
let info=InternalFileInfo(meta: FileMetadata(name: file.name, size: file.size, mimeType: file.mimeType),
payloadID: file.payloadID,
destinationURL: dest)
transferredFiles[file.payloadID]=info
}
let metadata=TransferMetadata(files: transferredFiles.map({$0.value.meta}), id: id, pinCode: pinCode)
DispatchQueue.main.async {
self.delegate?.obtainUserConsent(for: metadata, from: self.remoteDeviceInfo!, connection: self)
let metadata=TransferMetadata(files: transferredFiles.map({$0.value.meta}), id: id, pinCode: pinCode)
DispatchQueue.main.async {
self.delegate?.obtainUserConsent(for: metadata, from: self.remoteDeviceInfo!, connection: self)
}
}else if frame.v1.introduction.textMetadata.count==1{
let meta=frame.v1.introduction.textMetadata[0]
if case .url=meta.type{
let metadata=TransferMetadata(files: [], id: id, pinCode: pinCode, textDescription: meta.textTitle)
textPayloadID=meta.payloadID
DispatchQueue.main.async {
self.delegate?.obtainUserConsent(for: metadata, from: self.remoteDeviceInfo!, connection: self)
}
}else{
rejectTransfer(with: .unsupportedAttachmentType)
}
}else{
rejectTransfer(with: .unsupportedAttachmentType)
}
}
@@ -325,11 +354,11 @@ class InboundNearbyConnection: NearbyConnection{
}
}
private func rejectTransfer(){
private func rejectTransfer(with reason:Sharing_Nearby_ConnectionResponseFrame.Status = .reject){
var frame=Sharing_Nearby_Frame()
frame.version = .v1
frame.v1.type = .response
frame.v1.connectionResponse.status = .reject
frame.v1.connectionResponse.status = reason
do{
try sendTransferSetupFrame(frame)
try sendDisconnectionAndDisconnect()