Blog Stats
  • Posts - 144
  • Articles - 0
  • Comments - 36
  • Trackbacks - 0

 

Friday, April 19, 2013

Apple Networks


Just interested. (and I may be asking for it). Got a bigger Apple network than me? (you must have) IMG 0021

Monday, March 25, 2013

Super stylin


Firstly most impressed that I can now blog from my ipad courtesy of Blogpress.com

Self promoting my ios bin collections app for scambs.


https://itunes.apple.com/gb/app/scambs-bin-collections/id596758915?mt=8


- Posted using BlogPress from my iPad

Location:Cambridge Road,Waterbeach,United Kingdom

Thursday, January 3, 2013

Excel ODBC on OSX, Connect to SQL Server


Oh goodness. What a shocker. How hard can it be, to simply make Microsoft Office Mac (Excel) connect to Microsoft SQL Server. I've spent the last 2 hours being told to go spend $xx to go buy ODBC drivers and stuff. In this respect MS 1, Apple (or maybe Microsoft nil/NSNull) 0. I have finally arrived at - http://www.actualtech.com Which does the job, quite nicely, costs $xx (check it out); however bit of a fluff. But I guess this is what it takes to keep hi-tech. firms thriving. + Happy New year

Thursday, October 18, 2012

Clean SOAP Calls from iOS - SudzC


This is worth another mention.

Sudz

If you need to call SOAP web-services from iOS or Javascript, and lets face who doesn't. http://SudzC.com really delivers.

You give it the URL to you're WSDL file (or upload a file) and it just spits out a ready to go Xcode project.

I would point out that to get it to work 100%

I changed line 204, in Soap.m (commented out line is old version, mine is below)

//if([child respondsToSelector:@selector(name)] && [[child name] isEqual: name]) { if([child respondsToSelector:@selector(name)] && [[child name] hasSuffix: name]) {
I consumed a Microsoft Dynamics NAV set of web-service pages no problem (and they tend to be fairly complex WSDL definitions).

Monday, August 27, 2012

Time Capsule With Raspberry Pi


So I have a Raspberry PI, with an 1TB external USB HD plugged into it. I have Debian Wheezy installed to which I added the NetaTalk package. Unsaved Preview Document Following this guide which is on Ubuntu, but was easy enough to understand - http://kremalicious.com/ubuntu-as-mac-file-server-and-time-machine-volume/ I was even able to change the icon to look like an X-Serve :-) Next step to add a second HD that will backup my Windows 8 laptop as well.

Monday, July 30, 2012

Part 3–PassBook Server


So far we have covered some basic principals, a simple database schema to store pass-jobs.   Next step is to go about actually tie all this together and generate some passes.

I’m being careful to avoid talking specifics of how Apple Passbook works as this is still subject to NDA.   However I can point out that I have worked out all principals using pass generators in the public domain,  i.e

http://passsource.com/

http://passk.it/

Using these websites you can download sample boarding passes, tickets and coupons and rename the .pkpass files back to .zip.    So without breaking any of the terms of the NDA I have reverse engineered these samples to produce this guide.

Insider the zip you have the following base elements -

icon.png
icon@2x.png
logo.png
logo@2x.png
manifest.json
pass.json
singature

 

By playing around with passk.it and passsource, you can see what the icons and image files are.   The meat of actually what happens, is in manifest.json,  pass.json and signature

Manifest.json looks like this -

{
    "pass.json" : "de440478cd0db57d35474d88f455e0bcdd0d3864" 
,    "icon.png" : "ba47a8021c8d74d2146d7244c8a0566be37df43b" 
,    "icon@2x.png" : "bd5442b4b08aa4dde333ec9ef0269e7fd93140b3" 
,    "logo.png" : "780540b3a324bf66aeaee2d352283371356e9502" 
,    "logo@2x.png" : "a718ffd4e611e404dd3eb701454bcaefdabbe311" 
}

Its a JSON dictionary of all the files that make up you’re pass excluding the manifest.json itself and signature.

