Skip to content

Commit 67c633b

Browse files
Safe [Data -> Int32] conversion
1 parent 6c93d68 commit 67c633b

File tree

5 files changed

+62
-43
lines changed

5 files changed

+62
-43
lines changed

PSDirectSender.xcodeproj/project.pbxproj

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -455,12 +455,13 @@
455455
ENABLE_PREVIEWS = YES;
456456
GENERATE_INFOPLIST_FILE = YES;
457457
INFOPLIST_FILE = PSDirectSender/Info.plist;
458+
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
458459
INFOPLIST_KEY_NSHumanReadableCopyright = "";
459460
LD_RUNPATH_SEARCH_PATHS = (
460461
"$(inherited)",
461462
"@executable_path/../Frameworks",
462463
);
463-
MARKETING_VERSION = 1.0;
464+
MARKETING_VERSION = 1.1;
464465
PRODUCT_BUNDLE_IDENTIFIER = com.techunrestricted.PSDirectSender;
465466
PRODUCT_NAME = "$(TARGET_NAME)";
466467
SWIFT_EMIT_LOC_STRINGS = YES;
@@ -484,12 +485,13 @@
484485
ENABLE_PREVIEWS = YES;
485486
GENERATE_INFOPLIST_FILE = YES;
486487
INFOPLIST_FILE = PSDirectSender/Info.plist;
488+
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
487489
INFOPLIST_KEY_NSHumanReadableCopyright = "";
488490
LD_RUNPATH_SEARCH_PATHS = (
489491
"$(inherited)",
490492
"@executable_path/../Frameworks",
491493
);
492-
MARKETING_VERSION = 1.0;
494+
MARKETING_VERSION = 1.1;
493495
PRODUCT_BUNDLE_IDENTIFIER = com.techunrestricted.PSDirectSender;
494496
PRODUCT_NAME = "$(TARGET_NAME)";
495497
SWIFT_EMIT_LOC_STRINGS = YES;

PSDirectSender/SFOExplorer.swift

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,15 @@
88
import Foundation
99

