Wikileaks Vault 7: CIA Tips for Git Workflow

Wikileaks has begun dumping a large number of files on the CIA's hacking tools. The dump is called Vault 7. It is a goldmine, not only for information about the CIA's activities, but also for information on things like how to set up a development environment or properly use Git in your everyday programming workflow. Here are a couple highlights from some cursory searches of the document dump:

CIA Git Tutorials

CIA Vim Tutorials

CIA Setting Up a Development Environment

Comments (11)

How To: Install an Ubuntu Server Virtual Machine in VirtualBox

In this tutorial, we'll walk through the process of installing an Ubuntu Server virtual machine in VirtualBox. We'll then install open-ssh server on the server so we can access it from the host. I'll also be installing MongoDB in preparation for a database project.

We'll use Ubuntu Server our guest operating system for its relative ease of use and because there is already a large amount of support information that can be found online for its setup and maintenance in VirtualBox. I'll be using the 64-bit version of Ubuntu Server 14.04.3. Make sure you choose the version with the correct architecture for your system: 32 vs. 64 bit. Download a copy of Ubuntu Server from the link.



Before beginning the installation process of any virtual machine, it's always a good idea to check the hash value of the file you've downloaded to ensure its integrity. It is quite annoying to have to begin the process again because your download was corrupted in some way. You can find the hash values of various Ubuntu downloads here. (For a quick rundown on the process, see our previous post on why and how to check a file's hash value. See also our tutorial on how to build your own file hash checker in Python.)

Virtual Machine Configuration in VirtualBox

Let's jump in. After downloading and installing VirtualBox, if you haven't already, fire it up and click "New" to create a new virtual machine. Give your machine a name (I'm calling mine "ubuMongoLab," in preparation for the database project), select Linux as your type and select the appropriate version information from the dropdown menu.


After clicking "Next," we are prompted to select the amount of desired memory for the new machine. I'm going to leave the allocated memory at the recommended 512MB. You can tweak this for your own setup. In my experience, Ubuntu Server virtual machines tend to experience lag if you reduce the available memory below 386MB.


Click "Next." Select "Create a virtual hard drive now" and click "Create."



Under "Hard drive file type", select "VDI (VirtualBox Disk Image)" and click "Next."


On the next page, we configure the storage on the physical drive. Select "Dynamically allocated." This means that disk space for the virtual machine will only be taken up on your host machine's physical hard drive only after the virtual machine's disk has actually been written to. 


On the next screen, which determines "File location and size," I'm going to leave the default location and file name. The default size for the virtual machine's hard drive is 8GB. However, since I am using this VM for a database project that requires importing a fair amount of data, I'm going to allocate significantly more than that. Since I plan on using this virtual machine for other projects as well, I'm going to give it a good chunk of space: 50GB. 



Click "Create." The dialog should disappear and the new virtual machine should appear in your VirtualBox Manager. In the image below, I've created a group/folder for the new virtual machine called MongoTutorial.



Before starting up the new machine, let's tweak a few settings. Single-click the VM and then click "Settings." Under "General," I add in a short description under the "Description" tab:



Under "System," I unclick "Floppy" on the "Motherboard" tab.


I'm also going to allocate a second processor to the VM under the "System->Processor" tab:



For now, we can leave everything else as-is. I'm going to leave the defaults for the display, since we're not going to be using any graphical interfaces. And we'll leave the single default network adapter attached as NAT until the machine is up and running and fully updated. Click "OK" to save your settings. Make sure your host machine is connected to the internet before beginning installation of the Ubuntu Server OS. This is not strictly necessary, but it can speed the process up a bit.

Installing Ubuntu Server on the New Virtual Machine

Now single-click the machine in your VirtualBox menu, then click "Start" to fire up the new machine. You'll now be prompted to select your startup disk. Use the file icon next to the drop down menu to navigate to the Ubuntu Server .iso file you downloaded earlier and select it. This is the virtual equivalent to inserting an actual disk with the Ubuntu Server .iso file on it into a physical machine on which you want to install the system. Then click "Start".


Select your language and click enter (note: your mouse will not work here, the installation process is entirely keyboard-based):



Select "Install Ubuntu Server" using the up/down arrow keys, if it is not already selected, and hit enter.


Select the language for your new VM operating system and hit enter:



Then select appropriate values for the next two screens: your country and keyboard layout. Next we're going to enter a name for the new system. I'm going to choose the same name as I gave the VM itself, though they do not have to be the same. Enter the name, press the down arrow to select "Continue" then hit enter.


Then provide a name for the main administrative user of the new system:


Add a username for the account itself (I'm using the same name for both):


Choose a password for the account:



Choose whether to encrypt the home directory:



Select your time zone and let it do its thing. Next, for partitioning, I'm going to choose "Guided - use entire disk." This will install the operating system to the entirety of the disk we have allocated inside VirtualBox for the new virtual machine.



Select the virtual disk you have already allocated for the new machine and hit enter.


Now we have to answer "Yes" to write the changes to disk. This will install the new system on the space allocated for the VM.


Let it do its thing while it installs the new system (this could take a few minutes):


Follow the instructions for the proxy setup if you have a proxy, select continue and hit enter:



I'm going to update this system manually, so I select "No automatic updates" on the update config screen:



I'm also going to use manual package selection:


Select "Yes" to install the GRUB boot loader and hit enter:


Select boot into the new system (I've found you don't have to "remove the virtual disk"):



It should shutdown and boot right into the new system:



Supply the credentials you entered for the main user during the installation process and you will be logged in to your new virtual machine!



Updating and Upgrading the Server

We are now going to update and upgrade the operating system and install open-ssh server so we can access it from other machines on the LAN, whether the host or otherwise. Which means we also don't have to worry about installing VirtualBox guest additions, since you can just access the VM over ssh from your preferred host. Enter the following command at the command line, and enter the password credentials when propted to do so: sudo apt-get update. This will update the system's repositories. Now we'll update the existing software on the system. On the command line, now enter: sudo apt-get dist-upgrade. Hit "Y" if you are prompted to do so.


Now I'm going to install a couple programs I'll need for the current project: open-ssh server and mongodb. Open-ssh server allows you remote login access to the VM, so we can access it from a preferred host. I'm also installing mongodb as I created this VM for a database project. To install a program, on the command line, enter: sudo apt-get install <PROGRAM NAME>. For ssh: sudo apt-get install openssh-server. And for MongoDB: sudo apt-get install mongodb. Hit "Y" if you are asked to proceed:


Now let's shut down the machine so we can take a VirtualBox snapshot of our fresh install with updates and our necessary software. Enter: sudo shutdown -h now.


We'll now take a snapshot of the virtual machine inside VirtualBox, that way if we run into any serious problems from this point on (ex. it gets corrupted somehow) we can always revert to the present state of the machine and system. Click "Snapshots" inside the VirtualBox Manger.


Then click the camera icon. Add any notes you like, then click okay.



Switching to Bridged Networking Mode

Now we'll adjust the network settings of the virtual machine so we can log into it over ssh from other computers on the LAN, for example, the host machine on which the VM is a guest, or other hosts on the network. To do this, we are going to put the VM into bridged networking mode.

Click "Settings" for the VM inside the VirtualBox Manager, and then select "Network." From the "Attached to" dropdown menu select "Bridged Adapter." Note, the "Name" field contains the name of the connected network interface on the host machine. On my host machine, the eth1 interface is connected to the local network. Select the appropriate interface for your system and then click "OK."


Now start the virtual machine up again. Once it boots up, login with your main account credentials. To log into the virtual machine using ssh over the network, we need to know its IP address. To get the machine's IP address you can run either the ifconfig command or ip a.



Remote Login with SSH

As you can see in the screenshot above, my virtual machine has ip address 192.168.1.104. Yours is likely something similar. Now open a terminal on your host computer itself. From here we log in to the virtual guest via ssh with the following command: ssh <username>@<VM_Ip Address>. I created an account for user named 'admin1' and the IP address is 192.168.1.104. So I can log in to the virtual machine from a terminal on any other computer sitting on the network with the following command: ssh admin1@192.168.1.104. When you are prompted to add the ssh fingerprint, type "yes." When you are prompted for the virtual machine account's password, supply the proper credentials. And you should get a successful login:



We're now logged in to the virtual machine from the terminal of the host computer. Since I created this VM for a database project, I'll make sure mongodb is up and running: ps aux | grep mongo.


Since mongo is running, we should also be able to simply call the mongo command to get a mongo shell: mongo.


Congrats, if you've followed along in this tutorial, you now have a freshly installed version of Ubuntu Server running openssh-server and mongodb inside VirtualBox. Now the real fun can begin!
Comments (1)

PyGest: A Python tkinter Tutorial, Conclusion

This is the final article in our Python tkinter tutorial series. If you've been following along from the beginning, you should now have a desktop file hashing application with a fully functioning graphical user interface!  Here is our final product:



Here is what it looks like after successfully matching a user-supplied hash value:


And here it is on failure:
We covered a lot of ground in this tutorial. We took a pretty close look at: 1) tkinter's grid geometry management system, 2) all the most basic widgets such as labels, text entry objects, buttons, etc. and even 3) some of the newer advanced features in tkinter, such as the file dialog functionality.

For the above screen shots, I obviously cleaned up the code a bit from where we left off in the previous article, having removed the various background colors we were using for debugging purposes and some other small clean up tasks (I used one of the latter to reposition the "Hash Value" and "Result" fields, see if you can find it). Here is the final state of our code:


We hope you enjoyed the series. As always, comments, questions, suggestions and critique are welcome below.
Comments

PyGest: A Python Tkinter Tutorial, Part 5

This is part five in our Python tkinter tutorial series, in which we are building a simple GUI app to process and check file hash digests. In the previous two articles (part 3 and part 4), we configured the input and output widgets for our app. In this post, we're going to build out our app's two primary buttons and hook them into the appropriate input and output fields.




Our mockup design calls for two buttons: 1) a button that computes the hash value of the given file and checks to see if it matches the value that can be provided by the user; and 2) a button that clears all the input and output fields. Before we begin, let's consider more precisely what exactly our buttons will do. For the purposes of this tutorial, we're not going to consider all the possible edge cases, but rather try to keep things simple.

When the user clicks the hash button, what needs to happen? The app should first: 1) grab the file path from the file path input field, 2) grab the hash value to check against if the user has supplied one, 3) determine which hash function to run from the user's choice of radio button. Then it has to hash the appropriate file, and when the hash digest value is returned, it should: 1) compare that value against the user supplied hash value if there was one, 2) display the digest value in the appropriate output field, 3) indicate whether there was a match, or no match, or something else, in the result field. The second button is much simpler. When the user clicks the clear button, all input and output fields should be cleared of any values.

You can find the current state of our code at the end of part four in our tkinter series. As usual, we'll begin here by getting the preliminary configuration of our button widget frame out of the way. Here's the relevant code from our View class:


Following our normal work flow, we've configured a new row in our main_frame to hold the new frame for our button widgets, and given it a weight of 1. We've also created a new method where we'll configure the frame for our button widgets, and we've called that method from our setup method. We've embedded the buttons frame into the main frame grid at row 3, column 0. And finally, we configured our button frame to have 2 rows and 1 column, to hold each of our two buttons. Let's now configure our two buttons and create place holders for the functions they will call.


These are the first buttons we've configured for our app, but the code in the snippet above should look fairly familiar to you by now if you've been following along from the beginning. We've attached each button to the buttons_frame object. We've embedded the hash button at row 0, column 0, and the clear button at row 1, column 1. We've given both a 'raised' relief to make them look like buttons, and made them both sticky in all four directions.

The only thing really new that we're encountering in the configuration of the buttons is the 'command' keyword argument. As you might have guessed, the command keyword argument contains a reference to the method that is called when the button is pressed. (Note that there are no parentheses () following the name of a method or function when it is assigned to the command keyword argument, but rather just the name of the method itself.) We've also created an initial version of each of these methods, which, for the time being, log a simple message when the method is called.

If you run the app, you'll see that each time you click one of the two buttons, the corresponding log message will appear in your terminal. Make sure you have verified this and that your buttons are working properly before moving on to the next section.

The Home Stretch
We're in the home stretch! All the widgets for our application's GUI are now in place. All that remains to do is to fill out the runHash() and clear() methods with the necessary functionality, and then clean up the code.

So, what do we need in order to run our hash function? To begin with, we need to know the full path of the file to be hashed and the hash function we are going to use. Fortunately, we have access to the appropriate class instance attributes that we created in previous installments!


In the runHash() method, we've now grabbed the file path and hash function values from their respective class instance attributes and logged the results to make sure things are working properly. If you run the app, you can play around with various input states to make sure you are indeed grabbing the correct values. Try choosing a couple different files, using the two different radio button options, and verify that the correct values are logged in your terminal.

We'll now write a top level function to process our file hashes and return the hash digest. I've decided to place this function outside our class to keep its logic separate from our app's main view. We'll name this function processDigest() and call it from the runHash() method and log the result.


If you've never used Python's hashlib module before, it might not be entirely clear what's going on in the function above. If so, don't worry too much about it, the code above should work for you, but you should read up on hashlib in the docs, and elsewhere, such as at Python Module of the Week. Suffice it to say, our processDigest() function takes two parameters: the path of the file, and the type of hash to run. It calls the appropriate hash function from hashlib based on the hash_type parameter, and then runs that function on the file located at the path parameter. If something goes wrong, it logs the error. If all goes well, it returns the hash digest.

Our hash button now returns the input file's hash value and logs it in the terminal. We still have to display the returned value in the digest output field, check this returned value against the one that may have been supplied by the user, and provide an appropriate message in the result field depending on the outcome of the match check. This might sound like a lot, but it can easily be accomplished without ever leaving the runHash method. Let's add the necessary functionality.


This seems to do the trick. First we set the hash value attribute with the returned digest string (we then get that value and log it to make sure it's there!). Then we get the the contents of the user supplied hash value input field in the same way, using the get() method that complements the object's set() method. If there's nothing there, we display a simple message saying we're done. If, on the other hand, the user supplied value matches our digest, we display a success message. And finally, on the third hand, if the supplied value does not match, we display a failure message.

Let's fill out our clear method now. It is pretty simple. All it needs to do is set our string variables to the empty string and delete the contents of our entry fields. 


Set and delete are all we need here. We've seen the set method before. Here we clear the string variables by setting them to the empty string. For the entry fields, we use the delete method. We want to delete everything in the entry field, so we pass in two parameters: 0, which is where we want to begin deleting from, and 'end', which is where we want to delete to. Here's what the app currently looks like on my system, with all the debug and testing colors still in place, after having successfully processed a hash a confirmed a match:
And that's it! All the necessary functionality for our PyGest checksum checker is in place! Our app is still a bit rough around the edges and could use some cleaning up. But everything's there and it appears to offer all the functionality required from our design and specs. In the final article in tkinter tutorial series, we'll clean up the code a bit, and then consider some final thoughts. Here's the current state of our code:


Thanks for following along!
Comments

PyGest: A Python Tkinter Tutorial, Part 4

This article is part four in our ongoing Python tkinter tutorial series. When we left off in part three, we had just completed configuring the inputs for our interface, which included text entry, label and button widgets. We'll now move on to the widgets necessary for conveying the application's two outputs: 1) the hash digest value of the file input supplied by the user, and 2) a message indicating whether the file hash generated by the app matches the optional hash value that may be supplied by the user.




In our mockup design for the application's interface, the output-related objects are comprised of four different widgets, all of which are basically just labels: 1) a pair for the output value of the digest that results from hashing the input file, and 2) a pair indicating whether that hash digest matches the optional input value that may be supplied by the user. Since the output values are going to be dynamically generated, we're also going to need two tkinter string variable objects to grab and display the dynamic values.

However, we have to be a bit careful here. If you run your app as-is, where we left off in the previous article, you'll notice that you are not able to copy the text from any of the labels we've already configured for the app. This is simply not possible because of the nature of Python tkinter labels. But it would obviously be nice if users were able to copy the output digest of the hash function. Indeed, most users would probably expect they would be able to do so, and would be annoyed if they couldn't. For this reason, we are going to use an Entry widget styled to look like a label for the hash value output, since you can copy text from an Entry widget.

To configure our output widgets, we're going to follow much the same method as we used for our inputs. We'll create an outputs frame embedded in the main frame, and then drop the various output widgets in the output frame's grid. Following our usual process, let's create a method to configure our output widgets, configure a new row to hold the outputs frame in the main frame, and call the configure outputs method from our setup method. Here is the relevant code from our View class:


This should all look pretty familiar by now. Notice, we have embedded the outputs frame at row 2, column 0 in the main frame since the inputs frame is in row 1 column 0 and the banner is in row 0 column 0. We've also given it some basic styling so we know where it is, and made it sticky in all four directions.

Our outputs frame is going to have two columns (one for a label indicating the name of the output, and one for displaying the output itself) and two rows (one for the hash digest output, and one for the result message indicating whether there is a match). Let's define them now, giving each a weight of 1.


Taking a stab at the top row of outputs, we'll need: 1)  a label to indicate to the user that she is looking at the output hash digest value, 2) a string variable to hold the hash digest value, and 3) an entry widget to provide a selectable display of the value. 


In the snippet above, we've configured a simple label indicating the result, and put it in the top left cell of the output frame grid (row 0, column 0), and provided it with the text 'Hash Value:'. We've also made it sticky to the east, so the text is displayed just to the left of the entry field. Next, we've created a string variable to hold the hash value itself, and provided it with a default text string. Notice that we've assigned this string variable to a class instance attribute because we are going to have to access it from other methods so we can get it and set it dynamically. Finally, we've configured an Entry widget to be 'readonly', with a flat relief and no highlight thickness. This latter configuration ensures that its displayed text will look like that of a label (at least on my system!). We've embedded it at row 0, column 1 in the outputs frame grid, and made it sticky to the west so it hugs its corresponding indicator label. We've further made the Entry object a class instance attribute so we can access it from other class methods as necessary. (Note: you may have to toggle the state of this Entry widget from 'readonly' to 'normal' when you want to insert a new text variable string. I have seen inconsistent information in this regard, but this toggle action was not necessary on my system.)

Now we'll move on to our second row, which will hold two labels: one indicating that that we are looking at the result of the matching function, and one displaying the result itself (i.e. if there was a match between the user-supplied hash value and the actual hash value of the user-supplied file or not). We'll also need a string variable to hold the desired result message.


The code above is pretty straightforward, and very similar to what we did for the previous row. We have a label indicating that we're dealing with the result, embedded it in row 1, column 0, and made it sticky to the east. Next we set a string variable as an instance attribute because we need to be able to set it from other methods, and provided it with a default text string. Finally, we have a third label that we are going to set dynamically with the appropriate text indicating the outcome of the hash check.

If you run the app now and play around with it a bit, you'll notice you are able to copy the string variable text associated with the 'Hash Value:' label, but that you cannot copy the string variable text associated with the 'Result:' label, just as we desired. Here's the current state of the interface with background highlighting of the three basic frames we've constructed: the banner (blue), the inputs (white), the outputs (green):
With that, we're done with the first stab at our outputs widgets. Wow, that was easy, no? We may find ourselves tinkering with these widgets a bit more as we add the last layer of functionality to the app. We're now ready to configure our app's buttons, and hook them into our inputs and outputs through their corresponding actions! You can review previous articles from this Python tkinter tutorial at the link. You can find the next article in our tkinter tutorial series (part 5) at the link.
Comments

PyGest: A Python Tkinter Tutorial, Part 3

This is part three in our Python tkinter tutorial series on building a simple GUI app to compute and check file hash values. In part two, we added a banner header to our bare bones view by inserting a tkinter label into our app's content frame. In this segment, we will build out our app's various input widgets. Recall our mockup design:




We'll continue working our way from top to bottom, and add in those components relating to the application's inputs: 1) the file path, 2) an optional hash value to check against, and 3) a choice of hash functions to run against the file. Altogether, we'll have six objects to configure: two labels, two corresponding input fields, and two radio buttons. We'll also get a glimpse of tkinter's more advanced  functionality by implementing a native window dialogue that lets the user choose the file that will be hashed. This will be the most involved article in the series, so make sure your caught up with the current state of the code, get a cup of coffee and settle in.

Configuring the Inputs Frame
As with the banner, we'll create a new method to configure the input-related objects, and call it from our setup method. However, because there are a number of inputs, we'll group all the objects in this method inside their own frame, defined specifically for the purpose. To make space for this group's frame in the GUI, we'll also have to configure a new row in our main_frame object, and then drop the input objects frame into that row. To begin, let's get the preliminaries out of the way.