The long hex number alongside is the SHA1 hash of the bytes of each file.  In C#  I wrote a bit of code to loop through all files and generate these hash’s as following -

 private string generatehash(string filePathAndName)
        {
            byte[] fileData = File.ReadAllBytes(filePathAndName);
            return generatehash(fileData);
        }

        private string generatehash(byte[] fileData)
        {
            string hashText = "";
            string hexValue = "";

            byte[] hashData = SHA1.Create().ComputeHash(fileData); // SHA1 or MD5

            foreach (byte b in hashData)
            {
                hexValue = b.ToString("X").ToLower(); // Lowercase for compatibility on case-sensitive systems
                hashText += (hexValue.Length == 1 ? "0" : "") + hexValue;
            }

            return hashText;
        }

A little bit of string handling is required to build the manifest.json file up.   But once you’ve looked at File.IO at getting a list of files in a given directory its plain sailing using the algorithm above.

The lion share of the work goes on in pass.json,   this file describes exactly what’s on a pass.  A sample of this, is shown below -

{
    "relevantDate" : "2012-07-28T04:10Z"
    ,"locations":[
        {"longitude":-122.3748889, "latitude":37.6189722}
    ]
    ,"barcode" : {
        "message" : "barcode"
        ,"format" : "PKBarcodeFormatPDF417"
        ,"messageEncoding" : "iso-8859-1"
        ,"altText" : "alt barcode"
    }
    
    ,"logoText" : "Skyport Airways","foregroundColor" : "rgb(22, 55, 110)","backgroundColor" : "rgb(50, 91, 185)"


    ,"boardingPass":
    {
         "transitType" : "PKTransitTypeAir"
        ,"headerFields":[{"key":"gate","label":"GATE","value":"23","changeMessage":"Gate changed to %@."}]
        ,"secondaryFields":[{"key":"passenger","label":"PASSENGER","value":"Mike H","changeMessage":"Passenger changed to %@."}]
        ,"auxiliaryFields":[{"key":"depart","label":"SAN FRANCISCO","value":"SFO","changeMessage":"Origin changed to %@."},{"key":"boardingTime","label":"DEPART","value":"2:25","changeMessage":"Boarding time changed to %@."},{"key":"flightNewName","label":"FLIGHT","value":"815","changeMessage":"Flight number changed to %@"},{"key":"class","label":"DESIG.","value":"Coach"},{"key":"date","label":"DATE","value":"7\/22"}]
        ,"backFields":[{"key":"passport","label":"PASSPORT","value":"Canadian\/Canadien"},{"key":"residence","label":"RESIDENCE","value":"5780 E Mission St, San Jose, CA"},{"key":"terms","label":"TERMS","value":"stuff"}]
    }


    ,"organizationName" : "ORGNAM"
    ,"serialNumber" : "1234"
    ,"formatVersion": 1
    ,"passTypeIdentifier" : "pass.com.binaryrefinery.www.boarding"
    ,"webServiceURL" : "http://192.168.0.1/passserver/"
    ,"authenticationToken" : "D9BB5A2D-9BDA-4E01-9480-604F235BCDFF"
    ,"teamIdentifier" : "TEAMID"
    ,"description" : "Boarding Pass"
}

So in article 1, I showed what my template file does.    My code substitutes values from a table of database fields into this file.   I have a straight table for writing in individual field value like the barcode value i.e  $$Message,  + others for substituting fields into the JSON dictionaries for headerFields, secondaryFields etc.

See article 2, for details of all the tables I am using.

Security is implemented by a couple of means.    The organizationName, passTypeIdentifier and teamIdentifier tie the pass to a given provider as verified by Apple.

To get these you will have to signup for an Apple Registered iOS developer account (about £60/$99 PA).   Worth doing, and give you all the NDA details that I can’t yet discuss.

The Organisation Name, is tied to you too,  so companies that generate passes for lots of organisations will need to create a developer account for each they represent;  or use a blanket one to cover them all.

The webServiceURL/Authentication Token is how you are able to update the pass once deployed.   This is strictly NDA.  So we will cover this in future articles.

Once you’ve built you’re pass.json.      That too needs to be included in your manifest.json file along with its SHA1 hash.

The next piece of the jigsaw it to produce a signed version of the manifest.json file which lives in a file called signature.

To sign the file,  you will need to generate a pass signing cert.   Once again this is done through the Apple Developer website as a registered developer.   I exported this signature from my Mac that generated the certificate as a p12 file and exported it to my Windows PC that I’m using for this project (then imported it).

I also needed on my Windows machine to install a trusted root certificate from Apple.

I got the ‘World Wide Developer Relations’ cert from -

