Swift 3 - FTP Upload - ios

I have added the Rebekka touch framework to my Swift 3 project in order to upload files via FTP.
I have used the swift 3 conversion tool in xCode and I'm left with just one error
Value of type 'NSMutableData' has no member 'count'
And here's where it occurs:
let bytes = self.inputData!.bytes.bindMemory(to: UInt8.self, capacity: self.inputData!.count)
Full Function:
override func streamEventEnd(_ aStream: Stream) -> (Bool, NSError?) {
var offset = 0
let bytes = self.inputData!.bytes.bindMemory(to: UInt8.self, capacity: self.inputData!.count)
let totalBytes = CFIndex(self.inputData!.length)
var parsedBytes = CFIndex(0)
let entity = UnsafeMutablePointer<Unmanaged<CFDictionary>?>.allocate(capacity: 1)
var resources = [ResourceItem]()
repeat {
parsedBytes = CFFTPCreateParsedResourceListing(nil, bytes.advancedBy(offset), totalBytes - offset, entity)
if parsedBytes > 0 {
let value = entity.pointee?.takeUnretainedValue()
if let fptResource = value {
resources.append(self.mapFTPResources(fptResource))
}
offset += parsedBytes
}
} while parsedBytes > 0
self.resources = resources
entity.deinitialize()
return (true, nil)
}
Does anybody know the swift 3 equivalent of self.inputData!.count ?

I am using Swift3.
I did the following changes in the source code of Rebekka framework, specifically, the file ResourceListOperation.swift. (Note: advanced(by:..), .length).
fileprivate var inputData: NSMutableData?
var resources: [ResourceItem]?
override func streamEventEnd(_ aStream: Stream) -> (Bool, NSError?) {
var offset = 0
let bytes = self.inputData!.bytes.bindMemory(to: UInt8.self, capacity: self.inputData!.length)
let totalBytes = CFIndex(self.inputData!.length)
var parsedBytes = CFIndex(0)
let entity = UnsafeMutablePointer<Unmanaged<CFDictionary>?>.allocate(capacity: 1)
var resources = [ResourceItem]()
repeat {
parsedBytes = CFFTPCreateParsedResourceListing(nil, bytes.advanced(by: offset), totalBytes - offset, entity)
if parsedBytes > 0 {
let value = entity.pointee?.takeUnretainedValue()
if let fptResource = value {
resources.append(self.mapFTPResources(fptResource))
}
offset += parsedBytes
}
} while parsedBytes > 0
self.resources = resources
entity.deinitialize()
return (true, nil)
}
Here is what I used in my application to list the directory after importing RebekkaTouch framework:
var configuration = SessionConfiguration()
configuration.host = "<ip-address:followed-by-port>"
configuration.username = "uname"
configuration.password = "password"
configuration.encoding = String.Encoding.utf8
self.session = Session(configuration: configuration)
self.session.list("/") {
(resources, error) -> Void in
print("List directory with result:\n\(String(describing: resources)), error: \(String(describing: error))\n\n")
}

As suggested in the comments I used .length to get this working, along with some other slight changes as below:
override func streamEventEnd(_ aStream: Stream) -> (Bool, NSError?) {
var offset = 0
let bytes = self.inputData!.bytes.bindMemory(to: UInt8.self, capacity: self.inputData!.count)
let totalBytes = CFIndex(self.inputData!.length)
var parsedBytes = CFIndex(0)
let entity = UnsafeMutablePointer<Unmanaged<CFDictionary>?>.allocate(capacity: 1)
var resources = [ResourceItem]()
repeat {
parsedBytes = CFFTPCreateParsedResourceListing(nil, bytes.advancedBy(offset), totalBytes - offset, entity)
if parsedBytes > 0 {
let value = entity.pointee?.takeUnretainedValue()
if let fptResource = value {
resources.append(self.mapFTPResources(fptResource))
}
offset += parsedBytes
}
} while parsedBytes > 0
self.resources = resources
entity.deinitialize()
return (true, nil)
}
I then got some errors when tying to use Rebekka touch, the example usage didn't work so I modified slightly as below:
var configuration = SessionConfiguration()
configuration.host = "ftp.somewebsite.co.uk"
configuration.username = "username"
configuration.password = "password"
let URL = filename
let path = "/"+currentJob.ReservationsID+".png"
Session(configuration: configuration).upload(URL, path: path) {
(result, error) -> Void in
print("Upload file with result:\n\(result), error: \(error)\n\n")
}

