Adding MIME Types To Support App Distribution On Apache, IIS, and NGINX

iOS Apps are .ipa files, which are compiled bundles of files that comprise an App on a device. By default, most web servers do have a handler that tells them what to do in the event that a call attempts to access one of these files. Therefore, in order to support downloading those files properly, you need to teach the server how to handle them.

First, let’s grab the MIME type from the Mac file command. To do so, run file with the, big surprise, –mime-type option and then the path to the file:

file --mime-type /Users/ce/Downloads/enrollmentProfile.mobileconfig

The output would be as follows, indicating that a file with the .mobileconfig extension has the application/octet-stream extension:

/Users/ce/Downloads/enrollmentProfile.mobileconfig: application/octet-stream

Since more and more apps are deep linking a plist into the app, we’ll also add a plist. The output on a Mac for the various file types is:

  • .mobileconfig: text/xml or application/octet-stream if signed
  • .mobileprovisioning: text/xml or application/octet-stream if signed
  • .ipa: application/x-ios-app
  • .plist: text/xml or application/octet-stream if a binary plist

In the above, note that a signed mobileconfig, a signed mobile provisioning, and a binary plist are basically interpreted as binary files. This means that when possible, use signed mobileconfig and mobileprovisioning files so you have a consistent handler.

We’ll start defining those with Apache. Handlers are managed in Apache’s global configuration file, often located at /etc/httpd.d/httpd.conf and you would paste the following towards the bottom of the file where you see the media types (note that each AddType is teaching the web server what type of file each file extension indicates):

AddType application/octet-stream .ipa
AddType text/plain .plist
AddType aapplication/octet-stream .mobileconfig