We've made a few additions to our View class in the snippet above. We've created a configure_inputs method with a simple log message, and called it from set_up(). In the configure_mainframe() method, we've added a single row to the app's outer frame. (We'll soon attach the inputs frame to this cell in the grid.) In configuring the new row, we identify it as row 1 and give it a weight of 1. Notice, the weights of both row 0 and row 1 are equivalent, which means they will expand and contract in the same proportion when the window is resized. We will change this in due time. Now on to the inputs.

In the configure_inputs method, we are going to configure a new frame using the grid geometry manager, and attach the various input objects to the appropriate cell in this grid. Looking at our mockup, the app's input objects are basically organized in a 3x2 grid: three columns to hold a label, an input field and a radio button in a single row, and two rows to hold each of the sets of these objects. We'll begin by creating our inputs frame and dropping it into the new row we just created in  the class's self.mainframe property. We will add columns and rows to our input frame as necessary.


Here we begin laying out our inputs frame with some basic settings. This frame is pretty much self-contained, so we don't have to make it accessible as a class attribute. We define it as a tkinter.Frame() object and pass in a number of arguments: self.mainframe is the pre-existing object we want to embed it in, and we also give it some styling to make it stand out against our temporary blue background. In the next line of code, we place the inputs frame in the desired grid cell in the self.mainframe object. Our banner is already at row 0, column 0. We'll put the inputs frame just below it, at row 1, column 0. We then make it sticky NSEW to start (we'll tweak this later as we add more elements to the frame). Finally, we configure column 0 and row 0 in the input_frame itself, giving each a weight of 1. By the end of this article, our inputs frame will have three columns and two rows.

Our input frame now has one cell, located at row 0, column 0. In our mockup, the top left object from among our input widgets is the label alerting the user to enter a file path. So let's add that first.


We define the file path label as a tkinter label object, and pass it the appropriate arguments to embed it in the inputs frame with a descriptive text. We also use kwargs to define a background and foreground color to get a sense for how the objects are laid out within the frame. In the next line of code, we then place the label at row 0, column 0, and make it stick to the east side of the cell because we predict it might be nice to have it flush against the entry input field once the other elements are added to the frame. Play around with some different variations of the sticky options to get a sense for how they affect the placement of the label text.

Just to the right of the file path label, we need an input field where the user can enter the path of the file to be hashed. In tkinter, this is called an Entry object. Let's think for a second about how we want to get this input. We can have the user actually type in or copy and paste the full file path as a text string. However, that is obviously not ideal. It would be more convenient for users to be presented with a dialog window that allows them to choose the file from their file system. Or better yet, both! As a first approach, we'll thus configure a text entry field so that when it is clicked it generates a file dialog that allows the user to choose the appropriate file from their local system. Then, when a file is chosen, its full path will be inserted into the entry field.

This will obviously make things a bit more complicated to code than simply just having the user enter a full path text string, but it will make the app much more user-friendly in the end. Plus, it will allow us to demonstrate one of the helpful additions to the tkinter library. Indeed, as we'll soon see, the tkinter library has just what we're looking for!

We thus want to configure a simple Entry object and then bind a click on that field to the generation of a file dialog. It makes sense to put the logic for the file dialog in a separate method. But we'll also have to access the Entry object from that method, which means we should define our Entry object as an attribute of the class. Here's our next snippet:


We want to embed this Entry object next to the file path label, so we have to add a new column to the input frame (see line 16). This is column 1 in the frame, and we'll give it a weight of 1 to start. Then, just below the label, we add the necessary code for the entry object. First, we define self.file_entry as a tkinter Entry object embedded in the inputs frame (line 22). In the next line of code, we call the bind method on the Entry object, and in the arguments, we connect a button-type single click event to our custom file dialog method, which we've called chooseFileName().  (For more info on events and bindings, see the effbot docs.) Finally, we call the grid method on the entry object to identify the cell we want to attach the entry object to in the inputs frame: it's going to be at row 0, column 1. As you can see from the above, the chooseFileName method is just a place holder at present, but it does log a message every time the method is called. If we run the code above, you should see something like this:


When you run the app, if you click inside the box delineating the Entry object, you should see the log message from the chooseFileName method, which is bound to be called on that event.

Weighting the Grid
However, if you run the app and play around with it a bit, you'll notice some strange behavior. For example, when you resize the window, you'll see that the banner header field expands with the window. Indeed, right now the banner will take up exactly half of the vertical space of the window, no matter what size it is. That's because there are only two rows in the main frame (one of which contains the banner header label object), and both of these rows have been configured to have a weight of 1, which means they resize proportionately to one another. Go back up to your configure_mainframe() method and change the configuration of row 0 to have a weight of 1: self.mainframe.rowconfigure(0, weight=0). You'll see the difference immediately: the banner header will no longer expand vertically when you resize the window.

Tkinter File Dialogs
Let's now fill out the chooseFileName() method. What exactly do we want this function to do? When the user clicks the file path entry field, we want a native-looking pop-up to appear that lets the user choose a file from his or her local system. Then, once that file is chosen, we want the window to close and the file path to appear in the file path text entry field. For this, we are going to utilize one of the new additions to Python tkinter: the filedialog submodule. It contains a number of helpful objects and functions, indeed, it has the exact one we are looking for: the askopenfilename() function.

As I understand it, the filedialog submodule has to be imported separately from tkinter itself. At the top of the script, let's thus import the filedialog submodule as fd: import tkinter.filedialog as fd. Our imports now look as follows:
import tkinter
import tkinter.filedialog as fd
import hashlib
import logging
Now, in our chooseFileName() method, we call the fd.askopenfilename() function, pass it a descriptive title, and log its return value (notice we're also passing the bound event itself to the method!):


If you run the app with this code, when you click on the file path entry field, it will generate a native file dialog asking you to choose a file from your local system. The title you supplied will be written to the top of this window. Furthermore, if you use the generated dialog window to choose a file, you'll see that the full path of the file is returned by the function when you pass the returned value to your logger.

Now we want to write that file path to our text entry field. This is accomplished by calling the insert method on the file entry class attribute object. We want to insert the file name beginning at index zero inside the entry field. This is why we needed to have access to the file_entry object outside of its method's local scope. So we add the following:



We're going to need to access the full file path later when we run the hash, so we might as well create a class instance attribute for the file path, and save the returned value from the file dialog to that variable. I also declare this attribute in the init() method just to be explicit about things. In chooseFileName, we call the insert method on the self.file_entry class attribute, and pass it two arguments: the index at which we want to insert the desired string, and the string returned by the file dialog. If you run the app, click the entry field and choose a file, the full path should now be written to the entry field once the file dialog window closes. Things are coming along nicely.

Radio Button and String Var
With our chooseFileName helper method finished, we can now return to work on configure_inputs(). Recall, our app is supposed to allow a choice between running a SHA1 hash or an MD5 hash of a file. SHA1 will be the default because it is more secure, so we'll place it on the top. Let's add the third object in the top row of the frame: a radio button that corresponds to the first option from among the two hash functions our app will utilize. First we have to add a third column to our inputs frame so we have somewhere to put the button! Of course, the third column is actually at column index 2 in our grid. The configuration of our inputs_frame object thus now looks as follows:


We're using radio buttons for the hash options rather than, say, check boxes, because a choice between radio button options is mutually exclusive. (It might be nice to perform multiple hashes at once, but we're trying to keep things simple here.) In our app, the user can choose to hash a file with SHA1 or MD5 by checking the appropriate radio button. We obviously need to keep track of which radio button the user has chosen so we can run the right hash function. To that end, we will utilize a tkinter string variable. We thus define a tkinter string variable, exposing it as a class attribute (since we will need to access the value of this variable to run the hash function), and give it a default value of 'sha1' with the set method, since that is the name of our default hash function. We add two lines to the bottom of our configure_inputs method to define the string variable:


We've also appended two more lines to define our top radio button. The first defines our sha1 variable as a tkinter.Radiobutton() object, and we pass in four arguments: 1) the name of the frame where we want to embed the button, 2) the text that will appear in the GUI next to the button, 3) the corresponding tkinter StringVar we want to associate this radio button with, and 4) the value to send to the string variable if this button is chosen. In the final line, we place the button in row 0, column 2 of the inputs frame identified in the previous line. Our app now looks something like this:


With that, we've reached the halfway point of our set task for the present article! At the top of our inputs frame, we've added 1) a label, 2) a text entry input, bound to a file dialog pop-up window event, and 3) a single radio button. We now have to add the second row. Like the previous row, it will hold: 1) a label indicating where the user can insert a hash value to compare against the hash of the file performed by the app, 2) an entry field where the user can insert that value, and 3) the MD5 radio button. Fortunately, we won't have to hook up the text entry input to a separate function, and now that we have the top row done, the second will be rather easy to implement.

First, we have to configure a second row in the input frame, and then we add two lines each for the label, text entry and radio button widgets:


We've added a digest_label to the inputs frame, with the text "Compare Digest:", and inserted it at row 1, column 0 in the frame, and made it sticky to the east. Secondly, since we are going to need to access the digest_entry field from other methods (in order to get the value we want to compare our hash with), we make it a class instance attribute and define it as an Entry object in the inputs frame. We then place it at row 1, column 1 in the grid and make it sticky to the east and west. Finally, we create our MD5 radio button, define it as belonging to the inputs frame, provide the text we want to appear in the app, define the variable it is attached to (i.e. the StringVar object variable we set up earlier, to which we've already attached our SHA1 button), and give it a value of 'md5' so we know when it has been selected. We then place it in row 1, column 2 of the grid. Our app is coming along nicely:


That took a bit of work, but now we're done configuring our app's inputs! Here is the current state of our code:


In the next article, we'll implement the various objects necessary to display our app's output. Thanks for following along! You can find part 4 in our Python tkinter tutorial series at the link.
Comments

PyGest: A Python Tkinter Tutorial, Part 2

This is part two in our Python tkinter tutorial series. In part one, we defined the basic structure of our script, set up a logger, and got the root window of our GUI application up and running in the app's single view class. In the present article, we'll begin work on the main view in earnest. We will configure the tkinter root object, create and configure a single frame to hold all the app's contents, and then create our app's title banner. First, however, we should discuss how to structure the layout of a Python tkinter application, and our strategy for doing so in the present project.


From what I've read, it appears that a lot of people had been turned off by Tkinter in the past because of its' seemingly weird geometry management, which involved a choice between placing widgets, or packing them or putting them in a grid, when building a layout. The docs suggest using the pack method over the placement method. It is thus no surprise that many tutorials and reference web sites utilize the pack method.

But the pack method never really clicked for me when I first started playing around with Tkinter in Python 2.7 a couple years ago. These days, in Python 3.4, the preference is to configure tkinter views using the grid geometry manager. This method is suggested by Russel Keith-Magee in his defense of tkinter (mentioned in the introduction to our series), and I've come across other recent discussions of the module making a similar argument.

Grid Geometry Management: Grids of Grids
In terms of its geometry, our app will consist of a grid of grids. First, we are going to configure the root window as a 1x1 grid. Into that single root cell, we'll then install a main outer frame, which we'll structure as a grid that will grow as we add more components to our interface. We will then group related individual widgets (labels, inputs, buttons, etc.) into their own frames in a grid format, and then drop these frames into the desired cell(s) of the main outer frame's grid as needed to build our interface.

For the purposes of this tutorial, we are going to structure the View() class by creating a setup method that is run on initialization of the class. This method will call a series of others methods that build the individual elements of the app: root window, main frame, banner, input fields, output fields, button box, etc. We will build out these various methods in subsequent articles until we have a working model of our mockup design.

Configure the Root Window
Beginning from where we left off in part one, we'll now add our set_up() method to the View class, and call it from init(). In set_up(), we'll call another method, configure_root(), where – you guessed it – we configure the root window. We're going to set some basic properties on the root window by calling two methods on the self.root attribute in the View class: columnconfigure() and rowconfigure(). It is here that we could also call methods such as minsize(), if we so desired.

We use the columnconfigure() and rowconfigure() methods on root to define the properties of the outermost grid in our app. These methods each take an integer parameter defining which column and row we are referring to (in our case, since we are building a 1x1 grid, we'll be defining column 0 and row 0), as well as a kwarg that defines their respective weights to be 1. The weight keyword argument determines how the cell responds when the window is resized. Giving them both a weight of 1 means they will resize proportionally to each other when the window is resized. Your View class should now look as follows:


Learn to love the column and row configuration methods! They are the primary means by which we'll define where our app's widgets live, and how the individual cells of our app respond to changes in the window size. There are other configuration options for the root window which you can play around with on your own, but we're now done configuring the root window for the purposes of PyGest.

Configure the Main Frame
We'll now configure the main content frame of the app. As mentioned above, we are going to drop this content frame into the single cell we just defined for the root window. Unlike the root grid, this content frame will be variable in size and will grow as we add more widgets to the interface. Define a new method called configure_mainframe() in the view class and call it from the class's set_up() method. For now, we are going to add five lines of code to this method. Later we'll see it grow along with the rest of the app.


If you run the app now, you may find that your window has mysteriously disappeared! No need to panic, we'll get to that in a second. (Hint: call the minsize() method on the root object.) There's a lot going on in our configure_mainframe() method. Always start with a comment. After that, I added a simple log to make sure the method is actually being called  – since I initially forgot to call this method from set_up!

Next we define the app's main frame as a tkinter.Frame() object. Notice I'm defining it as self.mainframe, i.e. as an instance attribute of the class. This is because we are going to have to reference this attribute from other methods as we add more widgets to our app. (Though not strictly necessary, I also declare this attribute in the init() method of the class and assign it an initial value of None just to be explicit about its existence, and to make my IDE stop complaining about the fact that I've defined an instance attribute outside of init().)

We thus define self.mainframe as a tkinter.Frame() object and pass it two arguments. The first identifies the pre-existing object into which we want to embed this frame. We only have one such object right now (the root window of the app!) so we pass in self.root. I've also given the frame a background color to provide visual confirmation that it is in place. You can explore other parameters in effbot's reference documentation.

Next, we call the grid() method on our newly declared mainframe object, and pass it three kwargs. The column and row arguments determine where the self.mainframe object will be located within the self.root grid that we are attaching it to (as defined in the previous line of code). Our root grid only has a single cell, with the coordinates row 0 and column 0. So that's what we pass to the mainframe's grid method. Finally, we pass in the kwarg sticky, which we define as north, south, east and west. This means that the mainframe object will stick to the north, south, east and west sides of the cell to which it has been attached, if the size of that cell changes.

Finally, we configure a single column and a single row for our mainframe content grid, and give them each a weight of 1, just as we did for the root window. At present, our main frame is now a 1x1 grid, embedded in the single cell of the root window's 1x1 grid. As we add widgets to our interface, we will add more columns and rows to the mainframe grid as necessary.

As mentioned above, if you run the app with the code above, you may find that your window as mysteriously disappeared! This is because it has nothing in it except for an empty frame! By default, tkinter windows and cells always shrink down to fit the size of their largest element. Since our frame is empty, the window is minimized to the maximum. You can easily resize the window by calling the minsize() method on the root object in your configure_root() method: self.root.minsize(200,200).

Running the app with the code above, not much should change except for the fact that the window is now blue (or whatever color you've decided upon). If you resize the app, the main frame will stick to all four sides of the root window, and the window will remain blue. However, if you play around with the sticky kwarg by using different combinations of north, south, east and west, you'll see some perhaps surprising changes in the look of things.

For example, if you make the frame sticky only to the north and south, you'll see a single vertical line through the middle of the window. If you make it sticky only to the east and west, you'll see a single horizontal line through the middle of the window. This is because in tkinter, by default, a widget object is only as big as its biggest element. But our main frame doesn't have anything in it yet, so it collapses down in this seemingly weird way.

Configure the Banner
We now have a single root window structured as a 1x1 grid. We've embedded a single frame in that root window, and this frame is (for the time being) also structured as a 1x1 grid. As we add components to our interface we will add more rows and/or columns to this frame as necessary. Let's start to fill it out by giving it a header banner that displays the name of the app. First things first, define a new method inside the View() class called configure_banner(), call this method from set_up(), give it a basic comment and a log message.

We are going to display our app's name in the title banner using a simple label object. However, we now have a choice. Label is one of the objects that can be found in both tkinter and the ttk submodule. (As mentioned in part one, the ttk submodule contains widgets that are not available in the top level tkinter library, ex. Combobox, and also "gives the application an improved look and feel," according to the docs.) Objects that are in both the tkinter top level library and the ttk submodule are styled in a slightly different manner. Styling parameters are passed directly to top level tkinter objects like labels, whereas for ttk objects you have to configure these objects using the style class. You can play around with both to get a sense of the differences, if you like. For the sake of simplicity and backward compatibility, we're going to use a basic tkinter label here.

The configure_banner() method in our View() class is going to be very simple. It will have two critical lines of code: the first defines the banner as a label attached to our main frame and gives it some basic styling, and the second defines where the label will be placed in the main frame's grid as well as some other parameters. Here's the code for the configure_banner() method:


Under the comment and the log message, I define the banner variable itself as a tkinter label. We're passing five arguments to the tkinter.Label() object: 1) self.mainframe is the object we are attaching this label to, 2) we're making the background black so we can see it, 3) the text kwarg defines the text that will be displayed in the label, 4) the font kwarg is assigned a tuple that contains the name of the font and its size, and finally 5) fg (which stands for foreground) defines what color the foreground text is (note, you can also shorten the background kwarg to bg).

In the final line of the method, we specify the behavior of the object itself by calling the grid method on it. We're passing in five arguments here as well. The row and column kwargs specify where the banner will appear in the mainframe object in which it is embedded. We want our banner to appear at the top of the interface, so we're putting it at row 0, column 0. (We'll drop our next object into the app just below the banner at row 1, column 0 in the main frame.) Next we make the object sticky to the north, south, east and west to start. Finally we give it some horizontal and vertical padding to give the object a bit of breathing room.

If you had previously defined a minimum size for your root window with the minsize() method, you should comment that out, so you can see how the default window sizing works now that we have an object with some substance embedded in the frame. Here's the state of the app with its banner and debug coloring:
With that done, we'll end the present article here. We covered a lot of ground in this post, and  introduced the basic development flow that we'll follow throughout the remainder of the series. Play around with the various parameters for the main frame and the banner, and start exploring other tkinter widgets. In the next article, we will configure the necessary widgets for our app's inputs: labels, text entry objects, and radio buttons. Here's the state of our code:


Thanks for following along. As always, questions, comments, critiques and suggestions are welcome in the comments. In the next article in the series, we will build out the widgets relating to our app's user inputs: labels, text entry fields and buttons.You can find the next article in the series here.
Comments

PyGest: A Python Tkinter Tutorial, Part 1

This is part one in our tutorial series on building a simple Python GUI app with tkinter. You can find the introductory article to the series at the link. In this article, we'll get things up and running by filling out the basic structure for our Python script and the application itself. We'll add a top level comment, define the necessary imports, set up our main name space, define the main function, and then configure a logger to aid in sanity checking . . .


Our app doesn't have a name yet. Typically, Python application names have a 'py' prefix or suffix attached to a word describing the app itself. Since this app processes hash digests, we'll call it PyGest, for lack of a better idea. So we'll create pygest.py, add our top level comment and our main namespace. Then we define our main function with a comment and a pass for the moment, and then call this function from the top level script environment.


Let's talk about imports. We don't need to import that many libraries for our little app. We'll use the hashlib module to perform the hashing operations, the logging module to help with debugging, and, of course, the tkinter library. The imports for tkinter require a bit of explanation.

With tkinter it is common practice not to import the module itself, but rather all the elements in it directly (i.e. "from tkinter import *" instead of "import tkinter"), which is normally frowned upon in other contexts. Perhaps this is to avoid unnecessary keystrokes? However, in this project, we're going to flout convention and import the module just like any other, i.e. "import tkinter". This will require us to explicitly declare the module's name when we call up one of its objects (ex. tkinter.Label()), but it will help us keep better visual track of tkinter objects in our code.

Secondly, one of the additions to the tkinter module in Python 3 is the ttk submodule, which offers many of the same objects as the tkinter module itself: labels, buttons etc. However, it also contains a number of widgets that are not in the tkinter standard library (ex. combo boxes), and its objects are optimized to take on the native look of the OS platform running the app. (Personally, on my system, I can't tell much of a difference between the look of most tkinter widgets and ttk widgets.)

For our tutorial app, we're not going to be doing anything especially fancy, so I've opted not to use the ttk submodule, as all of the widgets we'll be using that are in ttk can also be found in tkinter proper. Moreover, widgets in the ttk submodule require a different styling format than the same widgets in tkinter, so keeping to the main library will make much of the code that follows accessible to folks working in Python 2.7. For more on the ttk submodule, see TkDocs. (Note that in Python 2.7, the tkinter module has a slightly different name. It is capitalized: Tkinter. And the ttk submodule is not available, as far as I'm aware.) With that, let's add our imports.


To aid in sanity checking, I like to configure a basic logger at the beginning of a project. If you're not familiar with the logging module, read up on it a bit in the docs. The idea is simple: we configure a logging object and then call it when we want to report info from the program while it's running. Of course, you might also consider just using print statements, but a logger can provide more information such as the time, the line number in the script, indicate levels of severity, in addition to providing a particular message. I'm also going to declare a 'title' variable with the name of the application.

So I define the title variable just underneath the import statements, then configure the logger inside the main function, and log a message indicating that the app has started up. This logger configuration logs the time, the line number, the level name and a message. For all the basic logging configuration options, see the docs.


Alright, let's get down to business. Tkinter works by running a tkinter.Tk() object in an event loop that can react to defined user inputs such as button clicks, mouse events, keyboard inputs and the like. In our application's main function, we will: 1) initialize our Tk() object as 'root', 2) configure the application's title by passing it to the root object, and then 3) pass the root object to our application's main view.

The main view will be a Python class that we use to configure, structure and build our interface. We thus add four lines to our main function. Notice that when I pass the root object to the view, I'm assigning the return to a variable. I have seen inconsistent explanation of this idiom, but it appears to be standard practice.


Of course, running the script above will result in an error since we haven't defined our View() class yet. So let's do that now. The View class will accept one argument, the root object. In the init() method, we'll define the root argument parameter, then assign the root object to a class instance variable appropriately named 'root'.


If you run the script above, you'll see your log message written to the terminal and then the program will appear to hang. But if everything's working properly, that's just what we would expect because it has launched the tkinter root window, which should be running its main loop. If you don't see the application's window, cycle through the applications that are open on your desktop to find it. By default, the tkinter root window does not take focus, and may be hidden behind them (it's nice like that). In your system's list of running applications, you should also see an icon indicating that the Python app is up and active. Here's what the empty root window looks like on my system, with a default size of about 200x220px:
If you can't seem to find the window even though the app is clearly running, it may be that the window is being drawn, but is not big enough to be seen. In that case, try setting a minimum size to the root window. Just after you pass in the title to the root object, add a line such as the following: root.minsize(300, 300).

To exit, you can just close out the window. Notice, if you press <Control-c> on the keyboard when in the terminal, the program does not stop running until focus is returned to the root window itself. With that, we've got the seed for our application in place.

In the next article, we'll begin the process of building it out, widget by widget. You can find the second article in the series at the link.
Comments

PyGest: A Python tkinter Tutorial, Introduction

In this tutorial series, we are going to build a simple file hashing application using the Python standard library's interface to the TK GUI toolkit: tkinter. One can find some resistance to using tkinter in the Python community. However, my interest in tkinter was recently rekindled after watching "Tinkering with Tkinter", a presentation by Russel Keith-Magee, in which the Django developer makes a strong case for revisiting this often overlooked and under-appreciated component of the Python standard library . . .

As Keith-Magee points out, these days tkinter has a number of arguments in its favor: 1) it is in the standard library, 2) it has been greatly improved in recent years, with additions to its basic functionality (more widgets!) as well as improvements in the look and feel of the GUIs it can generate, and 3) new resources such as the website TkDocs provide a ton of information to get Python tkinter GUI apps up and running in a relatively short period of time. Keith-Magee walks the walk as well, having built Cricket – a GUI tool for running Django and Python test suites – entirely with tkinter.