Related

iOS - Check if mask ip is in valid(in range of the ip)

So i am trying to figure out how to validate the mask ip(in range?) according to the ip.
I cant seem to find the tools in swift as in java :
How can I detect if an IP is in a network?
let ip = "192.168.2.0"
let net = "192.168.1.0"
let pref = 24
func convertIpToInt(_ ipAddress: String) -> Int? {
var result = 0.0
let ipAddressArray = ipAddress.components(separatedBy: ".").compactMap {
Double($0) }
guard ipAddressArray.count == 4 else { return nil }
for (index, element) in ipAddressArray.enumerated() {
result += element * pow(256, Double(3 - index))
}
return Int(result) > 0 ? Int(result) : nil
}
let ipInt = convertIpToInt(ip)
let netInt = convertIpToInt(net)
let brkstInt = netInt! + Int(pow(2, Double(32-pref))) - 1
print(ipInt! >= netInt! && ipInt! <= brkstInt) // false

Getting EXC_BAD_ACCESS while the object exists

I'm developing a music sequencer with a standard piano roll type UI.
It was working well until I made some changes in the model side but it suddenly started to report EXC_BAD_ACCESS at (seemingly) unrelated part.
What's strange is all the necessary variables have their values properly and actually I can print values with po.
In my understanding, EXC_BAD_ACCESS happens when an object doesn't exist, so this seems quite strange.
My question is:
Is it common to EXC_BAD_ACCESS even the values are there?
If that's the case what is the possible situation to cause that?
Any suggestion is helpful. Thanks
[Below are the codes]
In my subclass of UICollectionViewLayout:
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
// note cells
let cv = self.collectionView as! YMPianoRollCollectionView;
let pianoRoll = cv.pianoRollViewController;
// Call the below func to get the indexes of the Note Objects included in the specified rect
let indexArray: Array<Int> = pianoRoll!.getNoteIndexes(inRect:rect, useOnlyStartTime: false);
var retArray : [UICollectionViewLayoutAttributes] = []
for i in indexArray {
if let _ = pianoRoll?.pattern.eventSequence[i] as? YMPatternEventNoteOn {
retArray.append( self.layoutAttributesForPatternEventInfo(i) )
}
}
return retArray
}
In my "piano roll" class which contains UICollectionView
func getNoteIndexes(inRect rect:CGRect, useOnlyStartTime: Bool) -> Array<Int> {
//
// Transform given values into musical values
//
let musicRange :YMMusicalValueRange = screenInfo.getMusicalRange(rect);
let startTime = musicRange.origin.time;
let endTime = musicRange.origin.time + musicRange.size.timeLength;
let lowNoteU = musicRange.origin.noteNumber;
let highNoteU = musicRange.origin.noteNumber + musicRange.size.numberOfNotes;
var retArray : [Int] = []
for i in 0..<pattern.eventSequence.count {
if let e = pattern.eventSequence[i] as? YMPatternEventNoteOn {
//
// Prepare ranges
//
let noteNo = e.noteNo; //<- App Crashes Here with BAD_ACCESS
let noteStTime = e.time;
let noteEnTime = e.time + e.duration;
let targetNoteRange = Range<Int>(uncheckedBounds: (lowNoteU, highNoteU));
let targetTimeRange = Range<Int64>(uncheckedBounds: (startTime, endTime))
let noteTimeRange = Range<Int64>(uncheckedBounds: (noteStTime, noteEnTime))
//
// Check the match
//
let noteMatches = targetNoteRange.contains(noteNo);
let timeMatches = useOnlyStartTime ? targetTimeRange.contains(noteStTime)
: targetTimeRange.overlaps(noteTimeRange)
if noteMatches && timeMatches {
retArray.append( i );
NSLog("XXX Found: note \(noteNo) at \(e.time)");
}
}
}
return retArray;
}
Error:- The object states when it crashed
EDIT
Here's the YMPatternEventNoteOn declaration
class YMPatternEvent : Codable, CustomDebugStringConvertible {
var time : YMSequenceTime = 0
// Some utility funcs follow
// ...
}
class YMPatternEventNoteOn : YMPatternEvent {
var noteNo : Int = 64
var velocity : Int = 127
var duration : YMSequenceTime = 480
var tempBendId : Int = 0;
var tempVibratoId : Int = 0;
var tempArpeggioId : Int = 0;
convenience init(time :YMSequenceTime, noteNo : Int, velocity: Int, duration: YMSequenceTime) {
self.init();
self.time = time;
self.noteNo = noteNo;
self.velocity = velocity;
self.duration = duration;
}
// Other methods follow
// ...
}
EDIT2
Note event is created by the user's action
//
// In YMPattern object
//
func insertNote(time:YMSequenceTime, noteNo:Int, velocity:Int, duration:YMSequenceTime) -> Int
{
let onEvent = YMPatternEventNoteOn(time: time, noteNo: noteNo, velocity: velocity, duration: duration);
let retIndex = insertEvent(onEvent);
return retIndex;
}
func insertEvent(_ event: YMPatternEvent) -> Int {
let atTime = event.time;
var retIndex : Int = 0;
if(eventSequence.count<1){
// If it's the first event just add it
eventSequence.append(event);
retIndex = 0;
} else {
// If any event already exists, insert with time order in consideration
var i : Int = 0;
while( atTime > eventSequence[i].time ){
i += 1;
if( i >= eventSequence.count ){
break;
}
}
retIndex = i;
eventSequence.insert(event, at: i)
}
}
//
// In pianoroll view controller
//
func actionButtonReleased(afterDragging: Bool) {
let values:YMMusicalValuePoint = screenInfo.getMusicalPosition(cursorPosition);
// insert new event with default velocity and duration
let _ = pattern.insertNote(time: values.time, noteNo: values.noteNumber, velocity: 127, duration: screenInfo.timeTicsPerDivision());
collectionView.reloadData();
}
I've solved it in a way.
By setting the optimization level to "Whole Module Optimization" it stopped reporting the error.
I don't know what is happening internally but if someone is having the same issue, this might work as a quick fix.

