9 recommended apps for macOS and iOS

2019-01-18

This is some apps from Bitfield that I share my office space with. Jörgen has some helpful tools and utilities I can highly recommend.

GIF’ted

Gifted

I use them for sharing moving screenshots with fellow programmers and customers. Crop and generate an optimized palette for making smaller gifs are great.

GIF’ted - Turn your movies into animated GIF’s

Playr

Playr

A video player that is unlike VLC easy to use. Since it’s based on FFMPEG, it opens almost everything.

Playr - Video playback simplified

Week

veckor

Why is not Americans using week numbers? It’s so convenient to refer to a week number instead of a range of dates.

Week - for macOS

Name Day

Namnsdagar

Friends and families always like to get a little congrats on their big day! They are much appreciated with a simple reminder.

Name days | Bitfield AB

PHPStorm

phpstorm

For PHP projects PHPStorm is the king of the hill. Everything is built in with being big bloat. PhpStorm: The Lightning-Smart IDE for PHP Programming by JetBrains

Affinity Designer and Affinity Photo

designer Great kit that works as an alternative to Adobe Photoshop and Illustrator. You can understand how to do macros! No monthly subscriptions and works great for my needs. Affinity - Professional creative software

Things

Things

My favorite todo-app. Read my review of todo apps

Things. Your to-do list for Mac & iOS


F-Bar version 2

2017-10-15

Version 2 of F-Bar is here. Make sure to check for updates. This is a free upgrade for every existing customer.

Support for Hyper

Finally, support for Hyper! Hyper lacks support for AppleScript, but it's possible to launch via accessibility controls. Answer yes, and let F-Bar take control. The next time it will launch Hyper!

Hyper

Push Notifications

Add a cURL request last in your deployment script and get a push notification when everything is done. Read more here.

Hyper

Configuration window

Added keyboard shortcuts for a faster workflow:

  • Cmd-S saves the content
  • Cmd-W closes the window
  • Cmd-R reloads the content, nice if you are looking into deployment logs

Hyper

Icon in dock

If you are running Spaces (multiple virtual desktops) it’s sometimes easy to loose where your dialog is hiding. With the dock icon enabled you can use TAB to select it again

Hyper

Updated to Swift 4.0

The project is completely updated to Swift 4.

Bugfixes

Removal of Forge Accounts works

Try F-Bar today


WordPress security myths

2017-07-24

Hide or move wp-admin to prevent brute force attacks

If you search on WordPress security, moving or hiding the wp-admin is one common tip, and there are many plugins that can do this for you. Bots and scanners are activity looking for WordPress-installations and attempting a brute password attack on /wp-admin

This is method is what's called "security by obscurity". Relying on this is not real security and cannot see as a good solution.

A big downside of this method is that many plugins depend on the exact location of /wp-admin. You are risking of breaking plugins.

Besides this, the most of the attacks are using vulnerabilities in XML-RPC, and hiding wp-admin are useless.

However, I highly recommend a password attempt plugin to prevent a brute-force attack.

Changing wp-prefix of all tables

Another common tip is to change the wp_ -prefix of the WordPress-tables. The theory is that this will make an SQL-injection harder. In reality, this does not matter; it is just a waste of time.

If an attacker can query against information_schema.tables, he or she will get all info about tables, whatever fancy prefix you put in front of the names, again "security by obscurity".

For the technical minded this is how a query could be executed.

SELECT DISTINCT SUBSTRING(`TABLE_NAME` FROM 1 FOR ( LENGTH(`TABLE_NAME`)-8 ) )
2
FROM information_schema.TABLES WHERE
3
`TABLE_NAME` LIKE '%postmeta';

My site is so small; no one cares hacking it

No site is too small to attack, in fact, smaller sites tend to have worse security. Hackers usually use tools for scanning the Internet for potential victims. If you leave your site unprotected it just matters in hours before it gets the first attack.

Why may you ask? There are a lot of use cases:

  • Sending spam
  • Improving SEO by linking to shady sites that sell drugs
  • Spreading malware to visitor
  • Installing scripts that can be used to a DDOS-attack. I have seen this behavior where attackers do nothing other than gaining access and waiting. One objective could be just waiting for to sell the information and use your site to create a DDOS-attack on other sites.

Conclusion

WordPress is a major platform today, 28% of the web is powered by WordPress. This does not mean that WordPress is less security, the popularity of makes the platform a big target.

There is nothing that beats keeping your WordPress-installation up to date and keeping an eye on this.

Keep your WordPress updated, use a good password. Follow my checklist, and you will be okay. :-)

Further reading

WordPress easy security list WordPress Security – 19+ Steps to Lock Down Your Site


Server side Swift for Laravel developers part 3

2017-07-21

Views

Next up we are going to add some views.

Unfortunately, Xcode does not render Leaf-templates correctly. You could manually set the type to HTML, but this will revert every time you build. Instead, I went back to good old Sublime for editing templates. First install Leaf - Packages - Package Control

Open Resources/Views/base.leaf and add Bootstrap 4 in the header. We cannot hurt our eyes with unsettled content :-)

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">