1010
fileprivate extension Data {
11-
var integerRepresentation: Int32 {
12-
return self.withUnsafeBytes({(pointer: UnsafeRawBufferPointer) -> Int32 in
13-
return pointer.load(as: Int32.self)
14-
})
11+
var integerRepresentation: Int32? {
12+
if self.count < MemoryLayout<Int32>.size {
13+
return nil
14+
} else {
15+
return self.withUnsafeBytes({(pointer: UnsafeRawBufferPointer) -> Int32 in
16+
return pointer.load(as: Int32.self)
17+
})
18+
}
1519
}
16-
1720
var stringRepresentation: String {
1821
return String(decoding: self, as: UTF8.self)
1922
}
@@ -74,22 +77,24 @@ class SFOExplorer {
7477
}
7578

7679
private func getParamSFOOffset(fileHandler: FileHandle) -> UInt32? {
77-
let filesCount = loadFileDataBlocks(from: 0x00C,
78-
bytesCount: 4,
79-
fileHandler: fileHandler)
80-
.integerRepresentation
81-
.bigEndian
80+
guard let filesCount = loadFileDataBlocks(from: 0x00C,
81+
bytesCount: 4,
82+
fileHandler: fileHandler)
83+
.integerRepresentation?
84+
.bigEndian
85+
else { return nil }
8286

8387
if filesCount >= 256 {
8488
print("[ERROR:] Files count >= 256 (current: \(filesCount)). It's can't be real.")
8589
return nil
8690
}
8791

88-
let tableOffset = loadFileDataBlocks(from: 0x018,
89-
bytesCount: 4,
90-
fileHandler: fileHandler)
91-
.integerRepresentation
92-
.bigEndian
92+
guard let tableOffset = loadFileDataBlocks(from: 0x018,
93+
bytesCount: 4,
94+
fileHandler: fileHandler)
95+
.integerRepresentation?
96+
.bigEndian
97+
else { return nil }
9398

9499
let tableData = loadFileDataBlocks(
95100
from: UInt64(tableOffset),
@@ -101,6 +106,7 @@ class SFOExplorer {
101106
for table in tableStruct where table.id == 1048576 {
102107
return table.offset
103108
}
109+
104110
return nil
105111
}
106112

@@ -116,11 +122,11 @@ class SFOExplorer {
116122
/// MAGIC
117123
/*
118124
let magic: Int32 = loadFileDataBlocks(
119-
from: 0,
120-
bytesCount: 4,
121-
fileHandler: fileHandler
122-
).integerRepresentation
123-
*/
125+
from: 0,
126+
bytesCount: 4,
127+
fileHandler: fileHandler
128+
).integerRepresentation
129+
*/
124130

125131
/// PARAM.SFO
126132
guard let offset32: UInt32 = getParamSFOOffset(fileHandler: fileHandler) else {
@@ -171,7 +177,7 @@ class SFOExplorer {
171177
values.append(entryData.stringRepresentation.replacingOccurrences(of: "\0", with: ""))
172178
case 1028:
173179
/* Integer */
174-
values.append(String(entryData.integerRepresentation))
180+
values.append(String(entryData.integerRepresentation ?? -1))
175181
default:
176182
break
177183
}

PSDirectSender/Screens/QueueView.swift

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ struct QueueView: View {
6363
@EnvironmentObject var logsCollector: LogsCollector
6464

6565
@State fileprivate var alert: AlertIdentifier?
66-
@State var packageURLs: [Package] = []
66+
@State var packages: [Package] = []
6767
@State private var selection: Set<UUID> = []
6868

6969
@State var isInDropArea: Bool = false
@@ -83,7 +83,7 @@ struct QueueView: View {
8383
}.padding()
8484

8585
List(selection: $selection) {
86-
ForEach(packageURLs, id: \.id) { package in
86+
ForEach(packages, id: \.id) { package in
8787
HStack {
8888
Image(systemName: "shippingbox")
8989
Text("\(package.title_id ?? package.url.lastPathComponent)")
@@ -106,10 +106,17 @@ struct QueueView: View {
106106
if let url = object, url.pathExtension == "pkg"{
107107
let packageDetails = SFOExplorer().getParamSFOData(url: url)
108108
var title: String?
109+
109110
if let packageDetails = packageDetails {
110111
title = packageDetails["TITLE"]
112+
if let title = title {
113+
logsCollector.addLog("Package name defined: \"\(title)\" (\"\(url)\")")
114+
} else {
115+
logsCollector.addLog("Package name for (\"\(url)\") is undefined. Maybe the package is damaged or not compatible with the PS4 system.")
116+
}
111117
}
112-
packageURLs.append(Package(url: url, title_id: title))
118+
119+
packages.append(Package(url: url, title_id: title))
113120
}
114121
}
115122
}
@@ -123,7 +130,7 @@ struct QueueView: View {
123130
Image(systemName: "shippingbox")
124131
.resizable()
125132
.frame(width: 100, height: 100)
126-
Text(#"Drop ".pkg" files"#)
133+
Text("Drop .pkg files")
127134
.font(.title)
128135
}
129136
.opacity(0.5)
@@ -172,29 +179,29 @@ struct QueueView: View {
172179
}
173180

174181
private func deleteSelection() {
175-
packageURLs.removeAll { selection.contains($0.id) }
182+
packages.removeAll { selection.contains($0.id) }
176183
selection.removeAll()
177184
}
178185

179186
fileprivate func AddButton() -> ColorButton {
180187
return ColorButton(text: "Add", color: .orange, image: Image(systemName: "plus.rectangle.on.rectangle"), action: {
181-
let packages = selectPackages()
182-
for package in packages {
188+
let selectedPackages = selectPackages()
189+
for package in selectedPackages {
183190
if let package = package {
184191
let packageDetails = SFOExplorer().getParamSFOData(url: package)
185192
var title: String?
186193
if let packageDetails = packageDetails {
187194
title = packageDetails["TITLE"]
188195
}
189-
packageURLs.append(Package(url: package, title_id: title))
196+
packages.append(Package(url: package, title_id: title))
190197
}
191198
}
192199
})
193200
}
194201

195202
fileprivate func SendButton() -> ColorButton {
196203
return ColorButton(text: "Send", color: .green, image: Image(systemName: "arrow.up.forward.app"), action: {
197-
if packageURLs.isEmpty { return }
204+
if packages.isEmpty { return }
198205

199206
if connection.serverIP.isEmpty || connection.serverPort.isEmpty {
200207
connection.generateServerDetails()
@@ -214,13 +221,13 @@ struct QueueView: View {
214221

215222
loadingScreenIsShown = true
216223
DispatchQueue.global(qos: .background).async {
217-
for index in packageURLs.indices {
218-
if packageURLs[index].state == .sendSuccess {
224+
for index in packages.indices {
225+
if packages[index].state == .sendSuccess {
219226
continue
220227
}
221-
let alias = createTempDirPackageAlias(package: packageURLs[index])!
228+
let alias = createTempDirPackageAlias(package: packages[index])!
222229

223-
logsCollector.addLog("Creating package alias (\"\(packageURLs[index].url.path)\" -> \"\(tempDirectory.path)/\(alias)\").")
230+
logsCollector.addLog("Creating package alias (\"\(packages[index].url.path)\" -> \"\(tempDirectory.path)/\(alias)\").")
224231
logsCollector.addLog("Sending package \"\(alias)\" to the console (IP: \(connection.consoleIP), Port: \(connection.consolePort))")
225232

226233
let response = sendPackagesToConsole(packageFilename: alias, connection: connection)
@@ -234,15 +241,15 @@ struct QueueView: View {
234241
}
235242
break
236243
} else if let response = response as? SendSuccess {
237-
logsCollector.addLog("Successfully sent \(packageURLs[index].url) [Package Link: \"\(packageURLs[index].id).pkg\", id: \(response.taskID), title: \"\(response.title)\"]")
244+
logsCollector.addLog("Successfully sent \(packages[index].url) [Package Link: \"\(packages[index].id).pkg\", id: \(response.taskID), title: \"\(response.title)\"]")
238245
DispatchQueue.main.async {
239-
packageURLs[index].state = .sendSuccess
240-
packageURLs[index].task_id = response.taskID
246+
packages[index].state = .sendSuccess
247+
packages[index].task_id = response.taskID
241248
}
242249
} else if let response = response as? SendFailure {
243-
logsCollector.addLog("An error occurred while sending \(packageURLs[index].url) [\(packageURLs[index].id).pkg] {ERROR: \(response.error)}")
250+
logsCollector.addLog("An error occurred while sending \(packages[index].url) [\(packages[index].id).pkg] {ERROR: \(response.error)}")
244251
DispatchQueue.main.async {
245-
packageURLs[index].state = .sendFailure
252+
packages[index].state = .sendFailure
246253
}
247254
break
248255
}
@@ -267,7 +274,7 @@ struct QueueView_Previews: PreviewProvider {
267274
@EnvironmentObject var connection: ConnectionDetails
268275

269276
static var previews: some View {
270-
let view = QueueView(packageURLs: [
277+
let view = QueueView(packages: [
271278
Package(url: URL(string: "https://example.com/game.pkg")!),
272279
Package(url: URL(string: "https://example.com/dlc.pkg")!, state: .sendSuccess),
273280
Package(url: URL(string: "https://example.com/dlc.pkg")!, state: .sendFailure)

PSDirectSender/ru.lproj/Localizable.strings

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,3 +113,5 @@
113113
"Stopped" = "Остановлен";
114114

115115
"Invalid configuration data" = "Неверные данные конфигурации";
116+
117+
"Drop .pkg files" = "Перетащите файлы .pkg";

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
## Current features
66
* Sending local .pkg files
77
* Drag'n'drop support
8+
* Automatic .pkg title detection
89
* Creating aliases for files for correct sending .pkg containing spaces in the name.
910
* Advanced logging system
1011
* Automatic appropriate data generation for the server (IP, Port)
12+
* English / Russian language support
1113

1214
<img width="998" alt="image" src="https://user-images.githubusercontent.com/83237609/166961465-36cb0ac6-00b1-405e-b28a-da6b4b8b6b9e.png">
1315

@@ -27,7 +29,7 @@
2729
* Wired or wireless connection to the same network as PS4
2830
* Local PS4-compatible .pkg files
2931

30-
# Usage
32+
## Usage
3133
<ol>
3234
<li>Open <b>PSDirectSender</b></li>
3335
<li>Go to the Configuration section</li>

0 commit comments

Comments
 (0)