Get CPU usage IOS Swift

I am trying to get overall CPU usage not of a single app. I found some of the resources but they are either written in C or outdated swift. Can anyone help me with this problem? I am trying to conver this https://github.com/beltex/SystemKit/blob/master/SystemKit/System.swift#L12
to swift.
Till now I am able to convert this much
fileprivate func hostCPULoadInfo() -> host_cpu_load_info{
let HOST_CPU_LOAD_INFO_COUNT = MemoryLayout<host_cpu_load_info>.stride / MemoryLayout<integer_t>.stride;
var size = mach_msg_type_number_t(HOST_CPU_LOAD_INFO_COUNT);
var hostInfo = host_cpu_load_info_t.allocate(capacity: 1);
let result = withUnsafeMutablePointer(to: &hostInfo) {$0.withMemoryRebound(to: integer_t.self, capacity: Int(size)){
host_info(mach_host_self(), Int32(HOST_BASIC_INFO), $0, &size)
}
}
let data = hostInfo.move()
hostInfo.deallocate(capacity: 1)
#if DEBUG
if result != KERN_SUCCESS{
print("Error - \(#file): \(#function) - kern_result_t = \(result)");
}
#endif
return data;
}
public func cpuUsage() -> (system: Double, user: Double, idle : Double, nice: Double){
let load = hostCPULoadInfo();
let usrDiff: Double = Double(load.cpu_ticks.0 - loadPrevious.cpu_ticks.0);
let systDiff = Double(load.cpu_ticks.1 - loadPrevious.cpu_ticks.1);
let idleDiff = Double(load.cpu_ticks.2 - loadPrevious.cpu_ticks.2);
let niceDiff = Double(load.cpu_ticks.3 - loadPrevious.cpu_ticks.3);
let totalTicks = usrDiff + systDiff + idleDiff + niceDiff
print("Total ticks is ", totalTicks);
let sys = systDiff / totalTicks * 100.0
let usr = usrDiff / totalTicks * 100.0
let idle = idleDiff / totalTicks * 100.0
let nice = niceDiff / totalTicks * 100.0
return (sys, usr, idle, nice);
}
But the thing is I am getting an error like this
Error - /Users/administrator/Downloads/Documents/Swift/SystemInfo/RAMInformation.swift: hostCPULoadInfo() - kern_result_t = 5
Does anybody knows what's wrong in the above code? I thing I am doing wrong on conversion of host_statistics.
Can anybody help me?
There are three errors in your code:
The CPU statistics is obtained by calling host_statistics(), not
host_info().
The "flavor" argument must be HOST_CPU_LOAD_INFO, not HOST_BASIC_INFO.
hostInfo contains the pointer to the allocated structure,
so that value must be rebound, not the address of the variable.
Putting it all together:
func hostCPULoadInfo() -> host_cpu_load_info? {
let HOST_CPU_LOAD_INFO_COUNT = MemoryLayout<host_cpu_load_info>.stride / MemoryLayout<integer_t>.stride
var size = mach_msg_type_number_t(HOST_CPU_LOAD_INFO_COUNT)
let hostInfo = host_cpu_load_info_t.allocate(capacity: 1)
let result = hostInfo.withMemoryRebound(to: integer_t.self, capacity: HOST_CPU_LOAD_INFO_COUNT) {
host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, $0, &size)
}
if result != KERN_SUCCESS{
print("Error - \(#file): \(#function) - kern_result_t = \(result)")
return nil
}
let data = hostInfo.move()
hostInfo.deallocate(capacity: 1)
return data
}
(I changed the return type to an optional so that nil can be returned
in the error case).
Alternatively, use a local variable instead of allocating and releasing
the host_cpu_load_info structure:
func hostCPULoadInfo() -> host_cpu_load_info? {
let HOST_CPU_LOAD_INFO_COUNT = MemoryLayout<host_cpu_load_info>.stride/MemoryLayout<integer_t>.stride
var size = mach_msg_type_number_t(HOST_CPU_LOAD_INFO_COUNT)
var cpuLoadInfo = host_cpu_load_info()
let result = withUnsafeMutablePointer(to: &cpuLoadInfo) {
$0.withMemoryRebound(to: integer_t.self, capacity: HOST_CPU_LOAD_INFO_COUNT) {
host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, $0, &size)
}
}
if result != KERN_SUCCESS{
print("Error - \(#file): \(#function) - kern_result_t = \(result)")
return nil
}
return cpuLoadInfo
}