As you can see Leaf works very similar to Laravel and Blade.

Create Resources/Views/index.leaf and add a simple index-page

#extend("base")

#export("title") { Stations }

#export("content") {

    <table class="table">
    	<tr>
    		<th>ID</th>
    		<th>Name</th>
    		<th>Country</th>
    		<th>Stream</th>
    	</tr>
        #loop(stations, "station") {
            <tr>
            	<td><a href="/station/#(station.id)">#(station.id)</a></td>
            	<td>#(station.name)</td>
            	<td>#(station.country)</td>
                <td>#(station.stream)</td>
            </tr>
        }
    </table>

    <a href="/create" class="btn btn-default">Add a station</a>
}

Instead of section, Leaf is using export as markup.

Create Resources/Views/edit.leaf for creating records

#extend("base")

#export("title") { Stations }

#export("content") {

	<form class="form" action="/station/#(station.id)" method="post">
		<div class="form-group">
			<label for="name">Name</label>
			<input class="form-control" type="text" name="name" value="#(station.name)">
		</div>
		<div class="form-group">
			<label for="description">Description</label>
			<textarea class="form-control" name="description" id="description" cols="30" rows="10">#(station.description)</textarea>
		</div>
		<div class="form-group">
			<label for="country">Country</label>
			<input class="form-control" type="text" name="country" value="#(station.country)">
		</div>
		<div class="form-group">
			<label for="stream">Stream URL</label>
			<input class="form-control" type="text" name="stream" value="#(station.stream)">
		</div>

		<button type="submit" class="btn btn-primary">Save</button>
		<a href="/" class="btn btn-default">Back</a>
	</form>

}

Connect the dots

Like Laravel, you can create controllers and RESTful resources. But for this tutorial, we will just use the Routes.swift and doing all operations directly.

First make an index view, should not be any surprises if you are used to Laravel.

        builder.get { req in
            
            // Get all stations
            let stations = try Station.makeQuery().all()
            
            
            return try self.view.make("index", [
                "stations": stations
            ])
        }
    
        builder.get("station", ":id") { req in
            
            // Make sure the request contains an id
            guard let stationId = req.parameters["id"]?.int else {
                throw Abort.badRequest
            }

            let station = try Station.makeQuery().find(stationId)
            
            return try self.view.make("edit", [
                "station": station
            ])
        }
        
        builder.get("station", "create") { req in
            return try self.view.make("edit")
        }
        
        builder.post("station") { req in
            guard let form = req.formURLEncoded else {
                throw Abort.badRequest
            }
            
            let station = try Station(node: form)
            try station.save()
            
            return Response(redirect: "/")
        }

Finally, we are adding a route for updating an existing record. As mentioned earlier, Swift is strict and just refresh the model would require a lot of checks. By going via Vapor’s Node package and create a new model and assigning it back to the original record was the easiest way I found. If you have better solutions, feel free letting me know.

 builder.post("station", ":id") { req in
            
            // Make sure it's a form posted
            guard let form = req.formURLEncoded else {
                throw Abort.badRequest
            }
            
            // Make sure the request contains an id
            guard let stationId = req.parameters["id"]?.int else {
                throw Abort.badRequest
            }
            
            guard let station = try Station.makeQuery().find(stationId) else {
                throw Abort.notFound
            }
            
            // Use Vapor's node functions to create a new entity
            let newStation = try Station(node: form)
            
            // Assign the new values back to the old
            station.country = newStation.country
            station.name = newStation.name
            station.description = newStation.description
            
            // ...and save
            try station.save()
            
            return Response(redirect: "/")
        }

Debugging in Xcode

A very nice feature using Xcode is that you get all the debugging features that you would expect from an IDE.

Try putting a breakpoint on the route for getting a station, and you can inspect the results.

Step by step

Conclusions

Overall Vapor was a delightful surprise that it feels very Laravel-ish, I am sure the developers of Vapor have looked a lot a Laravel. For me using the same language for the backend and your apps will be a deal maker for many developers, especially if you are using Vapor as a RESTful backend. Vapor feels super snappy, and the performance is incredible, and the memory footprint is very low.

Swift in its nature of being strictly type hinted makes some operations like models to have a lot of boiler plate. This could be resolved by a code generator like GitHub - krzysztofzablocki/Sourcery: Meta-programming for Swift, stop writing boilerplate code. Unfortunately, there is no such tool creating Vapor models here yet.

All of your edits also demands that everything is re-compiled. Apple has made tremendous efforts to make this more speedy. Obviously, it’s not so easy as save your changes and hit reload in the browser.

Will I change? If I am about to build a JSON backend for an iOS-app, I will most likely look into Vapor. In some parts, I could even reuse the same code between the iOS-app and the backend. For me building a SAAS with a lot of party at the front end I would for sure stay with Laravel and maybe use Laravel Spark, because of the more mature tooling like components, seedings, Mix, Vue.js and so forth.

Download complete source



Server side Swift for Laravel developers part 2

2017-07-19