Our goal here is much more modest. We're going to build a single view file hashing utility in a manner appropriate for people with some experience programming in Python, but little or even no experience in Python GUI programming. Why would anyone want to build a file hashing utility? Simply put, hash functions can help determine the integrity of a file. For example, if a developer provides the hash value of a given file along with a download, you can check the hash value of the file you've downloaded against the one supplied by the developer to test whether the file was corrupted or modified in transit. (If you're new to the concept of hash functions or need a refresher, check out our past article on How and Why to Check a File's Hash Value.)

With that determination, we can already specify the basic functionality that we'd like our tutorial application to have. It should be able to: 1) generate hash digests of a specified file, 2) check the result against a known hash value, 3) alert the user as to whether or not there is a match, and 4) provide a choice of hash functions to use in the process.

Our application will thus need: 1) a number of labels to orient the user, 2) input fields for the file's path and the hash value to check against, 3) mutually exclusive radio buttons to choose the hash value, and 4) some buttons to run the program and clear the contents of the input fields. The project will thus provide us with the opportunity to play around with the basic elements of any GUI application. Here's a simple mockup:


We are going to use Python 3.4 throughout, but much of the code that follows should also work in Python 2.7, and I'll try to provide pointers as to when and why it might not. In case anyone is interested, I'm building this using the PyCharm Free Community Edition IDE on a Macbook laptop. Please note, there may be, or rather, it is virtually certain that there are far better ways to code the application presented in this tutorial. I built the GUI on the basis of my own idiosyncratic research into the tkinter library, and have organized the project to make it easier to present and digest in this tutorial series.

In the next article, we'll begin by laying out the bare bones structure of the application. Then we'll use a grid layout manager to construct our primary view as a set of grids within grids. This post will be updated with links to each successive article in the series as it is uploaded to the site. Enjoy! As always, any and all suggestions, comments and critiques are welcome in the comments. You can follow along with the tutorial using the links below:

PyGest: A Python tkinter Tutorial, Part 1 
PyGest: A Python tkinter Tutotial, Part 2
PyGest: A Python tkinter Tutorial, Part 3 
PyGest: A Python tkinter Tutorial, Part 4 
PyGest: A Python tkinter Tutorial, Part 5 
PyGest: A Python tkinter Tutorial, Conclusion
Comments (3)

Swift Networking Tutorial Index: Building a Swift App to Query a Custom API

Our tutorial series on networking in Swift provides a detailed, practical overview of the topic from the back-end API to the end user application. The series is broken up into two major parts. In the first part, we build a custom web service in PHP which provides access to a RESTful API that serves inventory content from a hypothetical plumbing supply shop. Knowing how to create a simple API is useful for delivering mock content during your app development cycle, and provides application developers with more knowledge on precisely how such a service is constructed. In the second part, we use table views to create a Swift application to query our custom API and deliver the contents of the service to the end user of the application. Use the index below to navigate the tutorial.

Introduction
Introduction and Overview: From the Back End API to the End User Application

The Web API
Building a RESTful API in PHP, Part 1
Building a RESTful API in PHP, Part 2

The Swift Client App
Networking in Swift: Building the Swift Client, Part 1
Networking in Swift: Building the Swift Client, Part 2
Networking in Swift: Building the Swift Client, Part 3
Networking in Swift: Building the Swift Client, Part 4
Networking in Swift: Building the Swift Client, Part 5
 


This tutorial was authored by Stefan Agapie, a Senior iOS Software Engineer, and adapted for the present piece.
Comments (4)

Networking in Swift: Building the Swift Client, Part 5

This is the final article in our tutorial segment on building a Swift client application to query a RESTful API and serve the response to the end user in a table view. If you've been following along since the introductory article, we've come a long way, and we're almost done! But we're not at our final destination just yet.

When we last left off in part four, we had added the necessary code to display thumbnail images next to our lists of inventory items. In this article, we will walk through the process of adding views for each individual item in our inventory such that when a user taps an item in the list view, she'll be presented with an item description scene that displays: 1) a bigger picture of the item, 2) the name of the item, and 3) the lengthy item description provided by the API. Let's jump right in.

The Item Description Scene
We will now set up our final story board scene. When the user taps on an inventory item from among those listed in the table view, we want to display a new view that provides an image at the top of the screen and below it a scrollable content area that displays the description text for the selected item. Create a new file,  and name it PlumbingSupplyItemDescriptionViewController:


Switch over to the main storyboard and drag a view controller into the scene. Next, drag in an Image View and place it to the top of newly added view controller. Give the Image View a height of 160 points using the size inspector in the utilities panel. With the Image View selected, bring up the 'pin' popover view as shown below:

Within the 'pin' view, uncheck the 'Constrain to margins' box and select the horizontal red bars and the top vertical red bar. Also check the 'Height' box as shown below:

Finally, click the button that reads 'Add 4 Constraints.' If done correctly, you should see no red or yellow lines near the Image View:

Now drag and drop a Text View into the scene, and size it as shown below with a small margin all around. (The vibrant color you see in the image below on the Text View was set by us so that it is clear what object we are referring to).

While the Text View is selected, bring up the 'pin' menu again, uncheck the 'Constrain to margins' box, and select the horizontal red bars and the vertical red bars as shown below, and then add the constraints:

We will now make the view controller that we dragged into our storyboard be of type PlumbingSupplyItemDescriptionViewController. Ensure that the view controller is selected. From the Identity Inspector menu locate the Class field and type in PlumbingSupplyItemDescriptionViewController as shown here:

Open the Assistant Editor. You should now see the main storyboard with our selected view controller along with the corresponding class. To the top of this class add the following code:

Like so:


To link these IBOutlets (@IBOutlet) to the elements to our main storyboard, we select the given element on the story board with [control+left mouse button] and drag the blue line over to the corresponding variable as shown below:


Do this for both elements in the view controller (i.e. the image and the text), connecting them to the corresponding outlets in the class.

When we select a table view cell from our list of inventory items, we want our newly-added view controller to be presented to the user. To do this we will [control+left mouse button] from the table view cell located in each of our table view controllers and drag the blue line over to the new view controller. Do this for both table view controllers. When the drop down menu appears select 'Show.'

From Apple Docs: “The Navigation Bar provides a control for navigating hierarchical content. It’s a bar, typically displayed at the top of the screen, containing buttons for navigating within a hierarchy of screens." To prevent the Navigation Bar from overlapping our Image View, we need to set some properties in the main storyboard. Ensure that the newly-added view controller is selected. From the Attributes Inspector menu locate the check box labeled 'Under Top Bars' and uncheck it. Run the application, navigate to one of the two categories and select one of the item table view cell. You should see a view similar to the following:


Item Description Scene: Displaying Image and Text
When using storyboards with segues, the system provides a callback method to the source view controller for when the segue is about to be performed. This allows us to prepare the destination view controller for its presentation onto the screen. (A segue is triggered when we select a table view cell that was linked to some view controller using a storyboard segue.) Ensure that the callback method is located in the PlumbingSupplyInventoryTableViewController class like so (by default it is supplied in the class but commented out):

Uncomment this code block if it is commented out, and replace the comments in this callback method with the following snippet:

On the first line, the segue object provides a reference to the destination view controller. On the second line we cast the sender object that the callback method provides as a table view cell since the cell that was selected becomes the sender of this segue event. Then we grab the index of the selected cell, on line three, and use it to retrieve the associated plumbing supply item from our data source and send it over to the destination view controller on line four. To avoid having to download the image again we simply capture it in our destination view controller from the selected table view cell.

Now back to the destination view controller class, a.k.a the PlumbingSupplyItemDescriptionViewController. Define these three functions:

The viewDidAppear(animated: Bool) function is a system method that we override with custom behavior after the view appears onto the screen. In this method we set the title of the view controller to the name of the selected item and call a function that downloads the description of an item. Replace the comment, '// title and download //,' within this method with the following snippet:

Notice that the item description text is passed through a completion handler closure once the download is complete. The code 'self.bsn_textView.text = itemDescription' sets the Text View's text area with the text of the item description. On the source view controller, we did not use this completion handler, which is available on its networking request method, but instead made the UI updates inside the method itself. We prefer to update the UI outside of the method that is tasked to download content as it makes for clearer code by breaking up the variegated logic into separate sections. Both approaches are possible, as we'll now see.

In the function urlForItemWithDescription(itemID : String) -> (NSURL?) add the following lines of code:

This method takes an item's id, maps it one of two possible endpoints and inserts that item id into the selected endpoint. The mapping is done by inspecting the first two characters of an item's id and using a switch statement.

In the function, requestItem(endPointURL : NSURL?, responseHandler : (. . .) -> () ) -> (), add the following code:

This code should look familiar. We already described what this code does when we originally downloaded inventory items. The only difference here is that we passed our data for the UI element to the completion block.

For our final function, i.e. the system function viewDidLoad(), place the following code within it:

The first line of code takes the captured image that was assigned to us by the source view controller and insert it into our Image View. The second line sets the font type and size of the items description. The third line disables editing of the Text View since this functionality should not be applicable. The fourth line displays text that serves to indicate that there is activity with getting an items description. Run the application and navigate to the item description page. You should see a screen similar to the one depicted below:

Success!  With that, we've completed the last major task for our Super PHPlumbing Bros Swift client application! When run, the client queries our custom API to first display the titles of the two inventory categories supplied by the API. When the user selects one of those categories, the app displays a list view of the inventory and provides each item's name along with the corresponding thumbnail image. And finally, when the user selects an individual item, the app displays the full image along with the item's full description.

This project can be found on GitHub.

We hope you've found this tutorial series helpful and fun. As always, questions, comments and suggestions are welcome below!

Index
Introduction
Introduction and Overview: From the Back End API to the End User Application

The Web API
Building a RESTful API in PHP, Part 1
Building a RESTful API in PHP, Part 2

The Swift Client App
Networking in Swift: Building the Swift Client, Part 1
Networking in Swift: Building the Swift Client, Part 2
Networking in Swift: Building the Swift Client, Part 3
Networking in Swift: Building the Swift Client, Part 4
Networking in Swift: Building the Swift Client, Part 5

This tutorial was authored by Stefan Agapie, a Senior iOS Software Engineer, and adapted for the present piece. 
Comments

Networking in Swift: Building the Swift Client, Part 4

This is part four in our tutorial series on building a Swift client application to query a RESTful API and serve the response in a list view to the end user of our app. When we left off in part three, we had successfully created a list view of the items in the two inventories supplied by the API. But a simple list of item names isn't very exciting. Let's add thumbnail images to display alongside the item names in our inventory listings.

The images we'll display alongside our inventory items are not stored within our Xcode app bundle, rather, if you recall, they are served up by our custom API along with item id's, names, and descriptions. We will therefore download the inventory item images and display them to the left of our item names. You can download the image assets from our Git repository for the project here, so as not to have to create mock image files with the appropriate file names yourself. After you've downloaded the files, place them in an appropriate folder alongside the other files for your inventory API.

Multithreading in Swift
All user interface related events, touches as well as view updates, occur on the main thread. Thus, if we perform operations that take a long time to complete, this will block or prevent the user interface from responding and or updating view elements—this is not desired behavior since it makes for a terrible user experience. To prevent blocking the user interface from receiving touch events while we download an image, we will download images on a secondary thread.

To get images we need their URLs. Recall that within our item model object (i.e. our PlumbingSupplyItem class) we have a property called 'bsn_image'. This property holds a URL to a unique image that corresponds to the item name in the same model object. 

In our PlumbingSupplyInventoryTableViewController class, we'll thus create an operation queue that will run on a thread other than the main thread. Toward the top of that class type the following line of code:

The string in the quotation marks here is completely arbitrary, and serves to avoid name collisions. In the function func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell, add the following snippet:

The first line of code (line 2) gets the image URL for the cell that is about to appear onto the screen. We will use this URL to download the corresponding image. The second line of code (line 4) is a call to the dispatch system. It copies the code that is nested within the closure and places this copy on our backgroundQueue. The code within the closure comprises an operation. Our backgroundQueue will then dispatch the copied block of code at a system determined time—in the immediate future. This is known as executing an operation. (The code above is structured in such a way that, for each instance of a cell that appears onto the screen, an operation is spawned and placed onto our operation queue. For example, when our table view first loads we have at most the same amount of operations as there are visible cells.) For our next line of code, currently just a comment, we want to capture the index of the cell that is requesting this image download operation. As a result, each operation on our queue will have a record of the cell's index that requested this operation. Now place the following line of code under that comment (on line 6):

For our next lines of code, currently just a comment, we retrieve an image's URL and begin downloading it. The NSData class has the following method that will synchronously download some data from the provided URL. (Synchronously, in this context, means that the request will block our thread, but not the main thread, until the download is complete. This is desired because we want the image's data to download before proceeding to the next lines of code that processes and displays the images). Add the following code below the relevant comment:

On the next line of code we verify that the image was downloaded without a hitch. If the image failed to download, then the error object would not be nil. Since displaying an image in an already displaying cell is considered a user interface update, it must occur on the main thread or else our images will not get displayed. To accomplish this we will dispatch operations to the main queue; on the next line of code, the call to the dispatch system does just that. For our next line of code, currently just a comment, we create an UIImage object from the raw downloaded data. Place this line of code under the relevant comment:

The following line of code gets the index of the cell that corresponds to the cell that spawned this image download operation. Place this line of code under the relevant comment:

Now locate the if-statement with the text, '/* compare indices */', and replace the comment with the following line of code:

This if-statement compares the captured cell index to the cell's current index. If the captured cell index is equal to the current cell index, then the cell that requested the image is still on the screen. We therefore present the downloaded image by executing the code that is nested within this if-statement.

When scrolling the table view,  the cells are reused to improve performance. When a cell is scrolled off the screen, instead of being purged from memory it is instead reused with a new index assigned to it. The issue is that when a cell is reused and subsequently redisplayed onto the screen, the cell spawns another image download operation which puts us in a state where we have more than one operation associated with any given cell.

To understand the issue here, suppose that the user scrolled the table view enough times that a single cell has four associated image download operations. When the individual operations complete their task, they message the cell by attempting to load an image into it. The visual result of four operations loading an image into one cell is a rapid succession of images changing as each operation loads its image. This behavior is not desired. Also, since the images may not download in the same order in which they were requested, we may wind up displaying the wrong image—this is bad!

The next two lines of code set the image on the current cell and tells the cell to lay out its cell for the newly provided image. Run the app and select one of the two plumbing supply categories. You should now see a table view with images and associated text as depicted below:
Success! We've displayed the relevant thumbnail images alongside the names of the items in our inventory lists. We're almost done! In the next and final article in the series, we will construct our individual item detail views. But before we conclude, let's return to the image-display issue mentioned above. 

To see the effect of allowing each operation to set a cell's image by not checking cell indices do the following. Comment out the if-statement: if currentIndex?.item == capturedIndex!.item). Now locate this line of code: self.dataSource = self.inventoryItems(data). Just below that line, load the data source multiple items by adding this line of code: for index in 1...5 { self.dataSource += self.dataSource; }.

Run the app and select one of the two categories. On an inventory items list page, quickly scroll down to the last element, you should see the images changing in rapid succession! To fix this effect, uncomment the if statement code only. Run the application again and quickly scroll to the last element. The issue should have been fixed.

It's good practice to cache data that is expensive to download. In our example, every time we scroll to a cell with an image that has already been shown, we don't request it from a local memory cache but instead download it every time. Our accompanying project repository contains sample code with a cache implementation. Simply comment out existing code and uncomment 'Version Two' sample code for a caching implementation—located in two places. If you run this implementation you will notice that the images load much faster when scrolling. This is highly desired behavior. 

This project can be found on GitHub.

That's it for the present piece. In the final article in the series, we will construct our individual item detail views.

Index
Introduction
Introduction and Overview: From the Back End API to the End User Application

The Web API
Building a RESTful API in PHP, Part 1
Building a RESTful API in PHP, Part 2

The Swift Client App
Networking in Swift: Building the Swift Client, Part 1
Networking in Swift: Building the Swift Client, Part 2
Networking in Swift: Building the Swift Client, Part 3
Networking in Swift: Building the Swift Client, Part 4
Networking in Swift: Building the Swift Client, Part 5


This tutorial was authored by Stefan Agapie, a Senior iOS Software Engineer, and adapted for the present piece. 
Comments

Networking in Swift: Building the Swift Client, Part 3

This is part three in the tutorial segment on building a Swift client application to query a RESTful web API, from our series of articles on networking in Swift. In the first segment, we created a custom RESTful API in PHP that serves up the inventory of our hypothetical plumbing supply shop.

In this segment, we have been building a Swift client which queries this API and delivers that inventory content to our end user. In part one, we got our Swift application up and running. In part two of building the Swift client, we created our basic data model, hooked up the segues to our inventory views, and successfully handled raw responses from the server by printing them to the Xcode console.

In the present article, we'll create model objects from the JSON dictionary returned by the server (at the end of part two), and display our inventory item lists in their respective table view controllers.

Model Objects
When we left off in part two, we were filling out the requestInventory method in our PlumbingSupplyInventoryTableViewController. Currently, that method simply prints the returned JSON dictionary to the Xcode console. We'll now create model objects from this dictionary by factoring out the relevant code from the requestInventory method and placing them in a separate method to handle this logic. In your PlumbingSupplyInventoryTableViewController file, add the following method below the requestInventory function that we were working on in the previous article:

Notice that in the last line we do not print out the jsonResult dictionary object but instead wrap it in an array and return it to the caller. In the requestInventory method, replace the three lines of code we factored out into the new inventoryItems method with the following two lines of code:

If you run the app and select one of the two inventory item categories, you should see the same response as before in your console, but wrapped in an array. We'll now refine the raw JSON data. Replace the return [jsonResult] line of code in the inventoryItems method with the following snippet:


Let's take a closer look at this. The first line gets the raw data dictionary object from the JSON results container. The second line defines a container that will hold model objects that are built from the raw data dictionary objects from line one. Inside the for loop we iterate through the raw data dictionary objects and build an array of refined data objects. And in our last line we simply return the array of model objects.

If you now run the app again, you'll see the difference in the Xcode console output, which now returns a tidy array mapping individual inventory items to their memory locations. Let's display these inventory lists in their respective views.

Displaying Our Inventory Item List
Return to the main storyboard. Locate and select one of the table view cells from our PlumbingSupplyInventoryTableViewController scene. In the Attributes Inspector, locate the Style drop down menu and select the option “Basic.” Locate the Identifier field and type in “Cell”. Finally, locate the Accessory drop down menu and select the option “Disclosure Indicator.” Do the same for the other cell as well.

Now open the file PlumbingSupplyInventoryTableViewController.swift file. Inside and toward the top of the class, add the following property:

This data source property will supply our dynamic table view cells with the information to display on screen. The number of items in our data source will always be equal to the number of items from a single plumbing supply inventory category. In the same class  replace the default boilerplate code for the three methods below with the following snippets:

These data source methods are called by the system to query this controller on how to proceed when building our table view and displaying content within it. In the first method we simply tell the system that our table view will display only one section. The second method says that the number of items in our single table view section is equal to the number of items in our data source.

The last method does several things to build a table view cell. In the first line (line 12 in the snippet above) it dequeues a reusable cell. When scrolling a table view, table view cells that scroll off the screen are placed on a queue for reuse and cells that scroll onto the screen are removed from this queue and reused. This process helps speed up table view performance which makes possible the smooth table view scrolling with which we are all familiar. On the second line (line 13) we utilize the indexPath object to get the row number of the cell that is next to become visible in our table view; the row number corresponds to a unique item in our data source. There is a one-to-one correspondence between the cells and the items in our data source. The following line gets the name of an inventory item and assigns it to the label of the next cell to become visible. The last line simply returns that cell.

Let's jump back to where we defined our requestInventory function. In this method, replace this line of code that reads println(inventoryItems) with the following snippet:

What's going on here? In line 1, we capture a reference to the data source that is received from the self.inventoryItems(data) method call. The next segment is a C level API call to a dispatch system, on a queue of our choice, which executes code that we place inside its block/closure. The code inside the closure performs updates to our UI elements.

According to Apple's documentation, any code that updates UI elements must be executed on the main queue—which is what we do. The first line within the closure asks our table view to reload since we have assigned items to its data source. The second line hides the web activity indicator spinner, since our request for web content has terminated. Run the app and select on of the two plumbing supply categories. Once the content downloads you should see a table view similar to the one depicted below:


Success! We've successfully displayed the list of inventory items returned by the web API. Notice, however, that we did not use the callback responseHandler( error: nil, items: nil) closure but instead updated our UI in the method from above. We leave this as an exercise for the reader to implement. If you are not sure how to go about implementing this, don't worry, we wrote another method on a different controller that uses the closure to update its UI elements after an update. We do this towards the end of this tutorial.

This project can be found on GitHub.

We're almost done! In the next article, we'll display thumbnail images alongside each of the items in our inventory list above. And then in the final tutorial, we'll build our item description scene for each item in the inventory that displays the full image along with the extended description supplied by our API.

Index
Introduction
Introduction and Overview: From the Back End API to the End User Application

The Web API
Building a RESTful API in PHP, Part 1
Building a RESTful API in PHP, Part 2

The Swift Client App
Networking in Swift: Building the Swift Client, Part 1
Networking in Swift: Building the Swift Client, Part 2
Networking in Swift: Building the Swift Client, Part 3
Networking in Swift: Building the Swift Client, Part 4
Networking in Swift: Building the Swift Client, Part 5


This tutorial was authored by Stefan Agapie, a Senior iOS Software Engineer, and adapted for the present piece. 
Comments (2)

Networking in Swift: Building the Swift Client, Part 2

In the first part of this tutorial segment on networking in Swift, we got our client app up and running with a simple table view controller listing the two inventories supplied by the RESTful API we created in the initial segment of the series. In the present article, we will: 1) set up our data model, 2) create the segues to our inventory views, and 3) process raw responses from the server asynchronously. 

Building the Item Data Model
Our code looks better and becomes easier to manage when we build objects that represent or model the data items that we receive from our web service. To this end, we'll create a file for our individual plumbing supply items using a Cocoa Touch Class template, and then fill it out with the necessary parameters supplied by the API. Open up your Xcode project if you haven't already. In the Xcode Project Navigator panel, right click on the top most group folder. From the menu options that appear, select new file.



You will be presented with a set of options similar to this:


