Skip to content

Commit

Permalink
Safe [Data -> Int32] conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
TechUnRestricted committed May 26, 2022
1 parent 6c93d68 commit 67c633b
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 43 deletions.
6 changes: 4 additions & 2 deletions PSDirectSender.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -455,12 +455,13 @@
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = PSDirectSender/Info.plist;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
INFOPLIST_KEY_NSHumanReadableCopyright = "";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 1.0;
MARKETING_VERSION = 1.1;
PRODUCT_BUNDLE_IDENTIFIER = com.techunrestricted.PSDirectSender;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
Expand All @@ -484,12 +485,13 @@
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = PSDirectSender/Info.plist;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
INFOPLIST_KEY_NSHumanReadableCopyright = "";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 1.0;
MARKETING_VERSION = 1.1;
PRODUCT_BUNDLE_IDENTIFIER = com.techunrestricted.PSDirectSender;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
Expand Down
48 changes: 27 additions & 21 deletions PSDirectSender/SFOExplorer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@
import Foundation

fileprivate extension Data {
var integerRepresentation: Int32 {
return self.withUnsafeBytes({(pointer: UnsafeRawBufferPointer) -> Int32 in
return pointer.load(as: Int32.self)
})
var integerRepresentation: Int32? {
if self.count < MemoryLayout<Int32>.size {
return nil
} else {
return self.withUnsafeBytes({(pointer: UnsafeRawBufferPointer) -> Int32 in
return pointer.load(as: Int32.self)
})
}
}

var stringRepresentation: String {
return String(decoding: self, as: UTF8.self)
}
Expand Down Expand Up @@ -74,22 +77,24 @@ class SFOExplorer {
}

private func getParamSFOOffset(fileHandler: FileHandle) -> UInt32? {
let filesCount = loadFileDataBlocks(from: 0x00C,
bytesCount: 4,
fileHandler: fileHandler)
.integerRepresentation
.bigEndian
guard let filesCount = loadFileDataBlocks(from: 0x00C,
bytesCount: 4,
fileHandler: fileHandler)
.integerRepresentation?
.bigEndian
else { return nil }

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

let tableOffset = loadFileDataBlocks(from: 0x018,
bytesCount: 4,
fileHandler: fileHandler)
.integerRepresentation
.bigEndian
guard let tableOffset = loadFileDataBlocks(from: 0x018,
bytesCount: 4,
fileHandler: fileHandler)
.integerRepresentation?
.bigEndian
else { return nil }

let tableData = loadFileDataBlocks(
from: UInt64(tableOffset),
Expand All @@ -101,6 +106,7 @@ class SFOExplorer {
for table in tableStruct where table.id == 1048576 {
return table.offset
}

return nil
}

Expand All @@ -116,11 +122,11 @@ class SFOExplorer {
/// MAGIC
/*
let magic: Int32 = loadFileDataBlocks(
from: 0,
bytesCount: 4,
fileHandler: fileHandler
).integerRepresentation
*/
from: 0,
bytesCount: 4,
fileHandler: fileHandler
).integerRepresentation
*/

/// PARAM.SFO
guard let offset32: UInt32 = getParamSFOOffset(fileHandler: fileHandler) else {
Expand Down Expand Up @@ -171,7 +177,7 @@ class SFOExplorer {
values.append(entryData.stringRepresentation.replacingOccurrences(of: "\0", with: ""))
case 1028:
/* Integer */
values.append(String(entryData.integerRepresentation))
values.append(String(entryData.integerRepresentation ?? -1))
default:
break
}
Expand Down
45 changes: 26 additions & 19 deletions PSDirectSender/Screens/QueueView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ struct QueueView: View {
@EnvironmentObject var logsCollector: LogsCollector

@State fileprivate var alert: AlertIdentifier?
@State var packageURLs: [Package] = []
@State var packages: [Package] = []
@State private var selection: Set<UUID> = []

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

List(selection: $selection) {
ForEach(packageURLs, id: \.id) { package in
ForEach(packages, id: \.id) { package in
HStack {
Image(systemName: "shippingbox")
Text("\(package.title_id ?? package.url.lastPathComponent)")
Expand All @@ -106,10 +106,17 @@ struct QueueView: View {
if let url = object, url.pathExtension == "pkg"{
let packageDetails = SFOExplorer().getParamSFOData(url: url)
var title: String?

if let packageDetails = packageDetails {
title = packageDetails["TITLE"]
if let title = title {
logsCollector.addLog("Package name defined: \"\(title)\" (\"\(url)\")")
} else {
logsCollector.addLog("Package name for (\"\(url)\") is undefined. Maybe the package is damaged or not compatible with the PS4 system.")
}
}
packageURLs.append(Package(url: url, title_id: title))

packages.append(Package(url: url, title_id: title))
}
}
}
Expand All @@ -123,7 +130,7 @@ struct QueueView: View {
Image(systemName: "shippingbox")
.resizable()
.frame(width: 100, height: 100)
Text(#"Drop ".pkg" files"#)
Text("Drop .pkg files")
.font(.title)
}
.opacity(0.5)
Expand Down Expand Up @@ -172,29 +179,29 @@ struct QueueView: View {
}

private func deleteSelection() {
packageURLs.removeAll { selection.contains($0.id) }
packages.removeAll { selection.contains($0.id) }
selection.removeAll()
}

fileprivate func AddButton() -> ColorButton {
return ColorButton(text: "Add", color: .orange, image: Image(systemName: "plus.rectangle.on.rectangle"), action: {
let packages = selectPackages()
for package in packages {
let selectedPackages = selectPackages()
for package in selectedPackages {
if let package = package {
let packageDetails = SFOExplorer().getParamSFOData(url: package)
var title: String?
if let packageDetails = packageDetails {
title = packageDetails["TITLE"]
}
packageURLs.append(Package(url: package, title_id: title))
packages.append(Package(url: package, title_id: title))
}
}
})
}

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

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

loadingScreenIsShown = true
DispatchQueue.global(qos: .background).async {
for index in packageURLs.indices {
if packageURLs[index].state == .sendSuccess {
for index in packages.indices {
if packages[index].state == .sendSuccess {
continue
}
let alias = createTempDirPackageAlias(package: packageURLs[index])!
let alias = createTempDirPackageAlias(package: packages[index])!

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

let response = sendPackagesToConsole(packageFilename: alias, connection: connection)
Expand All @@ -234,15 +241,15 @@ struct QueueView: View {
}
break
} else if let response = response as? SendSuccess {
logsCollector.addLog("Successfully sent \(packageURLs[index].url) [Package Link: \"\(packageURLs[index].id).pkg\", id: \(response.taskID), title: \"\(response.title)\"]")
logsCollector.addLog("Successfully sent \(packages[index].url) [Package Link: \"\(packages[index].id).pkg\", id: \(response.taskID), title: \"\(response.title)\"]")
DispatchQueue.main.async {
packageURLs[index].state = .sendSuccess
packageURLs[index].task_id = response.taskID
packages[index].state = .sendSuccess
packages[index].task_id = response.taskID
}
} else if let response = response as? SendFailure {
logsCollector.addLog("An error occurred while sending \(packageURLs[index].url) [\(packageURLs[index].id).pkg] {ERROR: \(response.error)}")
logsCollector.addLog("An error occurred while sending \(packages[index].url) [\(packages[index].id).pkg] {ERROR: \(response.error)}")
DispatchQueue.main.async {
packageURLs[index].state = .sendFailure
packages[index].state = .sendFailure
}
break
}
Expand All @@ -267,7 +274,7 @@ struct QueueView_Previews: PreviewProvider {
@EnvironmentObject var connection: ConnectionDetails

static var previews: some View {
let view = QueueView(packageURLs: [
let view = QueueView(packages: [
Package(url: URL(string: "https://example.com/game.pkg")!),
Package(url: URL(string: "https://example.com/dlc.pkg")!, state: .sendSuccess),
Package(url: URL(string: "https://example.com/dlc.pkg")!, state: .sendFailure)
Expand Down
2 changes: 2 additions & 0 deletions PSDirectSender/ru.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,5 @@
"Stopped" = "Остановлен";

"Invalid configuration data" = "Неверные данные конфигурации";

"Drop .pkg files" = "Перетащите файлы .pkg";
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
## Current features
* Sending local .pkg files
* Drag'n'drop support
* Automatic .pkg title detection
* Creating aliases for files for correct sending .pkg containing spaces in the name.
* Advanced logging system
* Automatic appropriate data generation for the server (IP, Port)
* English / Russian language support

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

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

# Usage
## Usage
<ol>
<li>Open <b>PSDirectSender</b></li>
<li>Go to the Configuration section</li>
Expand Down

0 comments on commit 67c633b

Please sign in to comment.