http://www.apple.com/certificateauthority/

So in code the first thing I needed to-do is pull the correct cert out of the certificate store on my windows machine.  Code to achieve this shown below -

private X509Certificate2 getServerCert(string nameofpass)
        {
            // Open the cert store on the Local Machine
            X509Store store = new X509Store(StoreLocation.CurrentUser);

            if (store != null)
            {
                // Store exists, so open it and search through the certs for the Apple cert


                store.Open(OpenFlags.ReadOnly);
                X509Certificate2Collection certs = store.Certificates;

                if (certs.Count > 0)
                {

                    for (int i = 0; i < certs.Count; i++)
                    {

                        X509Certificate2 cert = certs[i];
                        Console.WriteLine(cert.Subject);
                        if (cert.Subject.ToLower().Contains(nameofpass)) // this finds the relevant cert
                        {
                            // Cert found, so return it
                            return certs[i];
                        }
                    }
                }
            }
            return null;
        }

This bit of code does the trick,  matching a pass’s name to that stored in the machine (in my case users) certificate store. 

Next bit was to use this cert to sign the manifest file. I pass in the contents of the manifest file as a string (I do it that way, because I want to-do as much stuff in memory) -

private byte[] signit(string manifest)
        {
            byte[] manifestbytes = ASCIIEncoding.ASCII.GetBytes(manifest);

            ContentInfo contentinfo = new ContentInfo(manifestbytes);
            SignedCms signedcms = new SignedCms(contentinfo, true);

               CmsSigner oursigner = new CmsSigner(ourcert);
            signedcms.ComputeSignature(oursigner);
            return signedcms.Encode();
        }

 

So there we are,  a signed and populated pass.   Final stages are to ZIP the contents to produce a single .pkpass file.

I used the Sharp2Zip .net library.  This provides all that you need to construct the zip.

For details -

http://www.icsharpcode.net/opensource/sharpziplib/

 

The final element is deploying this to your users.   Obviously this may vary depending on your application.  For my simple needs I wanted to deploy my passes view a web-server.  However you can deploy from email too.

I created a very simple pass.htm containing a link to my pass,  that looks as follows -

<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
</head>
<body>
<a href="boarding.pkpass">Get You're Pass</a>
</body>

</html>

So obviously this would need to have protection in code around it, to restrict which users could access which passes.

I copied my pass.htm and boarding.pkpass onto a web-server (note this works great on Azure too).    You need to add the pkpass mime type to your web server.    This is

.pkpass AS application/vnd.apple.pkpass

Net result hit the web-page from an iOS 6 Simulator (again you need that Apple developers account to get this).

Click the link and the pass installs.

Quite a few steps, but you’ve only got to go through them once.

Wednesday, July 25, 2012

Part 2–PassBook Server


So now that we’ve established we are going to-do a glorified mail merge to build up our individual passes.   The next step is to construct a database that is going to drive the entire process.

 

image

I’ve built my data structure in SQL Server,  and I thought I would walk you through the tables I’ve built and show you how we’ll use them in the full solution.

Our initial aim, is just to produce the passes so I’m going to concentrate on that aspect.   In future posts we will look at how we send updates to passes (to use an Apple example,  boarding gate changing on a boarding pass).

Its only 4 tables,  so please bare with me as I describe their purpose.

 

Table – PassFoundation

The role of this table, is to hold the foundation types of passes that we are able to produce and where the mail merge template is stored on disk.  Structured as follows:

PassTypeIdentifier varchar(50) – PK
Active From datetime – PK
Stationary Folder Path varchar(255)
OutputName varchar(50)

Descriptions -

PassTypeIdentifier = pass.com.binaryrefinery.www.boarding
Name of path as setup in Apple developer portal (more on this later)

Active From = 1 JAN 2012


Stationary Folder Path = \Projects\PassMaker\PassMaker\Stationary\BoardingPass
Stationary path is where all the icons etc. are stored for this path. + a template.json as described in last article.

OutputName = boarding
What to call the pass when it is produced

 

Table – PassJob

Holds a list of jobs i.e a list of passes that need producing.  Structured as follows:

PassTypeIdentifier varchar(50) – PK
SerialNumber varchar(50) – PK
Completed Bit
Created datetime
Updated datetime

Descriptions -

PassTypeIdentifier = pass.com.binaryrefinery.www.boarding