Under iOS, select Source, followed by Cocoa Touch Class, then click Next. Under the secondary menu options: next to the 'Class' field type in PlumbingSupplyItem. For the next field, 'Subclass of', type NSObject, do not create a XIB file (uncheck box), and for the Language portion ensure that Swift is selected:


Click 'Next'. When prompted to select a destination, place the file alongside the other project files. If the file is not automatically loaded into Xcode, then open it from the Project Navigator panel. Now place the following code within the PlumbingSupplyItem class implementation:

As you can see, this code block models the data item passed from the RESTful API we built in the previous segment of this tutorial series, initializing an item id, an item name, an associated image and an item description. It doesn't get much simpler than this.

Segues to the Inventory
With our data model in place, we'll now create our controller class for our inventory, using a table view. This will allow us to mediate between the two inventory table views upon a touch event by the end user.

In the same manner that we created the PlumbingSupplyItem model file, create a new file named PlumbingSupplyInventoryTableViewController using a Cocoa Touch template, and have this file subclass a UITableViewController. From the Object Library, located in the Utilities panel, drag and drop two UITableViewControllers into the main storyboard as depicted below:

Select one of the two view controllers that were just dropped in. Now, in the Identity Inspector, located in the Utilities panel, find the Class field, and type in the name of the class we just created (i.e. PlumbingSupplyInventoryTableViewController) as shown below:

Do the same for the other controller as well, since we are building two separate views of the same kind of object, i.e. items in each of our two inventories.

Note that when you are zoomed out in a storyboard, you can only make selections on the view controllers themselves. To make selections on a controller's internal elements, you have to zoom in. Armed with that information, go ahead and select the cell with the label 'Plumbing Tools'. While holding down the Control key and the left mouse button, drag your mouse over to the top right most view controller and release. During this motion you should see a blue line stretch from our starting location, the table view cell, to our final destination, the view controller.


Upon releasing your mouse button over the controller, a menu will appear. Select the top option that reads: Selection Segue->Show.


Now repeat the same steps for the other cell as well. Your storyboard should look like the following:

What did we just accomplished? We have set up view controller view transition objects known as segues. These segues will respond to a user's touch of a cell. When a cell is pressed, the associated segue will transition to the view controller that it points to.

Preparing Our Segue
Since we will be using a single view controller to display the different inventories of plumbing supplies from the two possible options, namely, Plumbing Tools and Copper Pipes and Fittings, we need to inform the destination view controller which cell was selected. The tip of a segue arrow is said to point to the destination view controller and the tail of the arrow is said to originate from the source view controller. Create a file named PlumbingSupplyCategoriesTableViewController and have this file subclass a UITableViewController.

Now we'll hook it up on the story board. Select the source view controller, i.e. the controller with the two cells. In the Identity Inspector, located in the Utilities panel, where the field reads 'Class', type in the name of the file and class we just created: PlumbingSupplyCategoriesTableViewController. In the main storyboard, select the segue arrow that is associated with the cell labeled 'Plumbing Tools'. From the Attributes Inspector, located under the Utilities panel, locate the Identifier field and type in: plumbingTools.

Do the same for the other segue arrow, but this time provide the Identifier with the name from the title of the other inventory list: copperPipesAndFittings.

We're now going to jump back to our code files. In the PlumbingSupplyInventoryTableViewController.swift file, place the following code (in line 3 below) immediately after the class definition, like so:

Now, over in the PlumbingSupplyCategoriesTableViewController.swift file, replace all the code inside the class PlumbingSupplyCategoriesTableViewController: UITableViewController { . . . } with the following snippet:


This is a system call method that is responsible for notifying the source view controller that a segue is about to be performed. The title that we set in the code above is to the destination table view controller that we segue to. On this destination controller we also set the plumbing inventory url endpoint so that the controller can load the content that was chosen by its corresponding table view cell. Our destination has enough information to load the entire inventory of the selected plumbing category.

Holding Pattern: Activity Indicator
Before we request a list of inventory items, it is customary to run an activity indicator to show the user that our app is in the process of getting some information to display. In the PlumbingSupplyInventoryTableViewController.swift file, below the line of code that reads var inventoryUrlEndpoint : String = "", enter the following line of code:

This line of code creates an instance of UIActivityIndicatorView and makes it private. Now we're going to fill it out inside the viewDidLoad method. In the same file, but inside the method override func viewDidLoad(), add the following lines:


Save all your files and run the application. Once it loads, segue to the two inventory table view controllers. You should see an activity indicator animation as shown here:

Requesting an Inventory
Inside the PlumbingSupplyInventoryTableViewController.swift file, immediately below the webActivityIndicator property, we'll now define another variable that holds a reference to a URL session object that will asynchronously handle our web request. Enter the following line there:
var urlSession = NSURLSession.sharedSession()
At the bottom of the same class, we now define a function that will perform the url session request, parse the request and send us back objects if the success was successful. Here's our first stab:

If you are new to Swift, this function might look rather cryptic. That's because it is! It was no easy task to get this right—a whole lot of Google engineering was required on our end. Lets break it down by parameter:

    'endPointURL : String'
        - 'endPointURL' is an arbitrarily chosen parameter name that we defined in order to identify this parameter, and the 'String' portion requires that the passed in object be of string type.

    'responseHandler'
        - 'responseHandler' is an arbitrarily chosen name for our closure, a.k.a block in Objective-C.

    'error : NSError?, items : Array<PlumbingSuppleyItem>?) → ()'
        - This portion defines a closure.
        - The 'error : NSError?' segment is again an arbitrarily chosen parameter name, and the 'NSError' portion requires that the passed in item be of NSError type.
        - The question mark (?) indicates that the passed in object is optional, meaning that a nil may be provided—in its absence we are required to pass in a none nil value NSError object.
        - 'items : Array<PlumbingSupplyItems>' indicates that the passed in object is a container that holds objects of PlumbingSupplyItem type. 
        - The arrow followed by the parenthesis '→ ()' indicates that this closure returns no values. Instead, objects are passed through the closure's callback parameters.
        - The second arrow followed by parenthesis '→ ()' indicates that the function returns no values.
        - The arrow along with the parenthesis may be omitted for both the function and closure.

Okay, that was a mouthful, but what happens when the view appears on the screen? Let's define it. Right below the viewDidLoad method, we add the following code for our new viewDidAppear method:

This function will be called by the system when the view appears onto the screen. This is good spot to begin requesting inventory items. Notice that we are calling our previously defined requestInventory function. Let's revisit that function now. Replace all the existing code inside the requestInventory method implementation, with the following snippet:


Let's go through this line by line. Line 1 creates an NSURL object from the provided endPointURL string that is referenced by a constant named url; it is essentially a wrapper object for a string formatted URL. This NSURL object is required by our urlSession object that is on the next line of code.

On this line of code, i.e. line 2, we create what is known as a 'data task' for querying our web service. This call spawns an asynchronous operation that communicates with our PHP web service without blocking the main thread. Not blocking the main thread is highly desired if we want our user interface to continue to be responsive—this makes for a better end user experience. Once the communication with our web service completes, the completionHandler closure and all of our code that is contained within this closure is executed. The closure has three parameters: 1) the raw data that comes from our web service, 2) a response object containing the headers from our web service response, or 3) an error object if the request failed.

Line 4 prints the response object inside the Xcode console.

Line 6 is a call to a closure that we defined for our requestInventory function. The parameters provided are an error object if any, and a list of data objects for our inventory items. Currently, we only return nil values. 

Run the application the select both Plumbing Tools and Copper Pipes and Fittings table view cells. You should see the response objects printed for both selections in your Xcode console. The responses in your Xcode console should look similar to this:


Success! Notice that the response object is of type NSHTTPURLResponse. This response object contains information about the requesting url, and the header fields from our web services. Notice the status code of 200; this means that request was completed without issue. You can also print the data object but in its raw form it will not make much sense—try it if you'd like. The communiqué between the host and client is comprised of two parts. The first part is known as the head or header and the second part is known as the body. A typical request or response will contain both of these parts (It's possible to just request the head of a web service response—Google to find out how). The real-world analogy that is often used to describe this is paper mail. The electricity bill, for example, is comprised of two parts as well. The first part is the envelope itself that contains information about its sender—the head. The second part is the contents of the envelope that contains information for the recipient—the body.

JSON Parsing
Now let's get our raw inventory. To do this, we take the response or body of the message and translate it into a container that we can readily read from. In the same function that we've been working on, replace the following line of code that prints out the response, (i.e. println(response), line 4 in the snippet above) with the following:

The first line of code creates a parse error pointer to an object of type NSError, or nil value. On line 2, we call the NSJSONSerialization class method JSONObjectWithData(. . .) and pass to it our raw data response from our web service along with the memory address of the pointer that we created on the first line.

This last method will convert our raw data into a mutable container of type NSDictionary. If the conversion process fails, then this method will assign an error object to the provided memory address with a description or nature of the failure.

The last line of code simply prints our newly created container to the console screen. Save the file then build and run the application. Navigate to one of the inventory endpoints from the table view. In the Xcode console, you should see a similar response to this:


This project can be found on GitHub.

Success! Our application is now querying our tools and supplies API, and returning the inventory response for each of the categories listed on our primary view controller. In the next article in the series, we'll create model objects and then display our inventory item list in our Swift client. Continue to part three on building the Swift client.

Index
Introduction
Introduction and Overview: From the Back End API to the End User Application

The Web API
Building a RESTful API in PHP, Part 1
Building a RESTful API in PHP, Part 2

The Swift Client App
Networking in Swift: Building the Swift Client, Part 1
Networking in Swift: Building the Swift Client, Part 2
Networking in Swift: Building the Swift Client, Part 3
Networking in Swift: Building the Swift Client, Part 4
Networking in Swift: Building the Swift Client, Part 5


This tutorial was authored by Stefan Agapie, a Senior iOS Software Engineer, and adapted for the present piece. 
Comments (2)

Networking in Swift: Building the Swift Client, Part 1

If you've been following along from the beginning of this tutorial series on networking in Swift, you're now running a local web server and have created a simple RESTful API in PHP that serves up the inventory for our hypothetical Super PHPlumbing Bros. project. In this segment of the series, we'll build the iOS Swift client to bring that content to our end user. In the present article, we'll start our Swift project from scratch and create a single view application using a table view controller that will serve as the primary interface to our inventory of plumbing tools and supplies.

In the Beginning . . . 
Download and install the latest version of Xcode, if you haven't already, and fire it up. From the Xcode menu bar (or the Welcome screen) select File->New->Project. A window will appear with various options to choose from. In the left hand panel, under iOS, choose 'Application'. And in the main panel select 'Single View Application'. Then go ahead and click 'Next' as shown below.

On the following window you will be asked to name your application. Name it what ever you like. Under the Language section select Swift from the drop down menu. Make sure that the build is for iPhone in the 'Devices' menu, and then click 'Next' again.

You'll then be prompted to choose a location to house your project and will be given the option to place the project under source control. If you know how to use git for source control, then by all means use it! Otherwise, uncheck the box if it is already checked and click 'Create' to start up the project.

Displaying the Available Services
In our Swift application, we want to present the user with all the available services that our supply shop has to offer. Our custom API provides an interface to our inventory of Plumbing Tools as well as our inventory of Copper Pipes and Fittings. To present these options to the end user we are going to use a table view. So let's jump in. In the navigator panel (the left panel) of Xcode, locate and select the file named Main.storyboard.

Once the main storyboard loads, scroll to the pre-loaded Single View Controller and select it. When properly selected its border will turn blue, as seen here:

As we are going to use a table view, we can safely discard this default view controller. Delete the single View Controller by pressing the delete key on your keyboard, while the controller is selected. In the Utilities Panel on the right side of the Xcode interface, locate the Object Library submenu. Select a Table View Controller, and drag and drop it inside the main storyboard. 

While the new controller is selected, point your mouse toward Xcode's menu bar and select: Editor->Embed In->Navigation Controller. This embeds our selected Table View Controller into, you guessed it, a Navigation Controller.



A Navigation Controller is a stack for managing the presentation order of our view controllers. Select the Table View situated inside the Table View Controller, and then select the Attributes Inspector from the Utilities Panel. Locate the 'Content' field and select 'Static Cells' from its drop down menu.


You should see three cells appear inside the Table View. We only need two such cells, as this is where the user will be presented with the option to browse either the Plumbing Tools inventory or the Copper Pipes and Fittings inventory. Delete the bottom cell by first selecting it, and then pressing the delete key on your keyboard. Now let's name our two primary interfaces. For each of the two remaining cells, select the cell, and then locate the 'Style' field in the Attributes Inspector panel. From the 'Style' drop down menu select 'Basic'.


Both table view cells should now display a label that reads 'Title'. Two clicks in rapid succession on a label will place it into edit mode. Modify the titles so that they read from top to bottom, 'Plumbing Tools' and 'Copper Pipes and Fittings', respectively.

In order for the application to run, we need to specify the initial view controller that we want to load when the application first boots up. In the main storyboard, select the Navigation Controller. Then, in the Attributes Inspector menu, locate the check box that reads, 'Is Initial View Controller' and select it as shown below:

In the top left corner of Xcode make sure that the active scheme is set, and click the play button to build and run the application. Once the iOS simulator starts up, your app should look like this:

This project can be found on GitHub.

Success! We've built the primary view that will be presented to the end user when they open our iOS application. In part two of this segment, we'll begin building our data models. You can find part two in the tutorial on building the Swift client at the link.

Index
Introduction
Introduction and Overview: From the Back End API to the End User Application

The Web API
Building a RESTful API in PHP, Part 1
Building a RESTful API in PHP, Part 2

The Swift Client App
Networking in Swift: Building the Swift Client, Part 1
Networking in Swift: Building the Swift Client, Part 2
Networking in Swift: Building the Swift Client, Part 3
Networking in Swift: Building the Swift Client, Part 4
Networking in Swift: Building the Swift Client, Part 5

This tutorial was authored by Stefan Agapie, a Senior iOS Software Engineer, and adapted for the present piece. 
Comments (1)

Networking in Swift: Building a RESTful API in PHP, Part 2

This is the third post in our tutorial series on networking in Swift. In the introductory article, we provided an overview of the project and set up our local server. In the next piece, we began building out our RESTful API in PHP, which will serve the inventory for our hypothetical Super PHPlumbing Bros. supply company to the custom Swift client we will construct in the final segment of the series.

If you've been following along thus far, you've set up your local server and completed building the first half of the API, which serves the inventory for the shop's supplies. In this article, we will complete our API by adding the necessary code to serve the content of our plumbing tools inventory.

Building the Plumbing Tools Interface
In creating the API for our plumbing tools interface, we will follow pretty much the same series of steps we took while building the plumbing supplies interface, continuing to add the necessary code to the bare bones API we started with in part one. Our skeletal structure now has some real meat on it. Your PlumbingAPI.php file should now look like this:

Jumping In . . .
Once again, let's begin toward the bottom, in the final else if block in the script, the plumbing tools API call, which begins at line 263 above. Replace the echo command in line 264 with the following code block, which contains the relevant response logic:
// build payload //
$response['code'] = 1;
$response['api_version'] = '1.0.0';
$response['status'] = $api_response_code[ $response['code'] ]['HTTP Response'];
   
// if an 'item_id' was provided then return details for that item //
if ( $_GET['item_id'] ) {
    $response['item_id'] = strtoupper($_GET['item_id']);
    $response['data'] = plumbing_tool_item_details(strtoupper($_GET['item_id']));
}
// else return our entire inventory of plumbing tools //
else {
    $response['data'] = plumbing_tools_inventory_without_description();
}
Save your PlumbingAPI.php file and point your browser to this url, http://localhost:8888/v1/PlumbingAPI.php?method=plumbing_tools&format=json. The response will appear as follows in your web browser:
Plumbing Tools Inventory without Descriptions.
Plumbing Tools Inventory.
{ "code": 1, "status": 200, "data": null, "api_version": "1.0.0" }
Now let's add in our plumbing tools inventory. The relevant function begins at line 132 above (function plumbing_tools_inventory()). Replace the echo command with the following associative array:

As in part one, this array constitutes the actual content of the relevant inventory, including item ids, names, image locations, and descriptions. Let's now write the necessary code to serve up our tools inventory without the lengthy descriptions. Appropriately, this will be placed in the plumbing_tools_inventory_without_description() function, located at line 140 in the full script file above. Replace the two lines of placeholder code in that function (lines 141 and 142) with the following snippet:

// pull our entire inventory of plumbing tools //
$inventory = plumbing_tools_inventory();
   
// container for plumbing tools inventory with omitted description //
$inventory_without_details = array();
   
// iterate over the array, duplicate the inventory without descriptions//
foreach ($inventory as $key=>$value) {
    if (is_array($value)) {
        $inventory_item = array();
        foreach ($value as $subkey=>$subvalue) {
            if ( strcasecmp($subkey,'description') != 0 )
                $inventory_item[$subkey] = $subvalue;
        }
        $inventory_without_details[$key] = $inventory_item;
    }
}
return $inventory_without_details;
Save your file and point your browser to this endpoint: http://localhost:8888/v1/PlumbingAPI.php?method=plumbing_tools&format=json. You should see a json response for our entire inventory of plumbing tools.

Now we'll work on serving individual plumbing tools along with their descriptions. Find the plumbing_tools_item_details($item_id) function at line 176 in the script above, and replace the place-holder code in lines 177 and 178 with the following block:
// pull our entire inventory of plumbing tools //
$inventory = plumbing_tools_inventory();
   
// container for item matching the provided item_id //
$inventory_item = array();
   
// iterate through our inventory and find the requested item //
foreach ($inventory as $key=>$value) {
    if (is_array($value) && strcasecmp($value['id'], $item_id) == 0) {
        foreach ($value as $subkey=>$subvalue) {
                $inventory_item[$subkey] = $subvalue;
        }
        break;
    }
}
return $inventory_item;
Save your php file and point your browser to this url:http://localhost:8888/v1/PlumbingAPI.php?method=plumbing_tools&item_id=PT12010&format=json. This is an endpoint to the first item from our json inventory response for plumbing tools. You should see the following response in your browser:
{
    "code": 1,
    "status": 200,
    "data": {
        "id": "PT12010",
        "name": "Plunger.",
        "image": "http://localhost:8888/assets/plunger.png",
        "description": "Super-pliable industrial-rubber cup with tiered ridges forms ultra-tight seal on any size drain. The heavy-duty steel handle allows for maximum pressure forced down drain to source of clog. Designed to work effectively at any angle for hard-to-reach, low-clearance applications."
    },
    "api_version": "1.0.0",
    "item_id": "PT12010"
}
Our API is almost complete! Besides json, you will typically encounter web APIs that support multiple formats. Let's have our API also support XML and HTML responses. Find the deliver_response($format, $api_response) function at line 23 in the API script above, and locate the "XML Response" else if block that begins at line 49. Currently, it only has a place holder comment indicating that this is where we will our XML response logic will live. Add the following code to that block:
// Set HTTP Response Content Type //
header('Content-Type: application/xml; charset=utf-8');
       
// initializing or creating array //
$data = $api_response['data'];

// Format data into an XML response //
$xml = '<?xml version="1.0" encoding="UTF-8" ?>' . "\n";
arrayToXml($data, $xml);
       
// Deliver formatted data //
echo $xml;
This is the next line. Notice that the HTML response logic is in the final else block of the same function. Replace the place-holder "// HTML Response //" comment with the following snippet:
// Set HTTP Response Content Type //
header('Content-Type: text/html; charset=utf-8');

// initializing ro creating array //
$data = $api_response['data'];
       
$payload = '';
$html = '';
if (is_array($data)) {
    arrayToHTML($data, $html);
    $payload = $html;
}
else {
    $payload = $data;
}
       
// Deliver formatted data //
echo $payload;
Finally, we have to fill out the arrayToXml($data, $xml) and arrayToHTML($data, $html) functions referenced in these two snippets. Find the empty arrayToXml function at line 214 in the PHP script above, and add the following to its body:
// wrap XML with $wrap TAG //
if ($wrap != null) {
    $xml .= "<$wrap>\n";
}
// main loop //
foreach ($array as $key=>$value) {
  
    if(is_array($value)) {
        // recursive call //
        arrayToXml($value, $xml,'ITEM');
    } else {
        // set tags in uppercase if needed //
        if ($upper == true) {
              $key = strtoupper($key);
            }
            // append to XML string //
            $xml .= "<$key>" . htmlspecialchars(trim($value)) . "</$key>";
    }
}
// close tag if needed //
if ($wrap != null) {
    $xml .= "</$wrap>\n";
}
Now locate the arrayToHTML function, located at line 224 in our PHP script above. Like its XML counterpart, it is currently empty. Add the following code to the body of the function:
// wrap html with $tag //
if ($tag != null) {
    $html .= "<HTML>\n";
}
// main loop //
foreach ($array as $key=>$value) {
   
    if(is_array($value)) {
        // recursive call //
        arrayToHTML($value, $html,'h1');
    } else {
        // set tags in uppercase if needed //
        if ($upper == true) {
            $key = strtoupper($key);
        }
        // append to XML string //
        $html .= "<$key>" . strtoupper($key) . ' : ' . htmlspecialchars(trim($value)) . "</$key><br>";
    }
}
// close tag if needed //
if ($tag != null) {
    $html .= "</HTML>\n";
}
Save your file and point your browser to this endpoint: http://localhost:8888/v1/PlumbingAPI.php?method=plumbing_tools&item_id=PT12010&format=json . You should see a json response for our entire inventory of plumbing tools. If you type in xml instead of json, in the url, you should see an xml response. Also, typing in html will result in an html response. 

Rejoice! We have completed what is arguably the hardest part of this tutorial!

Clean URLs
Although our URLs up to now were well-formed for the task, you will at times be restricted to use what is known as clean URLs to query a web service. Clean URLs are structured in such a way that the query portion of the URLs that we have been using thus far are instead inserted within the URL path. Simply put, instead of using this url, http://localhost:8888/v1/PlumbingAPI.php?method=plumbing_tools&format=json, to access our inventory of plumbing, we will setup a mechanism that supports this type, http://localhost:8888/api/v1/plumbing_tools.json, of URL as well.

For this, we will add some code to the .htaccess file created in the introductory article to this series. Remember, using .htaccess files is not recommended for production environments, but it will serve us just fine for the purposes of our testing our Swift app. In your usual text editor, type in the following lines of code to the .htaccess file:
# Turn on the rewrite engine
RewriteEngine on