Write extend file attributes swift example

I am looking for a solution to add extended file attributes for a file in swift. I checked this link Write extended file attributes, but the solutions are in objective c and I need a solution for swift.
Here is a possible implementation in Swift 5 as an extension for URL,
with methods to get, set, list, and remove extended attributes of
a file. (Swift 2, 3, and 4 code can be found in the edit history.)
extension URL {
/// Get extended attribute.
func extendedAttribute(forName name: String) throws -> Data {
let data = try self.withUnsafeFileSystemRepresentation { fileSystemPath -> Data in
// Determine attribute size:
let length = getxattr(fileSystemPath, name, nil, 0, 0, 0)
guard length >= 0 else { throw URL.posixError(errno) }
// Create buffer with required size:
var data = Data(count: length)
// Retrieve attribute:
let result = data.withUnsafeMutableBytes { [count = data.count] in
getxattr(fileSystemPath, name, $0.baseAddress, count, 0, 0)
}
guard result >= 0 else { throw URL.posixError(errno) }
return data
}
return data
}
/// Set extended attribute.
func setExtendedAttribute(data: Data, forName name: String) throws {
try self.withUnsafeFileSystemRepresentation { fileSystemPath in
let result = data.withUnsafeBytes {
setxattr(fileSystemPath, name, $0.baseAddress, data.count, 0, 0)
}
guard result >= 0 else { throw URL.posixError(errno) }
}
}
/// Remove extended attribute.
func removeExtendedAttribute(forName name: String) throws {
try self.withUnsafeFileSystemRepresentation { fileSystemPath in
let result = removexattr(fileSystemPath, name, 0)
guard result >= 0 else { throw URL.posixError(errno) }
}
}
/// Get list of all extended attributes.
func listExtendedAttributes() throws -> [String] {
let list = try self.withUnsafeFileSystemRepresentation { fileSystemPath -> [String] in
let length = listxattr(fileSystemPath, nil, 0, 0)
guard length >= 0 else { throw URL.posixError(errno) }
// Create buffer with required size:
var namebuf = Array<CChar>(repeating: 0, count: length)
// Retrieve attribute list:
let result = listxattr(fileSystemPath, &namebuf, namebuf.count, 0)
guard result >= 0 else { throw URL.posixError(errno) }
// Extract attribute names:
let list = namebuf.split(separator: 0).compactMap {
$0.withUnsafeBufferPointer {
$0.withMemoryRebound(to: UInt8.self) {
String(bytes: $0, encoding: .utf8)
}
}
}
return list
}
return list
}
/// Helper function to create an NSError from a Unix errno.
private static func posixError(_ err: Int32) -> NSError {
return NSError(domain: NSPOSIXErrorDomain, code: Int(err),
userInfo: [NSLocalizedDescriptionKey: String(cString: strerror(err))])
}
}
Example usage:
let fileURL = URL(fileURLWithPath: "/path/to/file")
let attr1 = "com.myCompany.myAttribute"
let attr2 = "com.myCompany.otherAttribute"
let data1 = Data([1, 2, 3, 4])
let data2 = Data([5, 6, 7, 8, 9])
do {
// Set attributes:
try fileURL.setExtendedAttribute(data: data1, forName: attr1)
try fileURL.setExtendedAttribute(data: data2, forName: attr2)
// List attributes:
let list = try fileURL.listExtendedAttributes()
print(list)
// ["com.myCompany.myAttribute", "com.myCompany.otherAttribute", "other"]
let data1a = try fileURL.extendedAttribute(forName: attr1)
print(data1a as NSData)
// <01020304>
// Remove attributes
for attr in list {
try fileURL.removeExtendedAttribute(forName: attr)
}
} catch let error {
print(error.localizedDescription)
}

