pátek 21. listopadu 2014

Camera Confidentiality Conundrum

One of BABEL's features allows you to capture a photograph using your device's camera then send the image as an attachment. This ability is important for users so they can send images of documents or developing events to their contacts. Originally BABEL would use the device's native camera application to take the photo, however we discovered a serious security flaw with this approach. On many Android devices the native camera app would automatically save photos taken by BABEL, and if the user had cloud backup enabled would also upload them to their cloud service. Obviously this is an unacceptable privacy violation for BABEL so we needed to implement a solution.

The solution we came up with was to develop our own simple camera activity which BABEL could use to capture images. By controlling the image capturing process we can ensure that the photo stays private and is not saved outside of BABEL. This was not a simple task unfortunately, to recreate the vast set of features available in native camera apps would take an enormous amount of development time. So we had to aim to include only the most important camera features in our app.

The features we decided to include were auto-focus, zoom and flash. Auto-focus and Flash were relatively simple to implement using the Android camera API, but the zoom was slightly more complicated. Anybody used to touch-screen devices recognizes the pinch to zoom gesture, surprisingly there is no standard utility in the Android framework for this. So firstly we needed to implement a gesture detector for this that would control the camera's zoom level. Another issue we encountered was a large variance in the number of zoom levels available on each device, some cameras we tested supported 3-4 times as many zoom levels as others! To normalize the zoom behaviour across all devices we added scaling to our zoom gesture detector. Now if the user does a 'pinch' that travels half the length of the screen, the device will perform the maximum zoom change with smaller gestures performing a zoom relative to this maximum.

So with this new camera activity included in BABEL's next release can be confident that photos sent as attachments will remain private and not be accidentally leaked by a third party app. The need for a custom camera was an unanticipated problem which demonstrates the importance of our rigorous testing for each release. In the future we may revisit this custom camera to offer a better, more fully featured camera to BABEL users.

pátek 7. listopadu 2014

UIDocumentInteractionController in landscape mode

The whole iOS version of Babel works in portrait mode, but since we implemented attachments, we wanted to display attachment previews in landscape mode also. We tried it at first with UIDocumentInteractionController, which is displayed modally on UINavigationController.

So the whole app is in portrait mode and only UIDocumentInteractionController is in both portrait and landscape. It worked great, but when you at first turn the iphone to landscape and then display UIDocumentInteractionController, you will see the preview, but the navigation bar is missing. So you cannot get out of this screen, in iOS 8, it looks like this:




In iOS 7, it's ok:


We tried using QLPreviewViewController, but displaying it modally on UINavigationController was the same. Then we tried to push it on the navigation stack with pushViewController:animated and finally it worked on both iOS versions 7 and 8.


However there is one issue with QLPreviewViewController that only occurs in iOS 8 (iOS7 is ok). When you try to play some sound in this preview and turn to landscape, then when you go back (dismiss QLPreviewViewController), the sound continues playing. If you do the same thing in portrait, it stops playing.

pondělí 13. října 2014

Teambuilding

Last weekend our team went to play Paintball near Prague. It was very good fun, as you can see from the pictures. The team enjoyed the game almost as much as their work! ;)






úterý 30. září 2014

Core data - metadataForPersistentStoreOfType fails after iPhone restart.

In our application, we often need to do core data migration when we create a new release. To do this we first need to get the metadata from our app’s persistent store,  so that it can be migrated. We use the following line of code for this:

[NSPersistentStoreCoordinator metadataForPersistentStoreOfType:NSSQLiteStoreType URL:self.storeURL error:&error];

However, we noticed that after restarting the iPhone, our application wasn’t able to run. We discovered this error in the log:

Error Domain=NSCocoaErrorDomain Code=256 "The operation couldn’t be completed. (Cocoa error 256.)" UserInfo=0x146570e0 {NSUnderlyingException=error during prepareSQL for SQL string 'SELECT TBL_NAME FROM SQLITE_MASTER WHERE TBL_NAME = 'Z_METADATA'' : attempt to write a readonly database, NSSQLiteErrorDomain=264}


We determined that this is a core data bug, if you do not need to call metadataForPersistentStoreOfType you won’t see that there is a problem.  We noticed that this bug occurs only if we use WAL journal mode in SQLite, when we changed it to DELETE journal mode the app worked as expected.

pondělí 15. září 2014

Using SQLite database in Portable Class Library

I am a member of the team who are developing the C# .NET version of the secure messaging application called Babel.