# Rewrite Rules for version 1.0.0 api
# ###################################
# Access to a single inventory item
RewriteRule ^api/v1/([^\/]*)[/]([^\/]*)[//.](html|json|xml) /v1/PlumbingAPI.php?method=$1&item_id=$2&format=$3 [L]
# Access to entire inventory
RewriteRule ^api/v1/([^\/]*)[//.](html|json|xml) /v1/PlumbingAPI.php?method=$1&format=$2 [L]
Any text after a pound character (#) is ignored by the interpreter of this file—it indicates a comment. The first non-comment line of code notifies the interpreter that we will be using rewrite rules. The other lines of code translate our clean url into a standard url that our web service can understand.

The syntax for the rewrite rule is as follows: RewriteRule Pattern Substitution [flags]. For the pattern argument we provided a regular expression (regex) to conduct the translation for us, as we would like to make it as generic as possible—in order to support multiple API signatures. The first RewriteRule interprets the single item with description inventory request for both copper pipes and fittings as well as plumbing tools. The second RewriteRule addresses requests for entire inventories. See this guide (.pdf) for more on regular expressions.

In the same file but just below the our last line, we'll now create the rewrite rules for version two of our API. Here are the rewrite rules for version two of our web service:

# Rewrite Rules for version 2.0.0 api
# ###################################
# Access to a single inventory item
RewriteRule ^api/v2/([^\/]*)[/]([^\/]*)[//.](html|json|xml) /v2/PlumbingAPI.php?method=$1&item_id=$2&format=$3 [L]
# Access to entire inventory
RewriteRule ^api/v2/([^\/]*)[//.](html|json|xml) /v2/PlumbingAPI.php?method=$1&format=$2 [L]
Save your .htaccess file and point your browser to the following url: http://localhost:8888/api/v1/plumbing_tools.json. The web service should respond by sending you the entire inventory of plumbing tools.

This url will also work: http://localhost:8888/api/v1/plumbing_tools/json. You can replace the json path with any other supported format.

Now point your browser here: http://localhost:8888/api/v1/plumbing_tools/pt12010.json. PT12010 is an item id value. This last web service request will respond by transmitting the relevant information along with description for the item matching the provided id.


Versioning
Placing web services with expanded or modified functionality into a separate folder is arguably the simplest versioning scheme to implement. There are other more complicated, and necessary, versioning schemes in use today. In our scheme, folder v1 is the earliest web service and v2 is the most recent. A number of arguments speak in favor of this implementation: there is no ambiguity about which web service version you are talking to, backward compatibility is maintained and you don't have to worry about creating dependency issues because each versioning folder contains the complete set of services.


Moving Forward
With that, we have completed our Super PHPlumbing Bros inventory API. Next week, we will move on to the final segment of this tutorial series and begin building the Swift client application that we will use to query the API and serve the content up to the end user. As always, comments, questions and suggestions are welcome below.



This project can be found on GitHub.

Index
Introduction
Introduction and Overview: From the Back End API to the End User Application

The Web API
Building a RESTful API in PHP, Part 1
Building a RESTful API in PHP, Part 2

The Swift Client App
Networking in Swift: Building the Swift Client, Part 1
Networking in Swift: Building the Swift Client, Part 2
Networking in Swift: Building the Swift Client, Part 3
Networking in Swift: Building the Swift Client, Part 4
Networking in Swift: Building the Swift Client, Part 5


This tutorial was authored by Stefan Agapie, a Senior iOS Software Engineer, and adapted for the present piece.
Comments

Networking in Swift: Building a RESTful API in PHP, Part 1

This is the second post in our tutorial series on networking in Swift. If you followed along in the introductory article, you have installed MAMP on your local machine, created an .htaccess file and set up the basic file structure for the project. In this tutorial, we'll begin building the API for our Super PHPlumbing Bros web service.

This RESTful API in PHP will serve content to the Swift-based iOS client application we'll create in the final part of the series. Our API will perform five distinct tasks when queried. It will provide: 1) inventory items response logic for our Plumbing Tools; 2) inventory items response logic for Plumbing Supplies; 3) inventory item response logic for Plumbing Tool with Description; 4) Inventory item response logic for Plumbing Supply with Description; 5) Error response logic.

In this article, we will cover the structure of our API queries, provide a simple bare bones interface for the service, and then build the first half of our custom API to serve up our plumbing supplies inventory.

API Queries
Our application will communicate with the web api through a simple url scheme. If you are not familiar with url schemes, take a brief detour through the linked Wikipedia page to learn about how they work (simply memorizing the components of a url scheme outright will save you lots of needless lookups later).

Our first stab at a url scheme looks crude. Here is the URL scheme that we will use to access our entire inventory of plumbing tools: http://localhost:8888/v1/PlumbingAPI.php?method=copper_pipes_and_fittings&format=json.

Let's take a closer look at this scheme. Any text in a URL that comes after the question mark (?) is known as the URL query component. Each key/value pair that follows is logically separated by an ampersand (&). In this example the query string contains two key/value pairs. These key/value pairs will get passed along to our PlumbingAPI.php script via an associative array known as $_GET[]. Within our PHP script we will access the values for the 'method' and 'format' keys as follows: $_GET['method'] and $_GET['format'] would return 'copper_pipes_and_fittings' and 'json', respectively, in the crude example above. We use these values to determine what was requested of our API.

A Bare Bones API
Let's get down to it. Using your text editor, open PlumbingAPI.php for both versioning folders, v1 and v2. Until further noted, we'll be entering the same code in both versions. For the skeletal structure of our API, we are going to adapt the code from Mark Roland's helpful tutorial on "How to Build a RESTful API Web Service in PHP." We'll explain each component as we add flesh to our bare-bones script. Here's a Gist of the script:


After reading through the code, copy it into the PlumbingAPI.php file in your v1 folder. Using the URL scheme from above, point your web browser at http://localhost:8888/v1/PlumbingAPI.php?method=copper_pipes_and_fittings&format=json, and you will see the API's response to the given method and format:

Simple API call to bare bones script


If you now navigate to http://localhost:8888/v1/PlumbingAPI.php?method=plumbing_tools&format=json, you'll see the response from the plumbing_tools method:

Second API call to bare bones script
  
If this is not working for you, then go back and make sure that you followed all the steps. If you do see a response in your web browser, then congratulations! You've successfully built and deployed your locally hosted web service. The various responses from our api are made possible by the following conditional code structure, from line 120 to the end of the file above:
// Copper Pipes and Fittings API //
if( strcasecmp($_GET['method'],'copper_pipes_and_fittings') == 0){
    echo 'Copper Pipes and Fittings API Call. <br>';
}

// Plumbing Tools API //
else if( strcasecmp($_GET['method'],'plumbing_tools') == 0){
    echo 'Plumbing Tools API Call. <br>';
}

// ** Deliver Response ** //
// Return Response to browser //
deliver_response($_GET['format'], $response);
With the exception of the function definitions, our script is executed from top to bottom. Notice the conditional if else if structure here. In our first API call we passed in the value 'copper_pipes_and_fittings' for the 'method' key. Recall that the parameters of a query string are passed in to the $_GET[] global array, which we read from in our first conditional if check. Since it evaluates to true in the first API call, we fall in that conditional block and therefore echo "Copper Pipes and Fittings API Call", followed by the function call: deliver_response($_GET['format'], $response). This last function call is what prints out the second line in the browser.

In our second api call, we passed in the value 'plumbing_tools' for the 'method' key in the URL. With this query, we fell into the conditional else-if check above. This gave us our alternate response. That's all there is to it!

Moving forward, we'll build on top of this primitive structure of conditional checks followed with a response using the echo call.  For explanations of built-in methods such as  strcasecmp() and echo, check out php.net and search for those calls to get documentation along with code samples on how to use them.

Building the Supplies Interface
We'll now begin building out the control flow for the various tasks our API will perform. In the first if conditional control flow replace the code at line 122 (echo 'Copper Pipes and Fittings API Call. <br>';) with the following:
// build payload //
$response['code'] = 1;
$response['api_version'] = '1.0.0';
$response['status'] = $api_response_code[ $response['code'] ]['HTTP Response'];
   
// if an 'item_id' was provided then return details for that item //
if ( $_GET['item_id'] ) {
    $response['item_id'] = strtoupper($_GET['item_id']);
    $response['data'] = copper_pipe_or_fitting_item_details(strtoupper($_GET['item_id']));
}
// else return our entire inventory of copper pipes and fittings //
else {
    $response['data'] = copper_pipes_and_fittings_inventory_without_description();
}
Save your PlumbingAPI.php file and point your browser to this URL: http://localhost:8888/v1/PlumbingAPI.php?method=copper_pipes_and_fittings&format=json. The response will appear as follows in your web browser:
Copper Pipes and Fittings Inventory without Descriptions.
Copper Pipes and Fittings Inventory.
Delivering Response. $api_response = Array, format = json
Your are seeing this response because our first if check did not fall through as we did not provide an 'item_id' key with an associated value pair as parameters in the query part of our URL. In other words, a parameter with this format, '&item_id=<some item id>', was not appended to the above URL. This resulted in our conditional control flow to fall through the else path. In this else block we call a method that we defined earlier: copper_pipes_and_fittings_inventory_without_description(). In our definition of this method, notice that we call another method: copper_pipes_and_fittings_inventory(). This last method is responsible for fetching our entire inventory of copper pipes and fittings along with all item details. Go to this method, found in lines 27 -33 above, and replace line 32 (echo 'Copper Pipes and Fittings Inventory. <br>';)<code> with the following:


This is an associative array of sub-arrays. Each sub-array contains all the information of one inventory item. There are twelve items in our hypothetical Copper Pipes and Fittings category, the information for which was cobbled together from online sources. In a real world scenario, this or a similar method would normally pull this data from a data store like a database. But for the sake of brevity we will skip this part. Now go to where we defined the method copper_pipes_and_fittings_inventory_without_description() (line 56 in the bare bones files above), and replace lines 57 and 58 with the following: 
return copper_pipes_and_fittings_inventory();
For now we'll simply return our entire inventory with descriptions. We will revisit this method later and write code to omit item descriptions. Now navigate to our response delivery function (function deliver_response($format, $api_response)), line 23 in the bare bones code, and replace its echo command in line 24 with the following:


The response to our API query gets processed here. If a parameter of 'format=json' is provided in the query part of the URL, then our script would fall through our first if check. This parameter informs our API that one of three available formatted responses was requested. We support three formats in this example: json, xml and html. 

Let's now write the code to process json format requests. In the first conditional if-check block (line 14) replace the comment (// JSON Response //) with the following code:
// Set HTTP Response Content Type //
header('Content-Type: application/json; charset=utf-8');

// Format data into a JSON response //
$json_response = json_encode($api_response, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);

// Deliver formatted data //
echo $json_response;
Save your PlumbingAPI.php file and point your browser to this url, http://localhost:8888/v1/PlumbingAPI.php?method=copper_pipes_and_fittings&format=json. The response will appear as follows in your web browser:
{
    "code": 1,
    "status": 200,
    "data": [
        {
            "id": "CP12010",
            "name": "1 inch copper pipe.",
            "image": "http://localhost:8888/assets/1_inch_copper_pipe.png",
            "description": "1 in. x 10 ft. Copper Type M Hard Temper Straight Pipe for a multitude of plumbing and heating purposes. It is NSF and ANSI Standard 61 certified. Made of hard-temper ASTM - B88 copper. For general plumbing and heating purposes. Alloy C12200 (DHP) meets industry standards and is NSF and ANSI Standard 61 certified. Meets or exceeds industry standards to deliver a high quality flow product. Plumbing and mechanical codes govern what types of products may be used for applications. Local codes should always be consulted for minimum requirements"
        },
        {
            "id": "CP12020",
            "name": "1 1/4 inch copper pipe.",
            "image": "http://localhost:8888/assets/1_1_4_inch_copper_pipe.png",
            "description": "1 1/4 in. x 10 ft. Copper Type M Hard Temper Straight Pipe for a multitude of plumbing and heating purposes. It is NSF and ANSI Standard 61 certified. Made of hard-temper ASTM - B88 copper. For general plumbing and heating purposes. Alloy C12200 (DHP) meets industry standards and is NSF and ANSI Standard 61 certified. Meets or exceeds industry standards to deliver a high quality flow product. Plumbing and mechanical codes govern what types of products may be used for applications. Local codes should always be consulted for minimum requirements"
        },
    .
    .
    .
    .
        {
            "id": "CP14040",
            "name": "1 1/2 inch copper elbow fitting.",
            "image": "http://localhost:8888/assets/1_1_2_inch_copper_elbow_fitting.png",
            "description": "1 1/3 in. Copper Type M Hard Temper Straight Pipe for a multitude of plumbing and heating purposes. It is NSF and ANSI Standard 61 certified. Made of hard-temper ASTM - B88 copper. For general plumbing and heating purposes. Alloy C12200 (DHP) meets industry standards and is NSF and ANSI Standard 61 certified. Meets or exceeds industry standards to deliver a high quality flow product. Plumbing and mechanical codes govern what types of products may be used for applications. Local codes should always be consulted for minimum requirements"
        }
    ],
    "api_version": "1.0.0"
}
The vertical ellipses indicate that we trimmed the actual response. You should see a lot more data in your browser. The problem with this response is that the copper pipes and fittings inventory response contains too much data. In our next step we'll trim the response so that item descriptions are omitted. 

It is not good practice to submit details of items when requesting them in bulk. In a real-world scenario, internet access is often spotty and unreliable. And serving up too much data could negatively impact your users' experience. And since users are often not aware that your application is not to blame for a given issue, but rather their connectivity to the network, they will associate this bad experience with your application. So, in an effort to mitigate connectivity issues, we should always prefer to send the least amount of data as possible over a network. Also, it is very unlikely that you can fit all this data for one item onto a screen when presenting the user with a list of items.

To omit item details, navigate to where we defined the method copper_pipes_and_fittings_inventory_without_description(), and replace our return command (return copper_pipes_and_fittings_inventory();) with this chunk of code:
    // pull our entire inventory of copper pipes and fittings //
    $inventory = copper_pipes_and_fittings_inventory();
   
    // container for inventory minus descriptions//
    $inventory_without_details = array();
   
    // iterate through inventory and duplicate all attributes except descriptions //
    foreach ($inventory as $key=>$value) {
        if (is_array($value)) {
            $inventory_item = array();
            foreach ($value as $subkey=>$subvalue) {
                if ( strcasecmp($subkey,'description') != 0 )
                    $inventory_item[$subkey] = $subvalue;
            }
            $inventory_without_details[$key] = $inventory_item;
        }
    }
    return $inventory_without_details;    
This code is straight forward. It iterates through the json objects and all the items into another container with the exception of key value pairs that are associated with a key name of 'description.' Save your PlumbingAPI.php file and point your browser to this url, http://localhost:8888/v1/PlumbingAPI.php?method=copper_pipes_and_fittings&format=json. The response will appear as follows in your web browser:
{
    "code": 1,
    "status": 200,
    "data": [
        {
            "id": "CP12010",
            "name": "1 inch copper pipe.",
            "image": "http://localhost:8888/assets/1_inch_copper_pipe.png"
        },
        {
            "id": "CP12020",
            "name": "1 1/4 inch copper pipe.",
            "image": "http://localhost:8888/assets/1_1_4_inch_copper_pipe.png"
        },
          .
    .
    .
    .
        {
            "id": "CP14040",
            "name": "1 1/2 inch copper elbow fitting.",
            "image": "http://localhost:8888/assets/1_1_2_inch_copper_elbow_fitting.png"
        }
    ],
    "api_version": "1.0.0"
}
Again, the vertical ellipses indicate that we trimmed the actual response. Notice that the descriptions have been omitted from the response. 

We will now write code to serve an individual copper pipe or fitting with a description. Find where the method function copper_pipe_or_fitting_item_details($item_id) is defined (line 66 in our bare bones API) and replace the two lines filling out the function (i.e. 67 and 68), with the following:
// pull our entire inventory of copper pipes and fittings //
$inventory = copper_pipes_and_fittings_inventory();
   
// container for item matching the provided item_id //
$inventory_item = array();
   
// iterate through our inventory and find the requested item //
foreach ($inventory as $key=>$value) {
    if (is_array($value) && strcasecmp($value['id'], $item_id) == 0) {
        foreach ($value as $subkey=>$subvalue) {
                $inventory_item[$subkey] = $subvalue;
        }
        break;
    }
}
return $inventory_item;
Save your php file and point your browser to this URL: http://localhost:8888/v1/PlumbingAPI.php?method=copper_pipes_and_fittings&item_id=CP12010&format=json. This is an endpoint to the first item from our json inventory response above. You should see the response below:
{
    "code": 1,
    "status": 200,
    "data": {
        "id": "CP12010",
        "name": "1 inch copper pipe.",
        "image": "http://localhost:8888/assets/1_inch_copper_pipe.png",
        "description": "1 in. x 10 ft. Copper Type M Hard Temper Straight Pipe for a multitude of plumbing and heating purposes. It is NSF and ANSI Standard 61 certified. Made of hard-temper ASTM - B88 copper. For general plumbing and heating purposes. Alloy C12200 (DHP) meets industry standards and is NSF and ANSI Standard 61 certified. Meets or exceeds industry standards to deliver a high quality flow product. Plumbing and mechanical codes govern what types of products may be used for applications. Local codes should always be consulted for minimum requirements"
    },
    "api_version": "1.0.0",
    "item_id": "CP12010"
}

Congratulations! We have completed the first half of our web API, serving up content for our copper pipes and fittings inventory. In the next article in the series, we'll complete the API to serve up our inventory of plumbing tools, and then begin building our Swift application to bring that content to our end user. Follow the line for part two on building a RESTful API in PHP.

This project can be found on GitHub.

As always, comments, questions, and suggestions are welcome below!

Index
Introduction
Introduction and Overview: From the Back End API to the End User Application

The Web API
Building a RESTful API in PHP, Part 1
Building a RESTful API in PHP, Part 2

The Swift Client App
Networking in Swift: Building the Swift Client, Part 1
Networking in Swift: Building the Swift Client, Part 2
Networking in Swift: Building the Swift Client, Part 3
Networking in Swift: Building the Swift Client, Part 4
Networking in Swift: Building the Swift Client, Part 5


This tutorial was authored by Stefan Agapie, a Senior iOS Software Engineer, and adapted for the present piece. 
Comments (3)

Networking in Swift: From the Backend API to the End User App

Introduction
In this tutorial series, we will create an iOS application that will leverage Swift's networking layer to query a custom-built web service. First, we'll build a RESTful API in PHP from the bottom up and host it on our local machine. Then we'll craft an iOS Swift application to consume the content provided by the service, and present it to the end user in a collection view. The series is intended for people who have some degree of programming experience, but who have not yet obtained much practical knowhow on building an everyday, real-world, user-facing, mobile application. 

A typical use case for mobile applications requires the consumption of content that is hosted on a web server. For successful mobile app development, this means that you not only need to know how to build an application that consumes web content, but also to have a high level understanding (at the very least!) of how a web service actually delivers content to your mobile application.

This is important because you will encounter network related errors during your development cycle. And if you don't have at least a basic understanding of the web service that your are trying to communicate with, then you cannot be sure where the errors are originating from. In addition, you will likely also be asked, at work or by your own clients, to begin writing a mobile application that relies on a web service that has not been built yet! (This actually happens way too often!) In such cases, you can write your own temporary web service that delivers mock data to your application, if you know how to build one. Although there are other ways of delivering such mock data, this can be just as useful. 

In this article, we'll provide an overview of the project, and then work through the preliminary steps for running the web service on our local machine. In the following articles, we'll build out the PHP script that will execute the API, and finally construct our Swift application to query the service and return the relevant data to the end user.

The ABCs of APIs
What is an API and how will our Swift application interface with it? API stands for Application Programming Interface. A simple web search for 'API' will return many definitions with various types of descriptions and creative examples. I like to think of an API as a real object. 
Source

Since the internet is a series of pipes and tubes, our API will provide an interface to a plumbing supply inventory. Let's call our API the Mario Interface. Mario works at the front desk of a plumbing supply house called Super PHPlumbing Bros Inc. Mr. Swift is a plumber who needs some supplies to rescue a local potentate's daughter from the clutches of an invading warlord.

Mr. Swift finds PHPlumbing and walks up to the counter where he encounters Mario. Mr. Swift tells Mario that he would like some piping, mushrooms and a wrench. Mario says, "No problem, but first I need you to know exactly what you need," and hands Mr. Swift two forms.

Each form is titled with the company's name. Below the title, there are several check boxes, but only one may be checked per form. The relevant check boxes are: Piping/Fittings and Plumbing Tools. Below that is a description field for the requested items along with their quantity. 

Once completed, Mr. Swift hands the forms to Mario, who then passes them along to his employees, local Toads from the Mushroom Kingdom, who are tasked to assist him. The Toads find the relevant items, bring them out and place them on the counter. 

If at any point during this process there was a problem retrieving Mr. Swift's supplies, the Toads are responsible for reporting these errors up the chain of command, from the assistants up to Mario and terminating at Mr. Swift.

In our analogy, Mr. Swift is the client (our iOS application) in need of content or plumbing supplies. Super PHPlumbing Bros Inc. is the store or website that has the supplies or content that Mr. Swift is looking for. The form for getting supplies is the actual url (location of content) that is used to find and retrieve the content. And Mario, along with the Toads, comprise the API. 

APIs, and people like Mario, are needed to maintain a system of flow control structures that are necessary to efficiently run the business logic of the operation. Can you imagine a plumbing supply house that had no control structures like forms and employees to manage its everyday workflow? The princess would be doomed.

In this tutorial series, we'll construct a RESTful API in PHP to serve up an inventory of plumbing tools and supplies, and then build a custom Swift app to interface with the API and serve that inventory to the end user. For now, let's get our local server up and running. 

Setting Up the Local Server
Unfortunately, the PHP file that will serve our API will not execute on its own. A service is required to interpret and execute our PHP script. We therefore need to set up a place on our local machine to host our Super PHPlumbing Bros. supply house. One of the easiest ways to get a server up and running on a Mac is with MAMP. Once you've downloaded MAMP, you can run the package by double clicking it.

After the package mounts, follow the instructions to install the software. 

Once installed, navigate to your Applications folder and start MAMP. You will be prompted with several initialization screens. Once MAMP is installed, start the server my clicking the START button in the top right corner of the application window. 


The tiny box to the right of the word Apache should turn green if everything went smoothly. This means that your server is up and running! Now start a new session of Safari, and in the url field type the following address: http://localhost:8888You should see a similar screen to the following, which indicates that all is in working order:

.htaccess
A .htaccess file provides directory level configuration on how a web server handles requests to resources that are in the same directory as the .htaccess file itself. Note that using .htaccess is discouraged for production environments, but for the purposes of our tutorial, it should work just fine. Using your favorite text editor, create a new file and name it .htaccess. In the screen capture above, notice the directory path next to the text, “Document root:”. Mine reads: "Document root: /Applications/MAMP/htdocs." This is where your PHP file, along with all related resources will live. Place your .htaccess file in this folder.

Remember, any file name that begins with a period “.” is a system file and is hidden by default. To view hidden files, you can use the "ls -a" command in a terminal. To view hidden files in Finder, you can follow the instructions here.

File Structure 
Navigate to the folder that contains your .htaccess file. For me, it's /Applications/MAMP/htdocs, and create three folders with the following names: v1, v2, assets. More on these folders later, but for now, your folder structure should more or less look like the following:

Using your text editor create a new file and call it PlumbingAPI.php. This file models the Mario Interface, our counter guy. Place a single copy in folder v1 and v2. The v1 and v2 folder will be used for version control. The earlier versions of an API would typically reside in folders with a smaller number while the most recent API edition would live in the folder with the largest number.

Moving Forward  
With that, we're all set to go! In the next segment of the tutorial we'll build our RESTful API in PHP, so let's take the plunge. Or, if you want to skip ahead, follow the link to the tutorial segment on building our Swift client application.


Comments (3)

Hack Lab Intro: How to Set up a Home Hacking and Security Testing Lab

Introduction

This series of articles comprises an introductory tutorial on how to set up a home lab to experiment with common hacking and information security testing tools. Our setup will  allow us to explore the sorts of computer and network vulnerabilities that can be encountered on the internet, and to test the security of our own home computer network and networked devices, all from within an isolated and secure working environment. The series is geared toward individuals who have little or no prior experience with virtualization software or common hacking and security testing tools, but are interested in exploring network and computer security.

Over the course of the tutorial series, we will create two separate network configurations. The first will be a completely virtual environment populated by two virtual guest systems running inside a single host computer. This requires nothing more than an internet connection for the necessary downloads, and a computer with relatively modest RAM and disk resources.

The second configuration will be an everyday local area network of the sort that can be found in many homes, but which is isolated from the internet and where we can strictly control and monitor all network traffic. This setup is slightly more involved in terms of hardware than the first, requiring also a spare router.

Our monitoring and attack system in both configurations will be an instance of a Kali Linux virtual machine running inside an installation of the VirtualBox software package on our primary computer. Kali is a Linux operating system distribution intended for security testing and digital forensics.

In the first completely virtual network environment, our victim will be an instance of  Metasploitable2, a virtual machine that exhibits vulnerabilities that can be found on  everyday computer systems and software configurations. As noted at Offensive Security, "Metasploitable is an intentionally vulnerable Linux virtual machine. This VM can be used to conduct security training, test security tools, and practice common penetration testing techniques."

In the second network configuration, we will use the Kali Linux virtual machine to compromise an everyday local area network router of the sort that can be found on many home networks, in order to demonstrate just how easy it can be to steal login credentials  passed from another computer on the network.

The tutorial is broken down into four parts:
  • Part 1 covers the installation of VirtualBox and provides a walk through of a full installation of a Kali virtual machine on your primary lab computer. Along the way, we'll take a short detour on how to quickly run live Kali sessions without a full installation of the machine.
  • Part 4 provides details on setting up our second network configuration, which models an everyday home local area network. With the attack machine, we'll conduct a simple man-in-the-middle attack against the network's router, and demonstrate a serious security vulnerability by stealing login credentials sent to it from the victim machine, in this case, the host computer. 
Comments (16)

Hack Lab Part 4: Compromising a Home Router on a Local Area Network

This is part four in our tutorial series on how to set up a home hacking and security testing lab. In part three, we set up a completely virtual network inside VirtualBox in order to use Kali to test the (in)security of the Metasploitable2 virtual machine. In the present article, we'll set up a local area network similar to one you might find in any home, and then walk through a man-in-the-middle attack against an everyday router.

Here's our hypothetical scenario: there is a malicious individual on a local area network listening in on the network traffic (sniffing it, as they say) using ARP poisoning in an attempt to steal login credentials from the router's administrator so as to hijack the device, and by extension, the network. In this scenario, Kali will once again function as the attacker but the host computer will be the victim.

This configuration will require a router specifically for the purpose of hosting our home lab's local area network. This could also be accomplished virtually, but having the external network will allow us to test the security of other external networked devices moving forward.

Configuring the Local Area Network
For the present test, which was successful, I picked up one of those ubiquitous Netgear WNR 2000 series home routers at a local flea market for ten dollars. You might even have an old router just lying around collecting dust. Plug the router in, turn it on, and configure it as desired. An online manual for this router stated that once you have connected your computer to it, you can navigate to the URL routerlogin.net or the device's ip address in a web browser to log in for administrative purposes. They further provided the factory default login credentials: 'admin' for the login name, and 'password' for the password. The first thing I did upon logging was to change the password using the router's so-called "Smart Wizard".

I prefer to hook up devices to the lab router through ethernet, and turn off wireless networking in the router when I'm feeling paranoid. Log into the router, and adjust settings as necessary. It should have DHCP, to provide ip addresses to hosts on the network. Keep it completely isolated from your actual home LAN that is connected to the internet, at the very least because connecting a second dhcp server to your main home network would cause a fair amount of chaos. We'll soon see whether this sort of interaction with the router is secure in any way. (Spoiler alert: in the case of the WNR 2000, it is not.)

Once your router is setup, open the Network settings in your Kali machine and change the attachment from the internal network to bridged mode, and attach it to the appropriate interface. (People who are more comfortable with managing multiple interfaces on Linux could just add a second adapter and switch between the two inside Kali.)  Under the Advanced section of Kali's Network settings, notice the drop down menu for Promiscuous Mode. This setting is important for our test. There are three options here: Deny, Allow VMs, and Allow All. Set it to Deny. This means that Kali will not be privy to any traffic directly to or from its host machine or other VMs that may be on the network.


Why have we set Promiscuous Mode to Deny?

Abstinence-Only Networking and the IP Stack
When Kali is running in bridged networking mode, so as far as the rest of the hosts on the network are concerned, it is a completely independent host. But it's not, it's a virtual machine, it shares its network interface with its host computer, and by extension with any other VMs that might also access that interface.

If we set promiscuous mode to Allow All, the Kali machine will pick up all traffic going over the network interface, to which it has access because it is itself bridged over this interface. That obviously includes the given network's traffic sent to and from the host computer on which the virtual machine is running, as well as any other virtual machines it might be running on that interface. If the host computer pings the router, Kali will pick up the traffic.

When promiscuous mode is set to Deny, on the other hand, Kali networks with the host computer (and any other virtual machines that might be on the network) as if they were all on completely separate physical devices. If the host computer pings the router, Kali will not pick up the traffic.

If there is a secondary computer on the network, even if Kali is in promiscuous mode, it will not be able to capture a ping from that computer to the router, or any other such traffic between them, for that matter, such as an http session.  

When we run the man-in-the-middle attack against the router and the host machine, however, we'll see that we can pick up traffic between them. One might wonder whether this is a true man-in-the-middle attack, because as we already know, the Kali guest and the host computer share an interface. Kali already has access to the host machine's traffic. Setting up the sniffer is basically just enabling promiscuous mode on the adapter setting.

However, we are not conducting a physical layer attack. ARP poisoning is conducted between the link layer and the network layer of the IP stack. This could be demonstrated with a secondary host on the network. An ARP attack by Kali against the secondary computer will still work even though Kali does not share a physical network interface with the victim, and could not detect such traffic even in promiscuous mode.


Reconnaissance and Scanning the Network
There should now be three hosts on the lab LAN: 1) the router, 2) the host computer (our victim), and 3) the Kali virtual machine (our attacker). Let's begin by conducting some passive monitoring of the network traffic.

Open up Wireshark on your Kali instance and conduct a live capture, to see what kind of traffic you can pick up on this network. (See part two in the series for info on how to properly configure Wireshark to conduct a live capture, if you haven't already.) Let the scan run for about half an hour. My capture picked up:
  • SSDP broadcasts from the router, alerting hosts as to its existence
  • ARP broadcasts from the victim computer and the Kali host machine, seeking out the router's hardware address from its ip address.
  • DNS requests to external websites for services running on Kali and the host machine, these are obviously unresolvable, since the network is not connected to the internet. (I would also like to shut down these services later if they are not system critical, as I don't like the idea of my machines contacting random services on the internet without my say so.)
Nothing really seems out of the ordinary here, so let's run a scan of the network. Here's the topology graphic produced by Zenmap from a default nmap scan of my lab network:


The router is at 192.168.1.1, the primary host computer is at 192.168.1.2 and the Kali machine is at 192.168.1.5. As you can see, Zenmap's color coding indicates that there may be some vulnerabilities in the router.

This scan discovered three open ports on the router, and found no open ports on any of the other hosts. Ports 23 (telnet) and 80 (HTTP) were found open by default on the router. We would expect port 80 to be open since you can log into the router with a web browser for administrative purposes. It seems a bit odd that the telnet port is open as well, as it is unlikely anyone today would be telnetting into the router on their home network. This is a security vulnerability, but, fortunately, this router does not actually allow simple telnet access to its administrative interface. Any basic attempts to connect to it via telnet are rejected, which makes one wonder why it is open to begin with.

Now let's attempt to systematically determine what traffic on the network the Kali instance is able to capture. All packets sent from or to the Kali VM will be captured in Wireshark, since the capture is running on that system: ex. ping requests to the router from Kali, ping requests to Kali from the host computer, HTTP traffic if you use a Kali web browser to navigate to the router's admin page, and so on.

As noted above, if your Kali virtual machine's network settings were in promiscuous mode, Wireshark would also capture any packets directly sent to or from the host computer. But this is not the case here as we have set promiscuous mode to Deny.

With promiscuous mode set to Deny, if you ping Kali from the host computer, the Wireshark capture will pick up all of these packets, since they are being sent directly to and from the Kali machine. However, if you ping the router from the host computer, none of the request or reply packets will be picked up by your Wireshark capture in Kali, nor will any other such traffic. For example, if you use a web browser on the host computer to navigate to the router's login interface, the capture will not detect any of this traffic.

With this observation, we have acquired our target. What we would like to do is two-fold: 1) pick up any direct traffic at all between the host computer and the router, 2) pick up any sensitive traffic (and any correspondingly sensitive information) sent between these devices.

Running a Man-in-the-Middle Attack with Ettercap
To compromise the traffic between the host computer and the router, we are going to use a program called Ettercap. As noted in its manual page, Ettercap is a "multi-purpose sniffer/content filter for man in the middle attacks." Ettercap can be run from the command line or through its graphical interface. To launch the graphical interface, type the following command into a terminal: sudo ettercap -G. The Ettercap graphical interface:


However, we're going to run Ettercap from the command line, as this conserves more resources on the host machine since it does not require excess RAM. Our plan is to use arp poisoning to capture traffic between the victim and the router. Reading through the Ettercap manual pages allows us to determine that we can use the following command to conduct our attack:
sudo ettercap -i eth0 -T -M arp /192.168.1.1/ /192.168.1.2/
Before we run the command, let's take a closer look at what's going on here: 
  1. sudo runs the command as a privileged user. This is necessary for Ettercap to conduct the packet capture.
  2. ettercap tells the shell to run the Ettercap program.
  3. -i eth0 tells Ettercap to run the capture on the eth0 interface inside Kali. This may be different for you depending on how you have your network adapters set up. If you try to run arp poisoning on an interface that is not enabled, Ettercap will likely complain that "No such device exists". If you run it on an interface that is enabled, but not connected to a network, Ettercap will complain that "ARP poisoning needs a non empty hosts list".
  4. -Tq tells Ettercap to run in text mode (-T), meaning it will print out any text characters found in its capture.
  5. -M tells Ettercap to run a man-in-the-middle attack.
  6. arp specifies that Ettercap should run an ARP poisoning man-in-the-middle attack.
  7. /192.168.1.1/ and /192.168.1.2/ specifies the two specific hosts we want to target.
Let's see if we can capture any traffic between the victim and the router. Start a Wireshark live capture on Kali. Now ping the router from your host computer, and just let it ride (ex. ping 192.168.1.1). If you are running in non-promiscuous mode, Kali will not pick up any of the ping requests and replies between the victim and the router.

Now run the Ettercap command above (with any necessary substitutions for your own network configuration) from a terminal in Kali. If successful, the Wireshark capture should now begin picking up the echo requests and replies between the victim and the router (as well as any other packets passing between them), and Ettercap will print to the terminal any text picked up in those packets. You can now stop the live capture, quit Ettercap and stop the ping from the host machine to analyze the results. 

The next question is whether we can pick up any sensitive information, such as login credentials, passing between the victim and the router. For this, we'll slightly modify our Ettercap command:
sudo ettercap -i eth0 -Tq -M arp /192.168.1.1/ /192.168.1.2/
As you can see, everything is the same here, except I've added a q to the -T option. This tells Ettercap to run in quiet mode, which means that it will not print any and all text it picks up in captured packets, but rather only text of potential significance, such as login credentials. For our test, we want to see if we can capture the victim's credentials when logging into the router.

Start a new Wireshark live capture in Kali. Run the Ettercap quiet mode command in a terminal. Now, on the host computer, use a web browser to navigate to the router and log in to the administrative interface. Here's the result in Ettercap when I ran this attack against the WNR 2000 router:


As you can see, Ettercap picked up the victim's user name (here: 'admin') as well as the password (here: 'supersecretstring'). Moreover, the router passed the login credentials over the network in plaintext six times when the victim logged in to the device! Obviously, 'supersecretstring' is not a very good password, but in the present case it doesn't really  matter how secure the password is, since the router passes it over the network in plaintext.  
The login credentials can also be found in the Wireshark packet capture run alongside the Ettercap ARP poisoning attack. My Wireshark capture picked up a lot of packets, so let's do a search for 'credentials':


Inspecting the first packet returned from this search, reveals the following under the HTTP section of the packet view:


And there they are, the user name and password, conveniently located under the authorization heading: 'admin:supersecretstring'.   In fact, it turns out the login credentials are sent in plaintext every time the victim loads another page in the router web interface!

The victim's router admin account has now been compromised. After the victim logs out of the router, the attacker can immediately log in with admin privileges, change the password and lock out the victim, or make changes to the system's settings, turning it off, etc. The "Smart Wizard" on the WNR 2000 router isn't so smart or wizardly after all!

Now the question is: does this attack work against the router on your home lab? Let us know in the comments.

Reflecting on this attack, one would probably ask: Can't we detect this attack as it was going on? Does it not create a whole load of excess traffic on the network? Wouldn't it be clear from a packet capture on the victim machine that the intrusion took place? Wouldn't it even identify the ip and hardware addresses of the attacker? The answer to all those questions is in the affirmative, but you'd need to have been monitoring the network traffic over the whole course of the login session to know that. A simpler solution for the potential victim is to check the system's ARP cache before logging in to the router. This will identify whether there are two hosts on the network with the same hardware address. Since hardware addresses are supposed to be universally unique, this is a tell-tale sign that ARP spoofing is in progress.


Moving Forward
Now that you have your lab's local area network set up, what can you do with it moving forward? Well, that's up to you! At the very least, you can use it to test the security of any given networked device you like, whether it's your main computer, a secondary computer, a cell phone, a tablet, a network drive or fileserver, a television or gaming console, and so on. Do you know what precise information your cell phone or laptop broadcasts to the entire local area network when you connect to any wireless device?

That concludes part four of our tutorial series on setting up a home hacking and security testing lab. If you've followed along from the beginning, you now have a virtual network you can use to explore the vulnerabilities in Metasploitable, an isolated local area network to test the security of any device you wish, and some familiarity with a handful of the many tools that are bundled with Kali.

As always, questions, comments, suggestions and criticism are welcome in the comments. Happy hacking!
Comments (8)

Hack Lab Part 3: Installing the Victim Machine on a Virtual Network and Basic Exploits

This post is part three in our tutorial series on how to set up a home hacking and security testing lab. If you followed along in parts one and two, you have installed a Kali virtual machine in VirtualBox on your primary computer, and have begun exploring your home computer network with nmap and Wireshark, both of which come bundled in Kali.

In the present article, we will walk through the creation and installation of our victim machine, a virtual instance of Metasploitable2, and then configure our first lab network: a completely virtual internal network inside VirtualBox. We'll place the Metasploitable2 victim machine and the Kali attack machine on the virtual network, and conclude by showing one way to begin exploring and exploiting Metasploitable's various vulnerabilities with Kali, and then provide some resources for further study.

On that note, it must be stated at the outset that Metasploitable is an intentionally insecure machine, with a ridiculous number of vulnerabilities. It should never be exposed to the internet, or to an untrusted network. This is why we will connect it to a completely virtual network, one that cannot even be accessed by the host machine that is running VirtualBox.


Installing Metasploitable2 in VirtualBox
There are number of subtle differences between creating a Metasploitable virtual machine and creating a virtual instance of an everyday operating system such as Kali in VirtualBox, as wel shall see. Metasploitable2 is a prepackaged system intended for security testing and practicing common exploit techniques. Once the machine is set up, it does not require any updates or further configuration as was the case with Kali.

The first step, of course, is to download a copy of the Metasploitable2. Metasploitable2 was developed by Rapid7, the IT security group that created the Metasploit Framework, "a tool for developing and executing exploit code against a remote target machine," as noted at Wikipedia. The Metasploit Framework, as you may know, is also bundled in Kali, and the intentionally vulnerable Metasploitable2 system was created to provide a way to test the sorts of exploits that can be launched from Metasploit, among other tools.

You can download Metasploitable2 from Rapid7, but it is also available from other sources such as SourceForge. Once you've downloaded the file, unzip it, and place it wherever you prefer. I keep all my virtual machine .iso files and the like in a dedicated folder.

In the Metasploitable2 download, you'll notice a few differences from your Kali download. For Kali, we used the .iso disk image file to install the system on the machine. There is no .iso file for Metasploitable2. Instead we are instead going to install the Metasploitable.vmdk file, which stands for virtual machine disk format.

Start up VirtualBox and click "New" to begin setup of the victim system. Name the new virtual machine, select its type and version. I've just used the defaults here: Ubuntu, 32 bit. Click "Next".


Since we will not be using the Metasploitable system directly, but rather only interacting with it as a target, we can lower the amount of RAM we allocate for it.  I've chosen 384 MB as the initial setting. After you get it up and running, you might find that you can reduce it even further. In my experience, response times begin to noticeably lag around 256MB of RAM. Click "Next".


We do not need to create a virtual hard drive for Metasploitable. Instead the .vmdk file will act as a virtual hard drive itself. Select "Use an existing virtual hard drive file", then click the file-browser icon, navigate to your Metasploitable download files, and select the .vmdk file. Click "Create".


The newly created instance should now appear in your VirtualBox interface. Notice I have grouped my kali1 instance and my Metasploitable2 instances inside a folder labeled 'lab'. Grouping becomes very helpful once you have more than a couple virtual machines set up.


Now we need to tweak a couple settings for our Metasploitalbe virtual machine. Open the Settings window. I uncheck 'Floppy' in the boot order under the System menu, though this is not very important. In the Network settings, you'll notice that the default is the same as it was for Kali: there is a single network adapter enabled with NAT, natural address translation.


We're going to change NAT to an internal VirtualBox network. In the "Attached to" drop down menu, change adapter one by attaching it to "Internal Network". You can also name your new virtual network. The default name is 'intnet'. I'm going to call mine 'labnet'. Click OK.


We're not quite ready to fire up our victim system just yet. Or at least, I'm not, because I've chosen a new name for my internal network. My experience with internal networks in VirtualBox has been a bit inconsistent. I clearly recall that the first time I used an internal network, it just worked and no further config was necessary. On another computer, I later found that the default internal network 'intnet' had to be configured as you would any custom internal network. If you fire up your Metasploitable virtual machine, log in and find that you have a functioning ip address, you're all set and can skip the following section. Otherwise, read on.

Configuring the VirtualBox Internal Network
I have to now enable the VirtualBox internal network 'labnet' to which I've just attached my Metasploitable virtual machine. If we take a look at the VirtualBox user manual section on Internal Networking, we read:
Unless you configure the (virtual) network cards in the guest operating systems that are participating in the internal network to use static IP addresses, you may want to use the DHCP server that is built into VirtualBox to manage IP addresses for the internal network. Please see Section 8.35, “VBoxManage dhcpserver” for details.
Rather than set up static ip addresses for our virtual machines on the virtual internal network, let's set up the virtual dhcp server. Reading through the VirtualBox user manual section on managing the dhcp server, we can conclude that running the following command in a terminal on the host computer will appropriately configure the internal labnet network.
VBoxManage dhcpserver add --netname labnet --ip 192.168.1.1 --netmask 255.255.255.0 --lowerip 192.168.1.2 --upperip 192.168.1.255 --enable
What's going on here? Let's parse this command.
  • There is the command for the VirtualBox dhcp server: VBoxManage dhcpserver
  • We want to create a new network, therefore: add
  • We indicate the name of the new network: --netname labnet
  • We specify the ip address of the dhcp server itself: --ip 192.168.1.1
  • We specify the subnet or netmask: --netmask 255.255.255.0
  • We specify the lower ip address for the server: --lowerip 192.168.1.2
  • We specify the upper ip address for the server --upperip 192.168.1.254
  • Finally, we enable the network so it starts any time a machine on the network is started: --enable
If successful, you can now fire up your new victim system and it will automatically be connected to the newly-configured internal virtual network. Go to the VirtualBox interface, select the system and click Start. This is the Metasploitable login screen:


Run ip addr or ifconfig to confirm that the system has been given an ip address and make a note of it. The victim is prepped. Did I mention? Metasploitable is an intentionally insecure machine, with a ridiculous number of vulnerabilities. It should never be exposed to the internet, or to an insecure network!

Now let's put our attack machine on the internal network. Network adapters can be changed in this manner even if the machine is running, though in my experience, this can also lead to minor glitches in the functioning of the VM, so I usually shut down if I'm going to change network settings for a VM.

Select your Kali instance in the VirtualBox application interface, click Settings, go to the Network settings. Change the adapter from Bridged to Internal Network, and select the name of your newly created internal network. I also "Allow All" in promiscuous mode under the advanced settings, as this allows the Kali network interface to detect any and all packets to and from the other virtual machine (as well as the host computer, if it were able to connect to the same network). Click OK.

Start up Kali and log in if the machine is not running. Check ip addr or ifconfig to make sure you have gotten an ip address from the virtual dchp server. If so, you're all good! Open up the Ice Weasel browser that comes bundled with Kali. In the address bar, enter the ip address of your Metasploitable instance. When the page loads, you should see the web interface that is pre-configred on the Metasploitable virtual machine. It comes packaged with 5 different websites/webapps that are intentionally insecure: TWiki, phpMyAdmin, Mutillidae, DVWA, WebDAV:


At this point, you now have a virtual internal lab network running on your host computer, and two virtual machines running on that network: your Kali attack machine and your Metasploitable victim machine. Remember, this network is completely internal to VirtualBox. Your virtual machines cannot communicate with the host computer over this network and the host computer cannot communicate with the virtual machines over this network. They are isolated.

Exploring Metasploitable's Vulnerabilities
Now the real fun begins! The first thing you might do here is passive network monitoring to see what kind of packets, if any, the victim machine is sending out over the network. Fire up Wireshark inside Kali, and start a capture on the appropriate interface for the lab network. (See part two of this series on how to configure Wireshark for live capture.)

From the packet capture, you'll soon notice that Metasploitable sends out workstation and workgroup announcements every couple of minutes for services that are running on it. If you inspect those packets more closely, you'll find that those packets contain a good deal of information about the host machine sending them, as well as about the services running on it.

An an exercise, confirm by inspecting the packets you've captured that Metasploitable is: 1) a workstation, 2) a server, 3) a print queue server, 4) a Xenix server, 5) an NT Workstation, 6) an NT Server, and 7) a Master Browser. You can doubly confirm that the machine is running such services by browsing its shares over the network in the file manager. But where can we find the network login credentials to view the shares?

Now that we have some idea of what we're dealing with, let's conduct a few port scans of the victim system to see what vulnerabilities that might expose. Let's just go through some of the various default scan types built in to Zenmap to see what they bring to light.

A ping scan reveals that the host is up. A quick scan identifies 18 open ports, among them the reserved ports for ftp, ssh, telnet, smtp, htttp, mysql and so on. A regular scan identifies 23 open ports. An intense scan also reveals 23 open ports, but it also provides operating system and version information, along with more detailed information about the services running on the various ports. For example, it notes that anonymous ftp login is allowed on port 21, identifies the SSH server's hostkey fingerprint, and so on. Run the more intensive scans to see what else you can find.

As an exercise, analyze the command options used in the various Zenmap scans to determine why those particular scans revealed that particular information.  

It is worth noting here that a couple leads for tracking down Metasploitable's network login credentials are provided already in the simple quick scan. However, it is indicative of the system's complete insecurity that these leads make the question of determining the network login credentials moot. Can you identify any such lead and why it moots our earlier question?

If you've followed along this far, you're probably asking yourself: what's next?  (That is, if you haven't jumped ahead already.) Well, you now have a fully functioning virtual hacking lab outfitted with one of the most powerful attack systems and one of the most vulnerable victim systems around. It's time to start exploring some of the more involved tools bundled in Kali and see what other kinds of weaknesses you can identify and exploit in the various services running on the victim machine, including in the five websites and applications running on the system.  That, however, is beyond the scope of the present article, but here are some resources to help get started:
Like nmap and Wireshark, all three of these tools are listed in Kali's "Top Ten Security Tools" menu.

That concludes the present article. In part four of the series, we'll set up an external local area network and demonstrate how it is possible to steal login credentials from a victim machine logging in to a compromised router. As always, questions, comments, suggestions and criticism are welcome below.
Comments (5)

Hack Lab Part 2: Exploring Your Home Computer Network with Kali Linux

This article is part two in our tutorial series on how to set up a home hacking and security testing lab. If you followed along in part one, installing a Kali Linux virtual machine in VirtualBox, you have installed VirtualBox on the primary computer for your home lab and created a Kali Linux virtual guest on this host machine. The Kali system has been fully updated and VirtualBox Guest Additions have been installed on it. Finally, your Kali VM has a single network adapter running in bridged mode and you have set up an administrator account on the Kali instance. 

Creating and configuring the virtual network setup outlined in the introduction, which we will do in part three of this series, requires a few more steps: we still have to download and install Metasploitable, set up the virtual network, etc. But if you're like me, you're probably already itching to start playing with all the toys Kali has to offer, if you haven't already!

Home Network Analysis 101
This article will show how some of the tools that come bundled in Kali can be used to explore your existing home computer network, and test whether you can successfully identify all the devices that are connected to it. In particular, we'll take a look at a set of tools that come bundled in Kali that can be used for network analysis: nmap/Zenmap and dumpcap/Wireshark.

These will come in handy in our eventual testing lab, but they can obviously also be used to explore your home local area network as well. Nmap is a command line network scanner, and Zenmap is a graphical interface to nmap. Dumpcap is a command line network traffic monitor, and Wireshark provides a powerful and versatile graphical interface to monitor network traffic and analyze network packet capture files.

Here's a simple experiment. Do you happen to know how many devices are currently connected to your home network? Can you identify all of them off the top of your head? Try to do so, and make a list of them. At the very least, we know there will be at least three: the Kali guest, the host machine you are running Kali on, and your router. There may also be more computers or cell phones connected to it, and maybe even your television, refrigerator or coffee maker!

We are first going to use nmap to see if we can identify any such devices on the network, and perhaps detect one or two that we did not think or know were connected to it. We'll then configure Wireshark and run a packet captures to get a sense for the normal traffic on the network, and then run another capture to analyze just how an nmap network scan works.

Determining Your IP Address
Before we can scan the network with nmap, we need to identify the ip address range we would like to examine. There are a number of different ways to determine your ip address on a Linux distribution such as Kali. You could use, for example, the ip or ifconfig commands in a terminal: ip addr, or sudo ifconfig.

(Note that if you are using an administrator account inside Kali, which is considered a best practice, when a non-root user enters a command such as ifconfig into a terminal, the shell will likely respond by complaining "command not found". In Kali, sensitive system commands like ifconfig have to be run as root. To access it from your administrator account, all you need to do is add "sudo" to the front of the command: sudo ifconfig.)

These commands will provide you will a wealth of information about your network interfaces. Identify the interface that is connected to the LAN (likely eth0), and make a note of the ip address indicated after "inet" for the ip addr command, or after "int addr:" for the ifconfig command. That is your ip address on your local area network. Here are a couple ifconfig and ip addr outputs posted by the Ubuntu Journeyman:



As you can see here, the ip address for this machine is 192.168.1.4.5. Yours is likely something similar to this: for example, 192.168.1.123 or 10.0.0.56 etc. Notice in the ip addr output above, the ip address is: 192.168.4.5/24.  That means 192.168.4.5 is the ip address of that specific machine, while the /24 at the end indicates the address space for the LAN's subnet, which in this case are all the addresses from 192.168.4.1 to 192.168.4.255.

If we were to scan this local area network with nmap, we would want to scope out all the addresses in the network's range, which means 192.168.4.1, 192.168.4.2, 192.168.4.3, 192.168.4.4, and so on, all the way to 192.168.4.255. One shorthand way of notating this is: 192.168.4.1-255. Another common shorthand is 192.168.4.0/24.  Of course, if your address were 10.0.0.121, then the shorthand would be: 10.0.0.1-255 or 10.0.0.0/24. 


Host Discovery
Let's assume your Kali VM has the ip address 192.168.1.5 on a subnet with possible host addresses from 192.168.1.1 to 192.168.1.255. Now that we know Kali's ip address and the address range we want to take a look at, open up a terminal and type: nmap. This will provide you with a long list of all the options available within the nmap program. Nmap is a powerful program and there are a lot of options! Perhaps the simplest possible network scan that can be conducted with nmap is a ping scan, for which we use the -sn option.

Now type nmap -sn 192.168.1.1-255 into your terminal and hit enter. (Don't forget to substitute the address range for your network if it is different from this!) This scan will tell you how many hosts nmap discovered by sending a ping echo request to each of the addresses in the range x.x.x.1-255, and provide you with a list of the ip addresses of the hosts that returned a ping reply. This is host discovery 101. Here is the ping scan output from nmap on a simple local area network I set up for the purpose:


The ping scan found 5 hosts up with the addresses: 192.168.1.1, .2, .3, .5 and .6.  Note that in the wild, this method of discovery may not work, as it is becoming increasingly common for administrators to configure their systems so that they do not reply to simple ping echo requests, leaving a would-be ping scanner none-the-wiser about their existence.

Did your scan find the same number of hosts that you had presumed were on your network? Were there more or less?

We can use the default nmap scan to further investigate known hosts and any potential ghost hosts the ping scan may or may not have uncovered. For this, simply remove the -sn option from the command above: nmap 192.168.1-255. Here's the output of the default nmap scan on the same network as above:


Nmap has returned much more information. It found three open ports on the router at 192.168.1.1, as well as an open web server port on host 192.168.1.2.  All scanned ports on the remaining hosts were closed.

You can also use nmap to further investigate known hosts. The -A option in nmap enables operating system detection and version detection. Pick out a couple of the hosts discovered by your nmap scans, for which you already know the operating system type and version. Now scan these hosts with nmap for OS and verstion detection by adding them to your host address target list, separated by commas.  For example, if I would scan the router and web server discovered above for OS and version detection with the command: nmap -A 192.168.1.1,2. This will return more information, if any is determined, on those hosts.

You can obviously also run an OS and version detection scan over the whole network with the command: nmap -A 192.168.1.1-255. Depending on the number of hosts on your network, this scan could take a couple minutes to complete. If you press <Enter> while the scan is running, it will give you an update on its progress.

If there are more and a handful of hosts on your network, the output can be hard to parse in the terminal. You could send the output to a file with:  nmap -A 192.168.1.1-255 > fileName.txt. Or you could use one of nmap's own built-in file output options.

But this is also where Zenmap comes in quite handy. Open up Zenmap from Applications->Kali Linux->Information Gathering->Network Scanners. If you are running as an administrator and not root, as you should be, you will get a message stating that not all of nmap's functionality can be accessed without root privileges. Root is not necessary for basic scans. However, you can run Zenmap as root by opening a terminal and typing: sudo zenmap. The Zenmap interface:


The Zenmap interface is pretty straightforward. Enter the target ip address or address range into the target field. Changing the scan profile from the drop down menu changes the scan command. You can also manually enter or edit commands in the command field. After you run a scan, Zenmap also helpfully breaks down the results for you, providing host details, port lists, network topology graphics and more.

Play around with the various built-in scan types. Can you identify all the hosts on your home network with a ping scan? a regular scan? an intense scan? Can you identify all the open ports on those hosts? If you have a laptop or another device that you frequently use to connect to the internet over public wi-fi hotspots, you can also do intensive scans of those devices to determine if there are any open ports that would represent a potential security vulnerability. Identifying open ports is important for vulnerability assessment, because these represent potential reconnaissance or attack vectors.


Network Traffic Capture and Analysis with Wireshark
Nmap scans a network and probes hosts by sending out ip packets to, and inspecting the replies from, its target at a given address. With 255 addresses to scan along with 1000 ports on all discovered hosts in the default scan of the subnet above, that's a lot of network traffic! What does the packet traffic generated by a scan look like on the network?

To answer this question, we can use Wireshark and dumpcap. Dumpcap, as its name implies, is a command line tool that dumps captured network traffic. Wireshark provides a graphical user interface to analyze these sorts of dump files, which are collections of all the network traffic to which the given network interface was privy.

If run with the proper privileges, Wireshark can capture live network traffic as well. In Kali, you can find Wireshark under: Applications->Kali Linux->Top 10 Security Tools. Unless you have already configured Wireshark with the appropriate settings, when you open it for the first time you will be informed by the "Capture" panel that "No interface can be used for capturing in this system with the current configuration."


In its documentation, Wireshark recommends appropriate settings to enable capture privileges. This also suggests confirming that Wireshark can also be run as root. To run Wireshark as root, you can log in as root, or run sudo wireshark in a terminal. When you run Wireshark as root, you will first be given a usage warning and provided with sources for how to set up proper privileges. This forum post on AskUbuntu boils the process down to three simple steps.

Now that you've enabled live captures in Wireshark, let's run one! Click "Interface List" in the Capture panel of the default view. Choose the interface that is connected to the network (it will indicate your ip address on that network), and click Start.

This will immediately begin a live capture of all the packets on the network to which the interface has access. At the very least, it will detect: 1) packets it sends out, 2) packets it receives directly, 3) packets it receives indirectly if they are broadcast to all the hosts on the network.