Epub Font Mangling is not working

I am creating an EPUB 3 reader for iOS using Swift 2.
The problem I'm currently facing is with font obfuscation / font mangling. I've read a tutorial that goes over how to do that in Swift, and integrated it into my project with some adaptations.
When I load an obfuscated epub into my app, the fonts are not loaded correctly and fall back to other system fonts. When I load an epub with the same fonts but not obfuscated, everything looks fine. Obviously, that means there's something wrong with my obfuscation code, but I can't for the life of me find the error.
Here's my code:
public struct Crypto {
public func obfuscateFontIDPF(data:NSData, key:String) -> NSData {
let source = data
var destination = [UInt8]()
let shaKey = key.sha1()
let keyData = shaKey.utf8Array
var arr = [UInt8](count: source.length, repeatedValue: 0)
source.getBytes(&arr, length:source.length)
var outer = 0
while outer < 52 && arr.isEmpty == false {
var inner = 0
while inner < 20 && arr.isEmpty == false {
let byte = arr.removeAtIndex(0) //Assumes read advances file position
let sourceByte = byte
let keyByte = keyData[inner]
let obfuscatedByte = sourceByte ^ keyByte
destination.append(obfuscatedByte)
inner++
}
outer++
}
if arr.isEmpty == false {
while arr.isEmpty == false {
let byte = arr.removeAtIndex(0)
destination.append(byte)
}
}
let newData = NSData(bytes: &destination, length: destination.count*sizeof(UInt8))
return newData
}
}
extension String {
func sha1() -> String {
var selfAsSha1 = ""
if let data = self.dataUsingEncoding(NSUTF8StringEncoding)
{
var digest = [UInt8](count: Int(CC_SHA1_DIGEST_LENGTH), repeatedValue: 0)
CC_SHA1(data.bytes, CC_LONG(data.length), &digest)
for index in 0..<CC_SHA1_DIGEST_LENGTH
{
selfAsSha1 += String(format: "%02x", digest[Int(index)])
}
}
return selfAsSha1
}
var utf8Array: [UInt8] {
return Array(utf8)
}
}
And here I call the obfuscation method:
func parserDidEndDocument(parser: NSXMLParser) {
if encryptedFilePaths!.count != 0 {
for file in encryptedFilePaths! {
let epubMainDirectoryPath = NSString(string: epubBook!.epubMainFolderPath!).stringByDeletingLastPathComponent
let fullFilePath = epubMainDirectoryPath.stringByAppendingString("/" + file)
let url = NSURL(fileURLWithPath: fullFilePath)
if let source = NSData(contentsOfURL: url) {
let decryptedFont = Crypto().obfuscateFontIDPF(source, key: self.epubBook!.encryptionKey!)
do {
try decryptedFont.writeToFile(fullFilePath, options: .DataWritingAtomic)
} catch {
print(error)
}
}
}
}
}
If you see where the error might be, please let me know.
I figured it out, here is the working code:
private func obfuscateData(data: NSData, key: String) -> NSData {
var destinationBytes = [UInt8]()
// Key needs to be SHA1 hash with length of exactly 20 chars
let hashedKeyBytes = generateHashedBytesFromString(key)
var sourceBytes = [UInt8](count: data.length, repeatedValue: 0)
data.getBytes(&sourceBytes, length: data.length)
var outerCount = 0
while outerCount < 52 && sourceBytes.isEmpty == false {
var innerCount = 0
while innerCount < 20 && sourceBytes.isEmpty == false {
let sourceByte = sourceBytes.removeAtIndex(0)
let keyByte = hashedKeyBytes[innerCount]
let obfuscatedByte = (sourceByte ^ keyByte)
destinationBytes.append(obfuscatedByte)
innerCount += 1
}
outerCount += 1
}
destinationBytes.appendContentsOf(sourceBytes)
let destinationData = NSData(bytes: &destinationBytes, length: destinationBytes.count*sizeof(UInt8))
sourceBytes.removeAll(keepCapacity: false)
destinationBytes.removeAll(keepCapacity: false)
return destinationData
}
/// Convert the key string to a SHA1 hashed Byte Array
private func generateHashedBytesFromString(string: String) -> [UInt8] {
var resultBytes = [UInt8]()
var hashedString = string.sha1()
for _ in 0.stride(to: hashedString.characters.count, by: 2) {
let character = "0x\(hashedString.returnTwoCharacters())"
resultBytes.append(UInt8(strtod(character, nil)))
}
return resultBytes
}
extension String {
func sha1() -> String {
var selfAsSha1 = ""
if let data = self.dataUsingEncoding(NSUTF8StringEncoding) {
var digest = [UInt8](count: Int(CC_SHA1_DIGEST_LENGTH), repeatedValue: 0)
CC_SHA1(data.bytes, CC_LONG(data.length), &digest)
for index in 0..<CC_SHA1_DIGEST_LENGTH {
selfAsSha1 += String(format: "%02x", digest[Int(index)])
}
}
return selfAsSha1
}
mutating func returnTwoCharacters() -> String {
var characters: String = ""
characters.append(self.removeAtIndex(startIndex))
characters.append(self.removeAtIndex(startIndex))
return characters
}
}

Resources