Serial Number = unique serial number for this job,  i.e produce me a boarding pass serial number 1234,  it is the foreign key we use for describing this individual pass.

Completed = whether job has been processed or not.

 

Table – PassJobField

Stores individual fields that we want to substitute into our pass, i.e Relevance Date, or Barcode.  This is the heart of our Passbook engine.

fieldname varchar(50) = PK
SerialNumber varchar(50) – PK
PassTypeIdentifier varchar(50) – PK
Value varchar(50)
Datatype int
Sequence int
Locale varchar(2)

So this is used to store our substitutes that we can mail-merge into our passtemplate for a given pass type and a given field for a given serial number.

Table – PassJobSectionField


Finally.   For the different section of the pass we need to store the more complex structured fields, like passport number, terms and conditions etc.   This has a similar structure to the above but contains a few more formatting options.

SerialNumber varchar(50) – PK
PassTypeIdentifier varchar(50) – PK
PassSection int – PK
label varchar(50) – PK
key varchar(50)
value varchar(1000)
changeMessage varchar(50)
Locale varchar(2)
Sequence int
TextAlign int

Description -
So this would hold we have a field called ‘Passenger’, with a value of ‘Richard Jones’,  that would exist in the primary fields section of our pass.    All of this is held for a given type of pass and for a given serial number.

 

So next time, we’ll look how can can build a .net service for using all this data to build fully automatically our own pass and issue it out to an iOS device.

Tuesday, July 24, 2012

Part 1–PassBook Server


 

So before we talked about the potential of building a server to issue and maintain Passbook passes.   The design goal to being able to issue boarding passes, concert tickets, etc. to iOS devices.

The starting point is to build a template pass that we can substitute (mail merge style),   the values that we need for our pass.   i.e to change the attendee name on each visitor pass we issue.

A passbook pass is essentially a ZIP achieve file digitally signed.    The  content of the pass is maintained with a fairly simple JSON fill,  named pass.json.   We’ll use this file as our foundation.

This is my proposed format that our server will use to build up our passes -

{
    "$$relevantDate"
    ,"locations":[
        {"longitude":-122.3748889, "latitude":37.6189722}
    ]
    ,"barcode" : {
        "$$message"
        ,"format" : "PKBarcodeFormatPDF417"
        ,"messageEncoding" : "iso-8859-1"
        ,"$$altText"
    }
    
    ,"logoText" : "Sun Airways","foregroundColor" : "rgb(22, 55, 110)","backgroundColor" : "rgb(50, 91, 185)"


    ,"boardingPass":
    {
         "transitType" : "PKTransitTypeAir"
        ,"$$headerFields"
        ,"$$secondaryFields"
        ,"$$auxiliaryFields"
        ,"$$backFields"
    }


    ,"organizationName" : "Richard Jones"
    ,"$$serialNumber"
    ,"formatVersion": 1
    ,"passTypeIdentifier" : "pass.com.binaryrefinery.www.boarding"
    ,"webServiceURL" : "https:\/\/www.binaryrefinery.com\/passhandler\/"
    ,"authenticationToken" : "12345678901234567890123456789012"
    ,"teamIdentifier" : "D3ZDFF92AK"
    ,"description" : "Boarding Pass"
}
 
My servers role will be to issue passes by substituting any variable that begins $$ into the pass body.
We will be using all Microsoft ‘stuff’ for the backend server;  so this is a good example of end-to-end integration.

Debugging Passkit Install on iOS Simulator


Top tip, this just saved my life in OSX Terminal run - tail -f /var/log/system.log This let me debug what was going on with a faulty Passbook pass (well faulty since iOS 6 beta 3) Pic

Monday, July 16, 2012

PassBook Server - Goals


So Apple releases the Autumn/Fall iOS 6. Included feature PassBook looks fantastic. The ability to store all those loyalty cards, coupons, tickets and travel documents in a unified interface looks compelling. Passbook 2246204b Being of Microsoft grounding (c#) and latterly Objective C, I figured it would make an interesting project to start building a server component to issue and maintain PassBook tickets. My design goal. Serve a large population, i.e festival goers ticket/airline boarding passes with iOS installed tickets. How could you issues, maintain and secure on large scale? How would you build it? What would you use? Would it work? Could it be hosted in the Cloud? Project time….
 

 

Copyright © Richard Jones