If you have never viewed a network packet capture before, you may be surprised what you can see, and what information is simply being broadcast over the network. You'll probably find messages from your router, you'll see internet traffic packets if you are viewing a webpage in a Kali browser, or on Kali's host computer (depending on whether or not Promiscuous Mode is enabled in the VirtualBox advanced network settings for your Kali machine). You might find that one device is especially chatty for no good reason. There might be devices pathetically sending out calls to other devices that have been removed from the network, such as a laptop searching for a printer that has been turned off, and so on.

The default Wireshark packet capture interface numbers each packet it captures, and then notes the time after the capture began that it received the packet, the ip address of the source of the packet, the ip address of the destination of the packet, the protocol, the packet's length and some info. You can double click an individual packet to inspect it more closely.

If you ping your router (which you should have been able to identify via nmap analysis) from Kali, you'll see all the requests and replies, obviously, since the Wireshark capture and the ping are running on the same machine. But the Kali guest shares its interface with the host machine. If you enable promiscuous mode in the advanced network settings inside VirtualBox for your Kali instance, when you ping your router from the host machine itself, the Wireshark capture will similarly allow you to see all requests and replies, they're going over the same interface! If you disable Promiscuous Mode, on this other hand, this will not be the case. In this case, packets to and from the host computer will not be picked up, as if it were a completely separate physical machine. Similarly, if you ping your router from a different computer, you will not see the request/reply traffic at all, though perhaps you might pick up an ARP if the requester does not already know the (hardware) address of the request's intended recipient.