One of the components which we need is database.  We chose SQLite for this component because it is optimal for our project and recommended for the Portable class library (PCL). We also want to use a framework for Object-Relation Mapping (ORM). After trying several options we decided to use SQLite-NET and its extension for object relationships SQLite-NET Extensions . This setup initially looked good but after some testing we discovered that the SQLite components target .NET 4.0, Win 8, WinPhone 8.1, Silverlight 5 and WinPhoneSilverlight 8.1. However our PCL needs to target .NET 4.5, Win 8.1 and WinPhone 8.1. This is a big problem because we are unable to use the SQLite component in the current build of our PCL.

We download both projects from GIT and delete every project which we cannot use (there are projects targeting every platform) then change the targeted platforms for the PCL projects to .NET 4.5, Win 8.1 and WinPhone 8.1. This will generate many errors in the code that we will need to repair before the project will build. But once the project does build the PCL components will all have the correct target platforms that we can use in our project.


If you want this component with the same target platforms here is a zip containing the compiled C# .NET libraries.

pátek 29. srpna 2014

New version of Babel Business Edition with attachments is out now!

So what is new?

We have just released a new version of our app which now includes some cool new features. The most important change is the ability to send and receive attachments, this includes any type of file but you can also capture images, video and audio to send as an attachment if your device has the capabilities.

Other improvements include displaying a contact's current status, a green icon next to the contact's name indicates they are online and a grey icon indicates they are offline. We have also introduced a new feature called 'message expiration', which gives you the opportunity to set a time period after which your message should expire if not delivered. Lastly you can set to be notified if your message has fallen into an "unsent" status – making sure you don’t miss out on actually sending your message!


Go to the App Store and Google Play to update your current version of Babel and get these cool new features.




středa 13. srpna 2014

Ignore certificate errors on Windows & Windows Phone

Introduction

Our team is also currently working on .NET version of secured messaging application Babel. To put it simply, main goal is to port great and useful Android & iOS app to Windows desktop (Vista, 7, 8), Windows 8.1 (Metro) and Windows Phone 8.1 - both known as "Universal apps".
At first, I'll try to explain the problem. Except the mentioned Babel, we've got also the second version, targeted to corporations and called Babel Bussiness Edition. This one is based on fact, that every company owns their private server and all communication comes through this one, so there is no third-party server. There is an authentication based on certificate, which is signed by our company. Essentialy, when user connects to server we needs to verify server identity and depending on that enable or disable the communi- cation. Of course, .NET framework does not trust certificates, which he cannot find or successfully compare with any from root trusted certification authorities. When you will try to initialize server connection secured with these type of certs, an exception will be raised. In this blog post, I will try to describe how to easily ignore certificate errors on:

  • Windows desktop client (WPF, WinForms etc.)
  • Win 8 (Metro), Windows Phone 7, WP8, WP8.1 Silverlight
  • Windows 8.1, Windows Phone 8.1 RT - Universal apps

Windows desktop client

Pretty easy, well known stuff:
//Set certificate validation delegate
private void SetCertValidationDel()
{
  //you can use ServicePointManager class
  System.Net.ServicePointManager.ServerCertificateValidationCallback += CertValidation;
}

//This method will be raised, when initializing https connection
private static bool CertValidation(
object sender,
System.Security.Cryptography.X509Certificates.X509Certificate cert,
System.Security.Cryptography.X509Certificates.X509Chain chain,
System.Net.Security.SslPolicyErrors sslPolicyErrors)
    {
      return true;
      //All cert will be considered as valid - recommended for testing.
      //Or your own implementation of cert validation.
    }
}

Win 8, WP7, WP8, WP8.1 (Silverlight)

You simply cannot use previous example, because missing some classes like ServicePointManager, X509Chain etc. I've found two solutions for this problem:
  • Install certificate to root cert. store of device.
Upload the certificate somewhere on the internet (mail, cloud service etc.) and access it directly from concrete device. The cert will be installed automatically to device root certification store.
  • Install certificate to root store of application.
Using certificate extensions destribed here.
You'll need to export server cert to DER file, copy to application, set build action to "Content" and always copy to output directory. The last step is to edit package.appxmanifest file.

Windows 8.1, WP8.1 RT - Universal apps

Up until Windows 8.1 & WP8.1 you could not ignore certificate errors in Windows Store apps with classic System.Net.Http.HttpClient class. Now you can do this with new  namespace Windows.Web.Http and Windows.Web.Http.Filters.
//Initialize new instance of HttpBaseProtocolFilter, which implements IHttpFilter.
var filter = new HttpBaseProtocolFilter();
//Untrusted and Expired cert. errors will be ignored in this example:
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted);
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Expired);
//Initialize new instance of HttpClient with IHttpFilter parameter.
var httpClient = new Windows.Web.Http.HttpClient(filter);
The ChainValidationResult is simple Enum and a list of possible values can be found here. Note that you should use this technique only in very limited type of scenarios (tests etc.). You should ever ensure that target you are hitting is the correct endpoint instead of ignore certificate errors.