In the above example we set a plist to plain in order to show that, well, sometimes it is. Alternatively (or additively if you need to host both binary and flat plist files), you could create an .htaccess file in the directory with the files (e.g. if you don’t have root access to change the httpd.conf), by adding something similar (the # is indicating a commented line):

# Apps
AddType application/octet-stream .ipa
AddType application/octet-stream .plist
AddType application/octet-stream .mobileconfig

For IIS, go into IIS Manager and right-click on the name of the server, select Properties and click on New… in order to create new MIME types. Then add each using the above types.

To update on nginx, edit the mime.types file in the conf directory for nginx. This is often found in /etc/nginx or /opt/nginx but ymmv. Once found, in mime.types look for a types section wrapped in curly-braces {}:

types { application/octet-stream mobileprovision; application/octet-stream mobileconfig; application/octet-stream plist; application/octet-stream ipa; }

Note: In some cases you might find that “application/x-apple-aspen-config” and in others text/plain or text/xml works better for .mobileconfig MIME types.

If you have failures, you can use a proxy to check it. Here, you’d probably want to use a unique port number to make calls easier to use. If you use Charles Proxy, you’d configure the proxy in the Wifi settings of an iOS device and then open the link in a browser and watch for any failures.

Visual Studio Project To cURL A REST Endpoint in C++

Published a new Visual Studio project for running rest operations against an endpoint using C++ or Visual C++. That’s available at

Note: When you compile the project, you will need to add the dependencies so check what’s being imported before doing so.

Get A List Of Software Installed On Windows And Uninstall Software Using Powershell

The Get-AppxPackage cmdlet can be used to obtain a list of all apps installed on a Windows host. In the following example, we’ll look at the apps installed for all users using the -AllUsers option.

Get-AppxPackage -AllUsers

The output includes a Name, the name of the publisher, along with a location, the architecture, the version, the full name, the status, whether the software is signed, whether the development mode is enabled (useful when testing), the id of the publisher, the family, etc.

Next we’ll do a Select against the found set. You can use so stdout displays the Name and the unique identifier, which we can then use to programmatically work with the package if needed (you can choose any of the metadata from the previous command in the select):

Get-AppxPackage -AllUsers | Select Name, PackageFullName

If you want, you can use -User instead of -AllUsers, to see the output of just a given package. One challenge with using Get-Appxpackage is that you don’t get the actual “Product Name” so if you, for example, wanted to uninstall a program, you’d need to hop into WMI. First, let’s use gwmi to find a product with the word Krypted in the name:

$Key = Get-WmiObject -Class Win32_Product | Where-Object {
$_.Name -match "Krypted"

Next, let’s use the $Key from the output to uninstall the software:


Transfer Text In And Out Of The iOS Simulator Using xcrun

In a previous article, I covered creating, starting, and stopping iOS simulations. macOS comes with a handy tool to interact with the clipboard (aka pasteboard) on a Mac called pbcopy. You can redirect information from a file into your clipboard using the pbcopy command. Here, we’ll simply call pbcopy and then a file path

pbcopy ~/Desktop/transfer.txt

You can then redirect your text into simctl by doing a pbpaste into

xcrun simctl pbpaste booted

Once you’ve copied your data, clean up the transfer file:

rm ~/Desktop/transfer.txt

You can also pull text out. If you write data into the clipboard (e.g. during instrumentation) then you can extract it from that pasteboard using the simctl subcommand pbcopy as follows:

xcrun simctl pbcopy booted

The xcrun simctl subcommand also comes with a number of other pretty cool automations for programatic control, which I’ll try and cover later.

C++ Application To Write Data Into HKEY_CURRENT_USER – This project includes a RegistryKeyManager class that takes care of writing/reading to a registry file. Using a dedicated class makes expanding your registry functionality in the future easier.A DWORD is 4 bytes, so the value for RegistryWriter to send is currently limited to 4 characters (i.e. test1234 is not technically possible with a DWORD).

To use it, simply call the RegistryKeyManager class along with the key to write to and the value to put into the key:

RegistryKeyManager r( "HKEY_CURRENT_USER/Software/x/y", 1234 ); Which would create a key in HKEY_CURRENT_USER/Software/x/y with a DWORD value of 1234.

You could then read the value of and modify the key with calls like:

DWORD currentValue = r.ReadDwordValue(); r.WriteValue( 1234 );

A small helper method is also included in case you’d like to encode strings in the dword (since in your example you have used an ASCII string as the value. The method is RegistryKeyManager::ToDword(). You just need to call it around the value:

r.WriteValue( RegistryKeyManager::ToDword( "TEST" )); // Stores the bytes T, E, S, T in the DWORD value.

Controlling Multiple launchagents and launchdaemons concurrently

Most of my examples for launchctl have been per-user, per-agent, per-daemon. But you can also control multiple launchctl targets concurrently. One example would be that you can unload everything in the user domain by not specifying a path but providing the userid. In the following example, we’ll just use $userid as a variable, but it’s worth noting that that would be, as an example, 501 for the :

sudo launchctl bootout gui/$userid

There’s another option that can be used to do the opposite from within single user mode, called bootshell. Bootshell is called similarly from single user mode:

sudo launchctl bootshell

Obtain a bearer token using curl

In the following, we set a variable called BearerToken using a simple curl to the contents of a bearer token. We do so by running a curl with data in the header for “userid” although sometimes we see this as just “user” or “username” and then a password. This hits an endpoint called authenticationendpoint although sometimes we see that called “auth” or “authenticate” – in this specific case we’re pulling the bearer token out of “id” and it’s nested in there with a name of “token”:
BearerToken=$(curl -s -X POST -H 'Accept: application/json' -H 'Content-Type: application/json' --data '{"userid”:”{userid}”,”password":"{password}"}' | sed -E 's/\},\s*\{/\},\n\{/g' File | grep  ‘”id” : “token”’)
Once we have that token we can then pass it into another API via the Authorization header when connecting. In this example we’ll just pass the BearerToken we just captured as such, to an endpoint called EndpointName to
curl -H 'Accept: application/json' -H "Authorization: Bearer ${BearerToken}”

C++ Program To Decode A JWT

Just posted a visual studio 2017 project at that includes an .exe file that, when run directly, extracts json out of an encoded jwt (and checks the signature). The encodedString variable in the jwt.cpp is a jwt that is used for extraction:

£include "pch.h" £include £include £include "jwt/jwt.hpp" int main() ¨ using namespace jwt::params; std::string encodedString = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImp0aSI6ImY4ZWQ0OTM2LTBlN2ItNDlmYi05YTkxLWM2MDQyZDEzODMzNiIsImlhdCI6MTU1NTUxODk4NSwiZXhwIjoxNTU1NTIyNTg1fQ.rsyE_KzLO99zKXC7TNFD1RkU6HYF2Y7XJuIkFKumt20"; jwt::jwt_object decoded = jwt::decode( encodedString, algorithms(¨ "hs256" ¼), false ); std::cout << decoded.header(); std::cout << decoded.payload(); return 0;

The returned json output is as follows (e.g. run as c:/mydirectory/jwt.exe):

{"alg":"HS256","typ":"JWT"}{"admin":true,"exp":1555522585,"iat":1555522585,"jti":"f8ed4936-0e7b-49fb-9a91-c604d138336","name":"John Doe","sub":"1234567890"}

There's a lot more to it that I'll take a stab at documenting at a later date. Visual Studio 2017 project as well as executables included in the project.

Linear Algebra in Python Scripts

Preparing data for tensorflow is often easiest when done as a two step process. In machine learning, you often get into trying to plot points, calculate tangents, and a lot of basic algebra. Working out equations kinda’ reminds me of being in in-school suspension in high school. Except now we’re writing code to solve the problems rather than solving them ourselves.

I never liked solving for a matrix… But NumPy is a great little framework to import that does a lot of N-dimensional array work. A few basic tasks in the following script includes a number of functions across norms, matrix products, vector products, decompose, and eigenvalues. Remove/comment what you don’t need:

import numpy as np from numpy import linalg as LA array = [[-1,4,2],[1,-1,3]] array2 = [[6,2,1],[7,1,-3]] array = np.asarray(array) converted = np.fliplr(array) #ifsquare >> cholesky = LA.cholesky(array) #ifsquare >> inv = LA.inv(array) #ifsquare >> determinant = LA.det(array) #ifsquare >> signlog = LA.slogdet(array) print print 'ONE ARRAY' print 'Sum: ', np.trace(converted) print 'Elements: ', np.diagonal(converted) print 'Solved: ', LA.norm(array) print 'qr factorization: ' print np.linalg.qr(array) print 'Hermitian: ' print LA.svd(array) print print 'TWO ARRAYS' print 'vdot: ',np.vdot(array,array2) print 'Inner: ' print np.inner(array,array2) print 'Outer: ' print np.outer(array,array2) print 'Tensor dot product: ',np.tensordot(array,array2) print 'Kronecker product: ' print np.kron(array,array2)

Managing The Xcode Simulator Programmatically

The iOS Simulator is a great way to test watchOS, tvOS, and iOS apps while you’re writing them. The easiest way to work with the simulator is through Xcode. But you can also use simctl for interacting with it, helpful in automating QA operations when possible. The simctl binary is located at /Applications/ and typically accessed as a verb from the /usr/bin/xcrun command. 

First let’s list all the simulators, done using the list command, called by simply running xcrun followed by simctl for the type of operation to be run and then the list command:

/usr/bin/xcrun simctl list

The output shows a lot of device types, runtimes, and devices, most of which should show as disconnected or shutdown:

== Device Types ==

== Device Types ==
iPhone 4s (
iPhone 5 (
iPhone 5s (
iPhone 6 (
iPhone 6 Plus (
iPhone 6s (
iPhone 6s Plus (
iPhone 7 (
iPhone 7 Plus (
iPhone 8 (
iPhone 8 Plus (
iPhone SE (
iPhone X (
iPhone Xs (
iPhone Xs Max (
iPhone Xʀ (
iPad mini (5th generation) (–5th-generation-)
iPad Air (3rd generation) (–3rd-generation-)
iPad 2 (
iPad Retina (
iPad Air (
iPad mini 2 (
iPad mini 3 (
iPad mini 4 (
iPad Air 2 (
iPad (5th generation) (–5th-generation-)
iPad Pro (9.7-inch) (–9-7-inch-)
iPad Pro (12.9-inch) (
iPad Pro (12.9-inch) (2nd generation) (–12-9-inch—2nd-generation-)
iPad Pro (10.5-inch) (–10-5-inch-)
iPad (6th generation) (–6th-generation-)
iPad Pro (11-inch) (–11-inch-)
iPad Pro (12.9-inch) (3rd generation) (–12-9-inch—3rd-generation-)
Apple TV (
Apple TV 4K (
Apple TV 4K (at 1080p) (
Apple Watch – 38mm (
Apple Watch – 42mm (
Apple Watch Series 2 – 38mm (
Apple Watch Series 2 – 42mm (
Apple Watch Series 3 – 38mm (
Apple Watch Series 3 – 42mm (
Apple Watch Series 4 – 40mm (
Apple Watch Series 4 – 44mm (
== Runtimes ==
iOS 12.2 (12.2 – 16E226) – 
tvOS 12.2 (12.2 – 16L225) – 
watchOS 5.2 (5.2 – 16T224) – 
== Devices ==
— iOS 12.2 —
    iPhone 5s (4A2CC670-55EF-4B36-896F-EC2009EDEC07) (Shutdown) 
    iPhone 6 (937105ED-AEF1-4487-B406-1795D9AD9243) (Shutdown) 
    iPhone 6 Plus (E4031984-D79E-4888-A104-0C6DA73EB67F) (Shutdown) 
    iPhone 6s (EA859DD2-D934-4CB1-B2D5-055F1DF93FB9) (Shutdown) 
    iPhone 6s Plus (CFFD27D8-4FEE-4632-B3BB-8133DBF74925) (Shutdown) 
    iPhone 7 (66BE2C4D-CB66-4618-A95D-BF239C569965) (Shutdown) 
    iPhone 7 Plus (3C6B97F3-AF19-49A9-B400-09A5CBCCB3D6) (Shutdown) 
    iPhone 8 (2D18B685-A642-44E5-BF8E-6D09AB478B0F) (Shutdown) 
    iPhone 8 Plus (BF652604-8F18-457C-B111-E951E8B55947) (Shutdown) 
    iPhone SE (384E1A51-7354-4FAC-A1A8-CB2B9CC5D1CF) (Shutdown) 
    iPhone X (98DD2AEC-4566-4896-83E5-E0B8603FFE9E) (Shutdown) 
    iPhone Xs (02A90E87-B2C4-44FE-9477-DD9455D7CB0C) (Shutdown) 
    iPhone Xs Max (79F42764-5020-41EA-87C3-55C541A790F5) (Shutdown) 
    iPhone Xʀ (AD6FD253-20A7-432C-8C22-5070489E787E) (Shutdown) 
    iPad Air (3rd generation) (DAB405D3-C1FD-47ED-B4FE-F0E1857A2862) (Shutdown) 
    iPad Air (3216E338-D522-43C7-9484-D7AEA081E926) (Shutdown) 
    iPad Air 2 (6B0BCC75-0ED6-4FC9-94C5-48A3466B79AD) (Shutdown) 
    iPad (5th generation) (24313239-A853-46EB-B5A3-0DD8A86080F2) (Shutdown) 
    iPad Pro (9.7-inch) (8E2BEE13-D726-4CF5-8388-0913B87495F1) (Shutdown) 
    iPad Pro (12.9-inch) (9493C54B-D61E-4D42-8952-A89C2CCF2FDD) (Shutdown) 
    iPad Pro (12.9-inch) (2nd generation) (5D978189-856D-4598-8C09-876BD832C71F) (Shutdown) 
    iPad Pro (10.5-inch) (2BF88E18-8C89-4515-A486-DC72C7A8629E) (Shutdown) 
    iPad (6th generation) (016DAA95-D917-4CD9-9A54-700D01BAF1AE) (Shutdown) 
    iPad Pro (11-inch) (307BEEDD-8652-4438-944B-CB423A26CC9E) (Shutdown) 
    iPad Pro (12.9-inch) (3rd generation) (D893291C-F214-4B43-A54F-3AB95A5442ED) (Shutdown) 
— tvOS 12.2 —
    Apple TV (1562B2B3-F403-4C99-8026-20AA51C8716B) (Shutdown) 
    Apple TV 4K (6C5CC68C-4C01-4097-91B8-A503B465F961) (Shutdown) 
    Apple TV 4K (at 1080p) (B8DCEFC3-F5BC-455D-B8B7-BAE7A48BE032) (Shutdown) 
— watchOS 5.2 —
    Apple Watch Series 2 – 38mm (06938C62-9757-4F5E-913F-F9639D8AFF9C) (Shutdown) 
    Apple Watch Series 2 – 42mm (BBA6DFC3-BC5A-494F-AFF4-E2B1331AFC69) (Shutdown) 
    Apple Watch Series 3 – 38mm (2D70BA7B-66BF-43E1-9F80-20EEFF588BB5) (Shutdown) 
    Apple Watch Series 3 – 42mm (F0E4E11E-639C-4F45-974A-2AAC684F1411) (Shutdown) 
    Apple Watch Series 4 – 40mm (B0CC419F-220F-46E1-B827-B512B08552B6) (Shutdown) 
    Apple Watch Series 4 – 44mm (7DAE1296-C9FF-4759-A066-1BA42A259853) (Shutdown) 
== Device Pairs ==
620743A8-FD31-408C-AEBF-8D0F0849BD9D (active, disconnected)
    Watch: Apple Watch Series 4 – 40mm (B0CC419F-220F-46E1-B827-B512B08552B6) (Shutdown)
    Phone: iPhone Xs (02A90E87-B2C4-44FE-9477-DD9455D7CB0C) (Shutdown)
20E13C7F-3788-4DA5-962A-FF1389CDDA12 (active, disconnected)
    Watch: Apple Watch Series 4 – 44mm (7DAE1296-C9FF-4759-A066-1BA42A259853) (Shutdown)
    Phone: iPhone Xs Max (79F42764-5020-41EA-87C3-55C541A790F5) (Shutdown)

Next, let’s create a fresh new spiffy simulator called testing_iPhone7. To do so we’ll 

/usr/bin/xcrun simctl create testing_iPhone7

The output includes a UUID such as the following. That can then be used to track further interactions with the simulation:


The most common tasks would be booting, shutting down, erasing, and opening simulations. First let’s boot it up:

/usr/bin/xcrun simctl boot E6D4C2B8-0601-4557-99DA-B6B8251D534D

To shut that same simulator down use the shutdown verb:

/usr/bin/xcrun simctl shutdown E6D4C2B8-0601-4557-99DA-B6B8251D534D

Neither of these commands provide any output on success, but do error on failure. Once you’ve run tests, I like to erase my simulator and start fresh. To do so, simply use the erase command:

/usr/bin/xcrun simctl erase E6D4C2B8-0601-4557-99DA-B6B8251D534D

To open the simulator you loaded, you can use the open :

open /Applications/

Simulator App

For more information on using simctl subcommands, use the help subcommand:

/usr/bin/xcrun simctl help

Notice there are a lot of verbs, which I’ll cover further in later articles:

create              Create a new device.

clone               Clone an existing device.
upgrade             Upgrade a device to a newer runtime.
delete              Delete a device or all unavailable devices.
pair                Create a new watch and phone pair.
unpair              Unpair a watch and phone pair.
pair_activate       Set a given pair as active.
erase               Erase a device’s contents and settings.
boot                Boot a device.
shutdown            Shutdown a device.
rename              Rename a device.
getenv              Print an environment variable from a running device.
openurl             Open a URL in a device.
addmedia            Add photos, live photos, videos, or contacts to the library of a device.
install             Install an app on a device.
uninstall           Uninstall an app from a device.
get_app_container   Print the path of the installed app’s container
launch              Launch an application by identifier on a device.
terminate           Terminate an application by identifier on a device.
spawn               Spawn a process by executing a given executable on a device.
list                List available devices, device types, runtimes, or device pairs.
icloud_sync         Trigger iCloud sync on a device.
pbsync              Sync the pasteboard content from one pasteboard to another.
pbcopy              Copy standard input onto the device pasteboard.
pbpaste             Print the contents of the device’s pasteboard to standard output.
help                Prints the usage for a given subcommand.
io                  Set up a device IO operation.
diagnose            Collect diagnostic information and logs.
logverbose          enable or disable verbose logging for a device

Next up, we’ll look at performing tasks in the Simulator in the next article on regression testing with the Simulator app.