After getting a feel for what the base level network traffic looks like on your network, start a new capture, and then run a simple scan from nmap or Zenmap, and watch the result in Wireshark. When the scan is finished, stop the capture and save the file. Capturing the simple nmap ping scan from above on my network resulted in a file with over 800 packets! Now you can analyze the network traffic generated by the scan itself. You'll probably want to play around with Wireshark for a bit to get a sense of what it offers. There are tons of menus and options in Wireshark that can be tweaked and optimized for your own ends.

Well, that's it for this article. In part three of our hack lab tutorial series, we'll install our victim machine, an instance of Metasploitable2, in VirtualBox and set up a completely virtual lab network to explore some more tools that are bundled in Kali. As always, comments, questions, corrections and the like are welcome below.
Comments (21)

Hack Lab Part 1: Installing a Kali Linux Virtual Machine in Virtualbox

In this article, which is the first part in our tutorial series on how to set up a home hacking and security testing lab, we will walk through the creation and installation of a Kali Linux virtual machine inside VirtualBox. This system will then function as our main monitor and attack machine in subsequent tutorials. After setting up the virtual system, we will:
  1. run a live Kali session
  2. do a full install
  3. update the system
  4. install the VirtualBox Guest Additions
  5. configure appropriate user accounts
  6. and finally switch over to a bridged network adapter in preparation for the next tutorial in the series
The whole process may take a few hours to complete, more or less, depending on the specifics of your own situation, ex. computer, internet connection speed, and so on. This session took me about three hours from beginning to end.


Virtualization
There are a number of different free virtualization packages available online. For this tutorial series, we've chosen to go with VirtualBox because it's open source, beginner friendly, and there is a lot of documentation and support information that can be found for it online, especially regarding the systems that we will be installing. For example, since Kali and Metasploitable are derived from the Debian Linux distribution, support information on other Debian-based operating systems such as Ubuntu or Crunchbang is often also applicable to Kali and Metasploitable, as we shall see in this and subsequent articles.

The first step is to download and install the VirtualBox software package onto the primary computer chosen for your lab setup. Make sure you download the right version for your operating system and hardware architecture (32 bit vs. 64 bit). Instructions for installation on various operating systems are readily available if you run into any snags. Also make sure to keep a handy copy of the VirtualBox user manual, which comes packaged with the software and can also be found online.

Once you install VirtualBox and run it for the first time, you'll be presented with the application's welcome prompt, which provides an orientation for the interface. Poke around in the menus to get a feel for the software.

Next, download a copy of the Kali Linux operating system .iso disc image. Again, make sure you download the proper ISO file for your computer's architecture. Depending on the speed of your internet connection, this may take some time, as both the 32 bit and 64 bit files are 3GB in size. Kali's documentation can be found here.

As Kali is a security sensitive system, once you have downloaded the file, it is recommended to check its SHA1SUM hash value against the one supplied on the download page to make sure the file had not been corrupted in transit. For more on how to check a file's hash value, follow the link to our previous article providing an overview of the process.

If you plan on playing around with a number of different virtual guests on your computer, it is probably a good idea to create a permanent folder somewhere on your system where you will keep all the necessary operating system .iso files.

Creating a Virtual Machine
Now let's return to VirtualBox and set up the virtual machine on which we will install the Kali operating system. Open VirtualBox and click "New". Provide a name for your Kali virtual guest system. Choose Linux as the type and Debian as the version, since Kali is derived from Debian Wheezy. As you can see below, I'm using the 32 bit version. Click Next.


Choose the amount of memory you want to allocate to the virtual instance once it is up and running. In my experience, Kali can use a lot of RAM, and the computer I'm running it on has a fair amount to spare, but for now I'm going to leave it at the default of 512MB.  You can also adjust these settings later to optimize them for your own setup. In my experience, Kali runs pretty well in VirtualBox even on a laptop with only 4GB of RAM, though you may have to conserve by shutting down memory intensive applications running on the host computer. After you've set your memory size, click Next.


Choose whether you want to create a virtual hard drive for the virtual machine. We're going to need one for our home lab, so check "Create a virtual hard drive now", then click Create.


For the "Hard drive file type", check "VDI (VirtualBox Disk Image)", then click Next.


In the "Storage on physical hard drive" window, you'll probably want to choose "Dynamically allocated." This means that space will not be taken up on your physical hard drive until it is actually written to the virtual disk. If you choose "Fixed size" then the virtual disk drive will take up a set amount of space on your physical hard drive even if that space has not been written to by the virtual machine. Click Next.


In "File Location and Size," choose where you want the hard drive files for the virtual system to be stored by clicking on the folder icon. I just use the default folder. This is where VirtualBox will store all files related to your virtual machine. Also, on this screen you may increase or decrease the amount of hard drive space you want to be allocated for the virtual instance. 8 GB is the default. I'm going to push mine up to 10 GB. Click Create.



The new virtual system should now appear in your Virtualbox interface. As you can see I have three folders in my left sidebar, and have placed the kali1 instance I just created into a new "lab" group. In the main interface we can see the settings for the new systems, which are a mixture of defaults and configuration settings we determined ourselves in the creation phase. Before starting up the instance for the first time, I usually adjust a few settings first.


Click "Settings" for your new virtual machine. I'm going to add a description under the General menu, because I have other Kali instances on my computer.


In the System menu, under Motherboard, I uncheck "Floppy" in the boot order.


Also in the System menu, under the Processor sub-menu, we have to check "Enable PAE/NX" for Kali to operate properly.


Finally, under the Display menu, I add more Video Memory to the default 12MB, bumping it up here to 36 MB to start. Again, this can be adjusted later to optimize your particular setup.


That's it for now. Browse through the other menus. Notice in the Network setting we can add up to 4 different network adapters for our virtual machine. Later we will play around with the network setting, after we've fully installed the Kali operating system. For now, a single network adapter running on NAT (i.e. Natural Address Translation) will suffice for our purposes.


Click "OK" to save your changes.

Fire up your new machine by double clicking it, or single clicking it and then clicking Start. You will be prompted to "Select start-up disk". We now have to choose the startup disk for our new virtual machine. This is the Kali .iso file we downloaded earlier. Click the folder icon and navigate to the folder where you've stored the Kali .iso file on your host computer. Select it, then click start.



Booting into a Kali Live Session
Kali should boot as if you were booting a real physical machine from a cd with the Kali operating system file on it. Notice that if you click inside the guest window, your mouse pointer will be "captured" by the guest. From then on, your keyboard and mouse activity will control the virtual machine. To switch back to using your host machine, you have to hit the host key, which by default is Right-Control on my computer. It may be different depending on your operating system. The Virtualbox interface will tell you what the "Host Key" is in the bottom right of the window.


From this menu, you can boot into a number of different types of live session, or you can do a full install of Kali on the virtual hard drive we previously created inside Virtualbox. As we shall see, there are numerous advantages to doing a full install of Kali for the purposes of our home hacking lab, but one of the advantages of a live session is that we can jump right in without any further configuration. Let's select the default Live session. Here is the Kali Desktop after booting into live session (note the time and day, yes, this is how I prefer to spend Saturday evening):


You will soon notice that there are certain limitations to the virtual machine's interface. For example, your mouse wheel will not work, you cannot enlarge the size of the screen, or go full screen, there is no tab completion in the terminal, and there are other interace issues as well. This is not a limitation of the live session, or Kali itself, but rather of the virtual machine we've created. However, all these issues can be addressed by installing the Virtualbox Guest Additions, but we'll save that for our future full install of the system.

Notice also that there are limitations to the default NAT networking interface. Under NAT (natural address translation) the Kali guest is not treated as its own independent node on the wider local area network. It does not have an independent ip address on the local area network. Its virtual ip address is translated by the ip address of the host machine. This can be addressed by adding a second network adapter to the virtual system or changing the present one, as we shall see later on.

However, despite these limitations, you can already begin exploring the ridiculous number of tools that come bundled with Kali. Here are Kali's Top Ten Tools:


Since all appears to be working well, let's take a snapshot of the virtual machine. VirtualBox snapshots are a way to keep a log of your virtual machines in a given state. If you are experimenting with a new configuration, and everything suddenly goes to hell, you can always revert back to your previous snapshot like nothing happened. Go to the VirtualBox interface window, select your Kali guest, click "Snapshots" in the upper right. Take a snapshot by clicking on the camera icon. Name the snapshot, and give it a description. Now, if we seriously screw up something on the machine, we can always just revert to this prior state of the system.


Now let's reboot to do a full install. Click the root menu item in the top right of the Kali Desktop window. Then choose reboot or do a full shut down and boot from the VirtualBox interface. In the process, you will be prompted to remove the disk from the system. Of course, we are using a virtual disk image, so there is no physical disk that needs to be removed. Just click enter to continue. Now reboot . . .  OH NO!!!!! "FATAL ERROR: No bootable medium found! System failed."


If you've been following along thus far, you've likely just been delivered this disturbing warning by your virtual machine upon reboot. It's a good thing we took that snapshot! Actually, this was only to be expected. Remember when you had to remove the virtual disk from the machine upon shutdown or reboot? Well, we now have to re-insert the virtual disk, that way we can reboot into Kali and move on to a full install of the operating system. So solve this "Fatal Error," with your virtual machine still running:
  1. Point your mouse toward the Oracle VM VirtualBox application menu on your host machine and find the Devices dropdown menu
  2. Select "CD/DVD devices"
  3. Select "Choose a Virtual CD/DVD disk file..."
  4. Select or navigate to your Kali .iso operating system file
  5. Close the virtual guest by exiting the window and powering off the machine 

After the machine closes down, restart it from inside VirtualBox, it should boot into Kali from the newly inserted virtual disk.

Full Installation of Kali in VirtualBox 

Now let's move on to our full installation of the Kali virtual instance. Once your system reboots into the main menu, choose the Install option and hit enter.


The installation process will begin straight away. Note that over the course of the installation, the various menus are not graphical interfaces. You cannot point and click, you have to enter info via the keyboard, and use the arrow keys to navigate. We're not going to do anything fancy here for the purposes of this simple home lab setup. In most cases the defaults will suffice. Simply follow the directions on each page. This process took about an hour on my computer. Here's the first screen:


  1. Choose your language.
  2. Select your location.
  3. Select your keymap.
  4. Enter the new host's name. It simplifies things to choose the same name you chose for your VM inside VirtualBox, but these need not be the same name. You can also always change both names later if you so wish.
  5. Enter a domain name. I'm going to leave it blank and hit enter.
  6. Enter a root password, then re-enter to confirm. These will be the credentials for the root super-user on the system. Be sure to make a note of the password you've chosen.
  7. Select your time zone.
  8. Partition Disks, select 'Guided - Use Entire Disk'. Not to worry, here 'Entire Disk' means the virtual hard drive we created upon initial setup of the VirtualBox machine. In my case, this will eventually claim up to 10GB on my harddrive, as this was the size I specified when I created the VM.
  9. Select disk. This is the virtual hard drive we configured earlier.
  10. Select partition scheme. Let's choose default, all files in one partition.
  11. Confirm selections, or go back if necessary.
  12. Select yes, to commit the changes by writing them to disk.
  13. Select network mirror if any. None is needed for this home lab setup.
  14. Select proxy if any. None is needed for this home lab setup.
  15. Install grub boot loader (default).
  16. Installation complete! Select continue.

Let the machine do its thing, and then reboot the system. Upon reboot, log into kali using 'root' as your username along with the password you chose for root during installation.

Congratulations, you now have a virtual instance of Kali Linux installed on your computer! But we're not done with our configuration of the new virtual machine just yet. We still have to update the software on the system, and then we're going to install the VirtualBox Guest Additions in order to enable full screen mode, tab completion in the terminal and so on. This process might take you another hour or so, depending on your internet connection.

Updating Kali and Prepping for Guest Additions
If your host computer is connected to the internet, you should have internet connectivity from inside your Kali VM over your NAT adapter. You can check this by opening up the bundled Ice Weasel browser and making sure you can get online. Ice Weasel can be opened by clicking the icon next to the Places drop down menu in Kali. You can also try pinging google.com or some other website from inside a terminal. You can open a terminal by clicking the terminal icon next to the Ice Weasel icon. We are going to need a working internet connection to update the system.

Let's update the system. Open a terminal in Kali and enter the following command:
apt-get update
This will make sure Kali checks the most recent repository for any software updates. Once this process completes, enter:
apt-get dist-upgrade
This will update all software on the Kali system. Depending on your internet connection, this may take some time. The process lasted around 15 minutes for me this time around. Once that is complete, you now have a fully updated Kali virtual machine. But we are still lacking some basic functionality, so now we're going to install the VirtualBox Guest Additions.

Installing Guest Additions in VirtualBox can be tricky. To prepare the system to handle the Guest Additions, we have to run a couple more commands inside the terminal, so open up a new terminal shell and run the following series of commands, one after the other, after each completes:
apt-get clean
apt-get autoclean
apt-get update
apt-get install build-essential linux-headers-`uname -r` dkms
Notice that `uname -r` is inside backticks, not single quotes in the final command here. Yes, this matters. The backtick key should be located just above the tab key on your keyboard. This series of commands was suggested on this CrunchBang forum post, and it has yet to fail me in setting up Guest Additions for a Debian-based machine inside VirtualBox. Once this process has completed, we can now install the Guest Additions themselves.

Installing VirtualBox Guest Additions in Kali
While engaged in the Virtual system, in the Oracle VM application menu, go to the Devices dropdown menu again. Notice the "Insert Guest Additions CD" option. Select it. You will get a pop-up inside Kali asking you if you want to run the file. If it succeeds, great! If not, that's not a problem. In my experience, it has never worked off the bat, so I click cancel.


Selecting the "Insert Guest Additions CD" menu option has inserted a virtual disk into your virtual machine. The files on this disk can be found in the folder: /media/cdrom/. Confirm that they are there by navigating to this folder in the graphical file system manager or in a terminal.

To install the Guest Additions for Kali, we need to run the VBoxLinuxAdditions.run file on the Guest Additions cd. However, you cannot simply run the file from the /media/cdrom/ directory. First we need to copy it and change its permissions.

Copy the file to your Desktop from inside a terminal with the following command:
cp /media/cdrom/VBoxLinuxAdditions.run /root/Desktop
You should see a copy of the file appear on the Desktop.  Change to the Desktop directory inside the terminal:
cd /root/Desktop
Change the permissions on the file with the following command:
chmod 755 VBoxLinuxAdditions.run
Run the additions file:
./VBoxLinuxAdditions.run
Success? Success!


If you experience any snags along the way here, you'll have to do some trouble shooting. There is a ton of info online regarding installation of Guest Additions in VirtualBox VMs, likely in large part because the process can be tricky. Remember also, that support info for other Debian-based systems such as Ubuntu and CrunchBang will also apply to Kali in many cases. But the series of commands above has yet to fail me.

Upon successful installation of the Guest Additions, we have to shut down the machine for the updates to take effect. Reboot and log in as root again. Once the system reboots, the simplest way to confirm that the Guest Additions have been successfully installed is to see if you can maximize the window for the guest system. You should now also have code completion in the terminal, among other things. You can now eject the Guest Additions virtual CD from the Virtual cd drive. Click the Computer icon on the Desktop, then click eject under the devices menu.

We now have a fully updated fresh install of a Kali virtual machine with the VirtualBox Guest Additions installed. Let's shut down the machine, take a snapshot and switch the network adapter into bridged mode in preparation for the next tutorial.

Switching to Bridged Networking
After the VM has shut down and you've taken your snapshot, open up the settings of your new virtual system and go to the Network menu. Unless you've already chaned these settings, you should have network Adapter 1 enabled, and attached to NAT. Change the attachment to a bridged adapter. This will allow our guest to act as an independent host on our local network, rather than have its address translated by the host computer the virtualization software is running on.


Finally, the adapter Name has to connect up to the appropriate network adapter of the host machine, i.e. the one that is actually connected up to your local network, whether it is a wireless connection, an Ethernet connection, or whatever. The appropriate one should be selected by default. Click Okay.

Start up the guest. Open a terminal and ping a known website or host, or use a browser to visit a web page. If it works, CONGRATS! You're in bridged mode.

If you have no networking capability, and can't even ping other computers on your home network, let along a website. You have to do some trouble shooting. Here are some troubleshooting questions:
  • Are your networking settings correct in VirtualBox?
  • Is the adapter for the guest machine connected to the right interface on the host computer?
  • Is Kali's /etc/network/interfaces file structured properly?
  • Is the appropriate interface up as indicated by ifconfig?
  • Have you tried restarting Kali's networking service?
  • Is Kali's /etc/NetworkManager/NetworkManager.conf file structured properly?
  • Have you tried restarting the network-manager service?  
As the old saying goes, when all else fails, read the manuals!  

Setting up an Administrator Account
If you've followed along this far, you are now logged into your Kali VM as root, have a fully updated system, and the VirtualBox Guest Additions installed. It is not good to get into the habit of running everything in Kali as root. Best practices dictate setting up an administrator account and using sudo to run security-sensitive commands.

Create an administrator account by going to the root dropdown menu in the top right of the Kali Desktop. Then select: root => system settings -> user accounts -> create an administrator account. Create an administrator account with a separate password.  Then log out, and log back in with your new admin account.  Using an administrator account such as this creates a bit of extra work (ex. having to use sudo for otherwise everyday commands such as ifconfig, having do to a bit of extra configuration for applications such as Wireshark and Zenmap), but it is a good habit to get into so as to avoid becoming careless with the root account. After setting up an administrator account, shut down the machine and take another snapshot.

In part two, we will use two tools bundled in Kali to explore your home local area network. Thanks for following along. As always, leave any questions or comments below. 
Comments (4)

Hack Lab Intro: How to Set up a Home Hacking and Security Testing Lab

Introduction

This series of articles comprises an introductory tutorial on how to set up a home lab to experiment with common hacking and information security testing tools. Our setup will  allow us to explore the sorts of computer and network vulnerabilities that can be encountered on the internet, and to test the security of our own home computer network and networked devices, all from within an isolated and secure working environment. The series is geared toward individuals who have little or no prior experience with virtualization software or common hacking and security testing tools, but are interested in exploring network and computer security.

Over the course of the tutorial series, we will create two separate network configurations. The first will be a completely virtual environment populated by two virtual guest systems running inside a single host computer. This requires nothing more than an internet connection for the necessary downloads, and a computer with relatively modest RAM and disk resources.

The second configuration will be an everyday local area network of the sort that can be found in many homes, but which is isolated from the internet and where we can strictly control and monitor all network traffic. This setup is slightly more involved in terms of hardware than the first, requiring also a spare router.

Our monitoring and attack system in both configurations will be an instance of a Kali Linux virtual machine running inside an installation of the VirtualBox software package on our primary computer. Kali is a Linux operating system distribution intended for security testing and digital forensics.

In the first completely virtual network environment, our victim will be an instance of  Metasploitable2, a virtual machine that exhibits vulnerabilities that can be found on  everyday computer systems and software configurations. As noted at Offensive Security, "Metasploitable is an intentionally vulnerable Linux virtual machine. This VM can be used to conduct security training, test security tools, and practice common penetration testing techniques."

In the second network configuration, we will use the Kali Linux virtual machine to compromise an everyday local area network router of the sort that can be found on many home networks, in order to demonstrate just how easy it can be to steal login credentials  passed from another computer on the network.

The tutorial is broken down into four parts:
  • Part 1 covers the installation of VirtualBox and provides a walk through of a full installation of a Kali virtual machine on your primary lab computer. Along the way, we'll take a short detour on how to quickly run live Kali sessions without a full installation of the machine.
  • Part 4 provides details on setting up our second network configuration, which models an everyday home local area network. With the attack machine, we'll conduct a simple man-in-the-middle attack against the network's router, and demonstrate a serious security vulnerability by stealing login credentials sent to it from the victim machine, in this case, the host computer. 
Comments (3)

Tutorial: A Simple iOS Stopwatch App in Swift

In this tutorial, we will create a single view iOS application using the Swift programming language. The tutorial will provide some insight into basic usage of the Apple Xcode integrated programming environment, as well as the model/view/controller software architectural pattern. Our target audience are people who have some prior experience in application development and programming but who are relatively new to Xcode and iOS development. The project goal is to build a simple iOS stopwatch-style timer application designed for iPhone using Swift.

The app will contain two labels (one for our title and one for our numeric timer display), and two buttons (a start/stop button, and a reset button). We will first lay out our main view, which will contain these elements and then use the interface builder (i.e. storyboard) to hook our view into the controller (IBOutlets and IBActions). Finally, we will turn to the business logic of the app. In the end, we will have two imports and a view controller. We will add three methods to the view controller class: two actions methods and one helper method. The tutorial will be broken down into a series of just over thirty steps with screen caps to provide a quick visual aid.

The first thing you'll need to do, if you haven't already, is download the latest version of Xcode 6 (currently in beta as of this writing). If you are completely new to Xcode, you may find it difficult to navigate the interface. There are tons of great guides to Xcode that can be found online such as this one.

On initial startup, Xcode will present you with its ‘Welcome’ screen and offer several options. Select the “Create a New Xcode Project” panel from the window (see figure 1). If it does not present you with this screen, select File->New->Project from the menu bar.

Figure 1
On the following screen, select “Single View Application” and press the “Next” button (see figure 2).

Figure 2

Next, choose the options for your new project (see figure 3) and fill in the necessary fields as you wish, ex. project and organization names, and select “iPhone” as the device, since we are creating an iPhone app.

Figure 3
The following screen will then prompt you to provide a destination directory for your project. I like to keep current projects in a folder on my Desktop. There is also an option on the bottom of the screen to place your project under source control. If you don’t know what source control is or how to use it, then simply uncheck this box. (However, it is highly recommended that you invest some time learning about source control systems such as git.) Click “Next” once you have made your selections.

Your project should have opened to a screen similar to the one in figure 4.

Figure 4
From the device dropdown menu, located in the upper left corner, select iPhone 5s (notice also the other options that could have been selected here if we were planning to create a different app). See figure 5.

Figure 5

Now that we have our project’s initial setup completed, let’s get down to business! From the Project Navigator, select the Main.storyboard file. See figure 6.

Figure 6
In the Storyboard, select any view, then go to the File Inspector in Xcode’s right panel. Uncheck “Use Size Classes”, and you will be asked to keep size class data for: iPhone/iPad. Then click the “Disable Size Classes” button. Doing this will make the storyboard’s view automatically size with the selected device. See figure 7.

Figure 7
In the top left corner of Xcode, locate the “Play” button and press it to build and run your project for the first time. See figure 8. Upon a successful first launch of the project, you should see something like the image in figure 9, an iOS simulator. If you get any errors and the project does not build correctly, read the error report(s) carefully and see if you can troubleshoot the problem.


From the Object Library toward the bottom of the right panel in Xcode, select Label (figure 10) and then drag and drop it at the left style guide, but vertically centered into your single storyboard scene/view. See figure 11. The style guides are temporary visual placement lines that appear as you position view elements into your scene. This label will eventually provide the numeric display of our running stopwatch.

Figure 10

Figure 11

In order to make the label wider, we will select and drag the trailing edge of our Label element to the right of your scene until it meets the right most style guide. See figure 12.

Figure 12
From the Attribute Inspector panel in the right panel of Xcode, toggle the text alignment to center so our text appears in the middle of the label. See figure 13.

Figure 13
Go back to the object library and place two Buttons equally spaced apart about midway between the label and the bottom of our scene. See figure 14. These will function as our reset button and our start/stop button on the stopwatch.

Figure 14

From the Size Inspector in Xcode’s right panel change, the width of each button to 60 points. See figure 14.1.

Figure 14.1
Run your project to see what it looks like. Again, if you get any errors and the project does not build correctly, read the error report(s) carefully and see if you can troubleshoot the problem.

Select the Assistant Editor from the top right corner of Xcode to display the storyboard and associated Swift file side-by-side. Now hide both the Navigator and Utilities panels by clicking on the appropriate panel buttons in the top right corner of Xcode. See figure 15.
Figure 15
Now let’s connect up our storyboard elements to our controller, which will connect our interface to our code, that way all the relevant interface elements can communicate events to the controller.

Place your mouse pointer over the Label; then press and hold the control button while clicking and holding down your mouse button as you pan your mouse pointer across the screen and into the right side of Xcode where your Swift file is located. You should see a blue line follow your mouse pointer. See figure 16.

Figure 16

Once in the class area, as shown, release the mouse button and the control as well.  You will see a dialogue box prompting you for the name of your outlet. Name it ‘numericDisplay’. See figure 17. This will add the necessary outlet code to your Swift controller class. An outlet is a reference pointer to an element inside your storyboard. Creating outlets allows for easy access to objects in your storyboard. After naming the outlet, your screen should look like figure 18.

Figure 17


Figure 18

Go ahead and connect the buttons as outlets as well. Name the left button ‘resetButton’ and the right button ‘startStopButton’.

In a similar fashion to the newly created outlets, we will now create action methods for each button. This time we will drag the blue line toward the bottom of the file but inside the class body. Name the left button resetButtonPressed and startStopButtonPressed for the right button. In the dialog box, make sure you select 'Action' from the Connection drop down menu. See figure 19. Action methods are the functions in your class that get messaged/called when the button that is associated with the connected method is triggered by an event. An event is initiated when the user interacts with any of your buttons.
Figure 19
Your interface should now look like the screencap in figure 20.

Figure 20

To accurately update our numeric display label, we need to tie it in to a mechanism that will update at very precise time intervals. To access this functionality, we need to import the appropriate class library. From Xcode’s menu bar, select the Window tab drop down menu then select Documentation and API Reference. See figure 21. The documentation search window should appear. In the search bar type CADisplayLink and locate the appropriate documentation. Read through the documentation and familiarize your self with the CADisplayLink class. This class is very useful when your code needs precise timing control.

Figure 21

Notice that the CADisplayLink requires the QuartzCore framework. A framework is a set of classes with predefined functionality so that you don’t have to reinvent the wheel; it's code packaged for re-use, so use it!  With Swift you no longer need to define an interface(.h) and an implementatin(.m) file to define a class which is nice. Also, when importing different frameworks into your project you no longer have to go Xcode's build setting and explicitly add that framework; it automatically loads when you use the keyword import followed by the desired framework like so: import {SomeFramework} but without the curly braces.  And my favorite addition is the fact that semicolons are no longer required! WhooHoo! There are also a ton of outher features of Swift that I have yet to discover. In your ViewController.swift file add the line of code importing QuartzCore:


Importing a framework into your file gives you access to its classes and functionality. In your ViewController class, add the following var properties just below the @IBOutlet properties. Add the code in lines 5 and 6 below:



‘var’ is short for variable and displayLink is our object pointer of type CADisplayLink. We use this pointer to hold a strong reference to an instantiated CADisplayLink object that we will create in a few moments. We want a strong reference to an instance of CADisplayLink to be able to access it throughout the various parts of our class. We also define a lastDisplayLinkTimeStamp of type CFTimeInterval. This variable will store a running tally of the total elapsed time.

Now let’s set the default view element values for our numeric display label and our two buttons. Add the code below to our viewDidLoad() method:



In your viewDidLoad() method now add the lines of code from the snippet below:



The first new line of code above (line 16) creates an instance of a CADisplayLink object, and assigns this class, i.e. “self,” as the target for messages that inform us of a display refresh rate update. This occurs in the first parameter of the CADisplayLink(<first parameter>, <second parameter>) method call. In the second parameter we pass the name of the method that we would like to be called when there is a display refresh rate update. We will define this method shortly. The second new line of code (line 9) ensures that the display link does not begin its updates until we press the Start button in our user interface. The third new line of code (line 12) schedules the display link to begin sending notifications to our instance method about display refresh rate updates. The fourth new line of code (line 15) simply initializes our elapsed time running tally variable.

The next step is to define the method that will be called when the display link has an update. Add this code to the bottom of the viewController.swift class, i.e. inside the final class curly brace:



Now for the logic—we are almost there! In the newly created function add the following lines of code:



The first new line of code (line 3) updates our running tally. The second (line 6) formats our running tally into a string that only shows the last two significant digits. The third (line 9) updates our numeric display label.

Let’s move over to the startStopButtonPressed(…) method. This method is called anytime the user presses the button situated to the right in our stop watch scene. When this button is pressed we want to toggle the display link’s “paused” Boolean value. Add the following line of code to this method.



At this point you can run your project and press the start button to see your stop watch in action! Woohoo! Again, if you get any errors and the project does not build correctly, read the error message(s) carefully and see if you can troubleshoot the problem.

Let’s shift our focus to the Reset button. What do you think this button should logically do? It should pause the display link to prevent it from  sending us any further updates, then set the numeric display label to zero, and update our Start/Stop button state. In the resetButtonPressed(…) method add the following lines of code:



Let’s now complete our code project by adding the last few lines of code for our Start/Stop button. In startStopButtonPressed(…) add the code in bold:



Our label text string will not be modified if our code does not fall through our first conditional if statement. If, however, the display link is paused, then we check the running display link tally. If this tally is greater than zero, then we display the resume button since pressing this button again will not reset our running tally. If it’s equal to zero then we display the start text. The button text is set in the last line of code.

Your final ViewController file should look like this.

Finally, let’s add a title label. Go back to the main storyboard. From the object list at the bottom of the File Inspector in the right pane of Xcode, drag a Label to the center/top of your main view. Size it as you like, and provide it with a text title such as “Stopwatch”.  The final product should look something like the three screencaps below, showing the default, running and paused states:

Default State



Running

Paused

And that concludes our simple Stopwatch app tutorial! We leave you off with a question for further reflection.  Notice that our chronometer output is not formatted for standard time. Our implementation increments our minor units, values to the right of the decimal point, from .00 to .99 before increasing the the major unit by one. Although this is a correct unit of measurement, it is not in the ubiquitous standard time format. In the standard format the minor unit, a.k.a the second, is incremented from .00 to .59 before the next major unit, i.e. a minute, is increased by one. Since there are many ways to implement this, some being more efficient than others, we leave this consideration to the reader as an exercise. Post your own solution below. And, as always, feedback, suggestions, and angry tirades are welcome in the comments.

This project can be found on GitHub.

The Stopwatch app and tutorial was originally authored by Stefan Agapie, a Senior iOS Software Engineer, and then adapted for the present piece.
Comments (6)
See Older Posts...