In this short example, we are going to build a simple CRUD-app of radio-stations that are used in my tvOS-app Radio Player.

If you have never programmed in Swift, there are some thing you need to know. Apple has designed Swift to be a static type-safe language with static dispatch. There cannot be any loose ends at compile time; everything must add up. Why is this? Apple’s motifs for this is performance, low memory usage, and stability; bugs should be caught at compilation and not in runtime. By defaulting to making structs and immutable variables is one way for example.

Swift 3 has all the bells and whistles you would expect from modern languages with influences from Rust, Haskell, Ruby, Python, C#. With Swift 2.0 Apple also introduced Protocol-Oriented Programming ) in replacement of Object Oriented programming. There are a lot of resources that can explain this better than I can.

The nature of the web is very stringy and combine this with Swift’s strict typing, and you have a bit of a problem. Vapor tries to resolve this with a package called Node to help and overcome this issue. Swift also misses multi line strings, which is planned to Swift 4. There are some quirks that you are not used to when doing PHP.

Some operation demands a lot more of boiler plate code than you are maybe used to. Swift features a very limited runtime and has no meta-programming features, which leads our projects to contain more boilerplate code. One solution to this could be the tool like Sourcery. Unfortunately there is no such tool yet. I think this is only beginning.

Create a model

Create a file in Model/Station.swift and create a class that extends Model like this

import Vapor
import MySQLProvider

final class Station: Model {
    
    // The storage property is there to allow Fluent to store extra information on your model--things like the model's database id.
    let storage = Storage()
    
    var id: Node?
    var name: String
    var description: String
    var country: String
    var stream: String
    
    // Just static variables holding the names to prevent typos
    static let nameKey = "name"
    static let descriptionKey = "description"
    static let countryKey = "country"
    static let streamKey = "stream"
    
    init(name: String, description: String, country: String, stream: String) {
        self.id = nil
        self.name = name
        self.description = description
        self.country = country
        self.stream = stream
    }
    
    // The Row struct represents a database row. Your models should be able to parse from and serialize to database rows. Here's the code for parsing the Stations from the database.
    init(row: Row) throws {
        id = try row.get(Station.idKey)
        name = try row.get(Station.nameKey)
        description = try row.get(Station.descriptionKey)
        country = try row.get(Station.countryKey)
        stream = try row.get(Station.streamKey)
    }
    
    // Init model from a Node-structure
    init(node: Node) throws {
        name = try node.get(Station.nameKey)
        description = try node.get(Station.descriptionKey)
        country = try node.get(Station.countryKey)
        stream = try node.get(Station.streamKey)

    }
    
    func makeRow() throws -> Row {
        var row = Row()
        try row.set(Station.nameKey, name)
        try row.set(Station.descriptionKey, description)
        try row.set(Station.countryKey, country)
        try row.set(Station.streamKey, stream)
        
        return row
    }
}

We need to show Vapor how to save it back into the database. We add a method called makeNode() with instructions. Just to make it more clear we create an extension that conforms to the NodePrespesentable protocol. Extensions can add new functionality to an existing class, structure, enumeration, or protocol type. Interfaces vs Inheritance in Swift

extension Station: NodeRepresentable {
    func makeNode(in context: Context?) throws -> Node {
        var node = Node(context)
        try node.set(Station.idKey, id?.int)
        try node.set(Station.nameKey, name)
        try node.set(Station.descriptionKey, description)
        try node.set(Station.countryKey, country)
        try node.set(Station.streamKey, stream)
        
        return node
    }
}

The cool thing is that protocols can be adopted by classes, structs, and enums. Base classes and inheritance are restricted to class types. You can decorate with default behaviors from multiple protocols. Unlike multiple inheritances of classes which some programming languages support, protocol extensions do not introduce any additional state.

Finally, we have to make a migration, called preparation in Vapor for the model.

extension Station: Preparation {
    static func prepare(_ database: Database) throws {
        try database.create(self) { builder in
            builder.id()
            builder.string(Station.nameKey)
            builder.string(Station.descriptionKey)
            builder.string(Station.countryKey)
            builder.string(Station.streamKey)
        }
    }
    
    static func revert(_ database: Database) throws {
        try database.delete(self)
    }
}

Next, we are going to add MySQL and Leaf-providers to the droplet, as you would do in Laravel

Source/App/Config+Setup.swift

import LeafProvider
import MySQLProvider

extension Config {
    public func setup() throws {
        // allow fuzzy conversions for these types
        // (add your own types here)
        Node.fuzzy = [JSON.self, Node.self]

        try setupProviders()
    }
    
    /// Configure providers
    private func setupProviders() throws {
        try addProvider(LeafProvider.Provider.self)
        try addProvider(MySQLProvider.Provider.self)
        
        // Run migrations aka preparations
        preparations.append(Station.self)
    }
}

Open Sources/App/Routes.swift and add a route.

builder.get { req in
     return try Station.makeQuery().all().makeJSON()
}



Manually add some records in the database. Vapor does not have any handy seeding functions.

Add record

Press the Run-button in Xcode

Press run


Visit http://localhost:8080 to see the JSON output