mirror of
https://github.com/seemoo-lab/openhaystack.git
synced 2026-03-02 17:20:20 +00:00
Export the created firmware file (instead of flashing directly)
Running swift-format
This commit is contained in:
@@ -51,6 +51,7 @@
|
||||
78EC226C25DBC2E40042B775 /* OpenHaystackMainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78EC226B25DBC2E40042B775 /* OpenHaystackMainView.swift */; };
|
||||
78EC227225DBC8CE0042B775 /* Accessory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78EC227125DBC8CE0042B775 /* Accessory.swift */; };
|
||||
78EC227725DBDB7E0042B775 /* KeychainController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78EC227625DBDB7E0042B775 /* KeychainController.swift */; };
|
||||
78F8BB4C261C50EB00D9F37F /* LargeButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78F8BB4B261C50EB00D9F37F /* LargeButtonStyle.swift */; };
|
||||
F126102F2600D1D80066A859 /* Slider+LogScale.swift in Sources */ = {isa = PBXBuildFile; fileRef = F126102E2600D1D80066A859 /* Slider+LogScale.swift */; };
|
||||
F12D5A5A25FA4F3500CBBA09 /* BluetoothAccessoryScanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = F12D5A5925FA4F3500CBBA09 /* BluetoothAccessoryScanner.swift */; };
|
||||
F12D5A6025FA79FA00CBBA09 /* Advertisement.swift in Sources */ = {isa = PBXBuildFile; fileRef = F12D5A5F25FA79FA00CBBA09 /* Advertisement.swift */; };
|
||||
@@ -155,6 +156,7 @@
|
||||
78EC226B25DBC2E40042B775 /* OpenHaystackMainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenHaystackMainView.swift; sourceTree = "<group>"; };
|
||||
78EC227125DBC8CE0042B775 /* Accessory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Accessory.swift; sourceTree = "<group>"; };
|
||||
78EC227625DBDB7E0042B775 /* KeychainController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainController.swift; sourceTree = "<group>"; };
|
||||
78F8BB4B261C50EB00D9F37F /* LargeButtonStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LargeButtonStyle.swift; sourceTree = "<group>"; };
|
||||
F126102E2600D1D80066A859 /* Slider+LogScale.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Slider+LogScale.swift"; sourceTree = "<group>"; };
|
||||
F12D5A5925FA4F3500CBBA09 /* BluetoothAccessoryScanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BluetoothAccessoryScanner.swift; sourceTree = "<group>"; };
|
||||
F12D5A5F25FA79FA00CBBA09 /* Advertisement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Advertisement.swift; sourceTree = "<group>"; };
|
||||
@@ -360,6 +362,7 @@
|
||||
78EC227025DBC8BB0042B775 /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
78F8BB4A261C50D500D9F37F /* Styles */,
|
||||
78286D7625E5114600F65511 /* ActivityIndicator.swift */,
|
||||
78EC226B25DBC2E40042B775 /* OpenHaystackMainView.swift */,
|
||||
78486BEE25DD711E0007ED87 /* PopUpAlertView.swift */,
|
||||
@@ -374,6 +377,14 @@
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
78F8BB4A261C50D500D9F37F /* Styles */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
78F8BB4B261C50EB00D9F37F /* LargeButtonStyle.swift */,
|
||||
);
|
||||
path = Styles;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F12D5A5E25FA79D600CBBA09 /* Bluetooth */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -541,7 +552,7 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "if command -v swift-format >/dev/null; then\n swift-format lint -r \"$SRCROOT\"\nelse\n echo \"warning: swift-format not installed, download from https://github.com/apple/swift-format\"\nfi\n";
|
||||
shellScript = "if command -v swift-format >/dev/null; then\n swift-format format -i -r \"$SRCROOT\"; swift-format lint -r \"$SRCROOT\"\nelse\n echo \"warning: swift-format not installed, download from https://github.com/apple/swift-format\"\nfi\n";
|
||||
};
|
||||
F14B2C7E25EFBB11002DC056 /* Set Version Number from Git */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
@@ -615,6 +626,7 @@
|
||||
F12D5A6025FA79FA00CBBA09 /* Advertisement.swift in Sources */,
|
||||
781EB3F225DAD7EA00FEAA19 /* OpenHaystackApp.swift in Sources */,
|
||||
781EB3F325DAD7EA00FEAA19 /* Models.swift in Sources */,
|
||||
78F8BB4C261C50EB00D9F37F /* LargeButtonStyle.swift in Sources */,
|
||||
781EB3F425DAD7EA00FEAA19 /* FindMyController.swift in Sources */,
|
||||
781EB3F525DAD7EA00FEAA19 /* BoringSSL.m in Sources */,
|
||||
F12D5A5A25FA4F3500CBBA09 /* BluetoothAccessoryScanner.swift in Sources */,
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "gray-gamma-22",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"white" : "0.866"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "gray-gamma-22",
|
||||
"components" : {
|
||||
"alpha" : "0.758",
|
||||
"white" : "0.310"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "gray-gamma-22",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"white" : "0.657"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "gray-gamma-22",
|
||||
"components" : {
|
||||
"alpha" : "0.758",
|
||||
"white" : "0.237"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -157,6 +157,7 @@ class AccessoryController: ObservableObject {
|
||||
//MARK: Location reports
|
||||
|
||||
/// Download the location reports from.
|
||||
///
|
||||
/// - Parameter completion: called when the reports have been succesfully downloaded or the request has failed
|
||||
func downloadLocationReports(completion: @escaping (Result<Void, OpenHaystackMainView.AlertType>) -> Void) {
|
||||
AnisetteDataManager.shared.requestAnisetteData { result in
|
||||
|
||||
@@ -74,10 +74,8 @@ struct MicrobitController {
|
||||
return patchedFirmware
|
||||
}
|
||||
|
||||
static func deploy(accessory: Accessory) throws {
|
||||
let microbits = try MicrobitController.findMicrobits()
|
||||
guard let microBitURL = microbits.first,
|
||||
let firmwareURL = Bundle.main.url(forResource: "firmware", withExtension: "bin")
|
||||
static func patchFirmware(for accessory: Accessory) throws -> Data {
|
||||
guard let firmwareURL = Bundle.main.url(forResource: "firmware", withExtension: "bin")
|
||||
else {
|
||||
throw FirmwareFlashError.notFound
|
||||
}
|
||||
@@ -87,6 +85,18 @@ struct MicrobitController {
|
||||
let publicKey = try accessory.getAdvertisementKey()
|
||||
let patchedFirmware = try MicrobitController.patchFirmware(firmware, pattern: pattern, with: publicKey)
|
||||
|
||||
return patchedFirmware
|
||||
}
|
||||
|
||||
static func deploy(accessory: Accessory) throws {
|
||||
let microbits = try MicrobitController.findMicrobits()
|
||||
guard let microBitURL = microbits.first
|
||||
else {
|
||||
throw FirmwareFlashError.notFound
|
||||
}
|
||||
|
||||
let patchedFirmware = try self.patchFirmware(for: accessory)
|
||||
|
||||
try MicrobitController.deployToMicrobit(microBitURL, firmwareFile: patchedFirmware)
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import os
|
||||
|
||||
struct ManageAccessoriesView: View {
|
||||
|
||||
@@ -21,6 +22,7 @@ struct ManageAccessoriesView: View {
|
||||
@Binding var focusedAccessory: Accessory?
|
||||
@Binding var accessoryToDeploy: Accessory?
|
||||
@Binding var showESP32DeploySheet: Bool
|
||||
@State var sheetShown: SheetType?
|
||||
|
||||
@State var showMailPopup = false
|
||||
|
||||
@@ -42,11 +44,14 @@ struct ManageAccessoriesView: View {
|
||||
.toolbar(content: {
|
||||
self.toolbarView
|
||||
})
|
||||
.sheet(
|
||||
isPresented: self.$showESP32DeploySheet,
|
||||
content: {
|
||||
.sheet(item: self.$sheetShown) { sheetType in
|
||||
switch sheetType {
|
||||
case .esp32Install:
|
||||
ESP32InstallSheet(accessory: self.$accessoryToDeploy, alertType: self.$alertType)
|
||||
})
|
||||
case .deployFirmware:
|
||||
self.selectTargetView
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Accessory List view.
|
||||
@@ -103,6 +108,57 @@ struct ManageAccessoriesView: View {
|
||||
}
|
||||
}
|
||||
|
||||
var selectTargetView: some View {
|
||||
VStack {
|
||||
Text("Select target")
|
||||
.font(.title)
|
||||
Text("Please select to which device you want to deply")
|
||||
.padding(.bottom, 4)
|
||||
|
||||
VStack {
|
||||
Button(
|
||||
"Micro:bit",
|
||||
action: {
|
||||
self.sheetShown = nil
|
||||
if let accessory = self.accessoryToDeploy {
|
||||
self.deployAccessoryToMicrobit(accessory: accessory)
|
||||
}
|
||||
}
|
||||
)
|
||||
.buttonStyle(LargeButtonStyle())
|
||||
|
||||
Button(
|
||||
"Export Microbit firmware",
|
||||
action: {
|
||||
self.sheetShown = nil
|
||||
if let accessory = self.accessoryToDeploy {
|
||||
self.exportMicrobitFirmware(for: accessory)
|
||||
}
|
||||
}
|
||||
)
|
||||
.buttonStyle(LargeButtonStyle())
|
||||
|
||||
Button(
|
||||
"ESP32",
|
||||
action: {
|
||||
self.sheetShown = .esp32Install
|
||||
}
|
||||
)
|
||||
.buttonStyle(LargeButtonStyle())
|
||||
|
||||
Button(
|
||||
"Cancel",
|
||||
action: {
|
||||
self.sheetShown = nil
|
||||
}
|
||||
)
|
||||
.buttonStyle(LargeButtonStyle(destructive: true))
|
||||
}
|
||||
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
|
||||
/// Delete an accessory from the list of accessories.
|
||||
func delete(accessory: Accessory) {
|
||||
do {
|
||||
@@ -114,7 +170,7 @@ struct ManageAccessoriesView: View {
|
||||
|
||||
func deploy(accessory: Accessory) {
|
||||
self.accessoryToDeploy = accessory
|
||||
self.alertType = .selectDepoyTarget
|
||||
self.sheetShown = .deployFirmware
|
||||
}
|
||||
|
||||
/// Add an accessory with the provided details.
|
||||
@@ -149,6 +205,58 @@ struct ManageAccessoriesView: View {
|
||||
}
|
||||
}
|
||||
|
||||
/// Deploy the public key of the accessory to a BBC microbit.
|
||||
func deployAccessoryToMicrobit(accessory: Accessory) {
|
||||
do {
|
||||
try MicrobitController.deploy(accessory: accessory)
|
||||
} catch {
|
||||
os_log("Error occurred %@", String(describing: error))
|
||||
self.alertType = .deployFailed
|
||||
return
|
||||
}
|
||||
|
||||
self.alertType = .deployedSuccessfully
|
||||
accessory.isDeployed = true
|
||||
self.accessoryToDeploy = nil
|
||||
}
|
||||
|
||||
func exportMicrobitFirmware(for accessory: Accessory) {
|
||||
do {
|
||||
let firmware = try MicrobitController.patchFirmware(for: accessory)
|
||||
|
||||
let savePanel = NSSavePanel()
|
||||
savePanel.allowedFileTypes = ["bin"]
|
||||
savePanel.canCreateDirectories = true
|
||||
savePanel.directoryURL = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
|
||||
savePanel.message = "Export the micro:bit firmware"
|
||||
savePanel.nameFieldLabel = "Firmware name"
|
||||
savePanel.nameFieldStringValue = "openhaystack_firmware.bin"
|
||||
savePanel.prompt = "Export"
|
||||
savePanel.title = "Export firmware"
|
||||
|
||||
let result = savePanel.runModal()
|
||||
|
||||
if result == .OK,
|
||||
let url = savePanel.url
|
||||
{
|
||||
// Store the accessory file
|
||||
try firmware.write(to: url)
|
||||
}
|
||||
|
||||
} catch {
|
||||
os_log("Error occurred %@", String(describing: error))
|
||||
self.alertType = .exportFailed
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
enum SheetType: Int, Identifiable {
|
||||
var id: Int {
|
||||
return self.rawValue
|
||||
}
|
||||
case esp32Install
|
||||
case deployFirmware
|
||||
}
|
||||
}
|
||||
|
||||
struct ManageAccessoriesView_Previews: PreviewProvider {
|
||||
|
||||
@@ -221,26 +221,6 @@ struct OpenHaystackMainView: View {
|
||||
.frame(width: 250, height: 120)
|
||||
}
|
||||
|
||||
func deploy(accessory: Accessory) {
|
||||
self.accessoryToDeploy = accessory
|
||||
self.alertType = .selectDepoyTarget
|
||||
}
|
||||
|
||||
/// Deploy the public key of the accessory to a BBC microbit.
|
||||
func deployAccessoryToMicrobit(accessory: Accessory) {
|
||||
do {
|
||||
try MicrobitController.deploy(accessory: accessory)
|
||||
} catch {
|
||||
os_log("Error occurred %@", String(describing: error))
|
||||
self.alertType = .deployFailed
|
||||
return
|
||||
}
|
||||
|
||||
self.alertType = .deployedSuccessfully
|
||||
accessory.isDeployed = true
|
||||
self.accessoryToDeploy = nil
|
||||
}
|
||||
|
||||
/// Ask to install and activate the mail plugin.
|
||||
func installMailPlugin() {
|
||||
let pluginManager = MailPluginManager()
|
||||
@@ -373,20 +353,6 @@ struct OpenHaystackMainView: View {
|
||||
action: {
|
||||
self.downloadPlugin()
|
||||
}), secondaryButton: .cancel())
|
||||
case .selectDepoyTarget:
|
||||
let microbitButton = Alert.Button.default(Text("Microbit"), action: { self.deployAccessoryToMicrobit(accessory: self.accessoryToDeploy!) })
|
||||
|
||||
let esp32Button = Alert.Button.default(
|
||||
Text("ESP32"),
|
||||
action: {
|
||||
self.showESP32DeploySheet = true
|
||||
})
|
||||
|
||||
return Alert(
|
||||
title: Text("Select target"),
|
||||
message: Text("Please select to which device you want to deploy"),
|
||||
primaryButton: microbitButton,
|
||||
secondaryButton: esp32Button)
|
||||
case .downloadingReportsFailed:
|
||||
return Alert(
|
||||
title: Text("Downloading locations failed"),
|
||||
@@ -419,7 +385,6 @@ struct OpenHaystackMainView: View {
|
||||
case downloadingReportsFailed
|
||||
case activatePlugin
|
||||
case pluginInstallFailed
|
||||
case selectDepoyTarget
|
||||
case exportFailed
|
||||
case importFailed
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// OpenHaystack – Tracking personal Bluetooth devices via Apple's Find My network
|
||||
//
|
||||
// Copyright © 2021 Secure Mobile Networking Lab (SEEMOO)
|
||||
// Copyright © 2021 The Open Wireless Link Project
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
struct LargeButtonStyle: ButtonStyle {
|
||||
|
||||
var active: Bool = false
|
||||
var destructive: Bool = false
|
||||
|
||||
func makeBody(configuration: Configuration) -> some View {
|
||||
ZStack {
|
||||
if configuration.isPressed {
|
||||
RoundedRectangle(cornerRadius: 5.0)
|
||||
.fill(Color.accentColor)
|
||||
} else {
|
||||
RoundedRectangle(cornerRadius: 5.0)
|
||||
.fill(self.active ? Color.accentColor : self.destructive ? Color.red : Color("Button"))
|
||||
}
|
||||
|
||||
configuration.label
|
||||
.font(Font.headline)
|
||||
.padding(6)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user