Vector images on Xcode 6

One of the new features of Xcode 6 is the capability to use vector instead of rasterised images. For some unknown reason, this has been done a little bit trickier than expected from the Apple people. here I will use the tabbar as example.

The first thing that surprises anybody when creates a new project with storyboard and a tabbar view controller is the fact that Apple creates two view controllers for you, and this two view controllers have two images, named first and second, that are not regular png/gif images, but PDF! Still to understand the reason Apple did not gave direct support for SVG files, but we will have to live with that…

First of all, needed tools, if you are plenty of money, why not getting Adobe Illustrator, but if you are a developer and does not really need any of the cutting edge Illustrator functionalities, another good alternative if Inkscape. To install Inkscape, first you will have to install quartz.
Is a little more difficult than a regular OS X program, but after installing both applications Inkscape should work perfect (mind rebooting after installing XQuartz)

One we have sorted out the tools to use, we need an image, we can download any SVG file we would like from much of the free of charge icon libraries on the internet, or create our own from scratch (if you are mainly a developer, maybe it would be better to start downloading one…), once we have an image in Inkscape, we need to define the size of the canvas, in the case of the tabbar, we will create a canvas of 37.5×37.5px, to do that we will go to File-Document Properties, then in the pop up window that will open, we will see the first tab named Page, in which we can put our custom size, as stated before we will put here 37,5px for width and height.

Now it is time to scale the image to fit inside the canvas, as we are dealing with vector images there is nothing to worry about, and we can scale (object-scale-second tab/Scale) as much as we want, and use the arrow tool to place it inside the canvas.

When you will be happy with the image, save it with PDF 1.5 format (“Save as” command).

And finally we arrive to the Xcode App, we should open the images.xcassets of our app, and there we can deploy the PDF or click on the + icon on the bottom to create a new file.
To be purist, the image generated is a generic image with 1x 2x and 3x empty slots to put our images, but Apple just have one universal image for that, as we don’t want to be less than Apple, we will make our images behave the same.

To make a single universal image, we should open the image in the Finder App, and open the Contents.json file that is kept in the same folder as the image we are editing.

The file should state similar at this:
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "image.pdf"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

We should remove all unused scales, and the scale part of the one containing the filename, so it should behave like this:
{
"images" : [
{
"idiom" : "universal",
"filename" : "message.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

As always, less is more…

Now you can use your new vector image in the tabbar.

Cisco IPSec VPN and native Mac support

This post is intented to be a merge of two of the technologies of my life. In one hand Cisco networking with the old IPSec VPN, and on the other hand OSX, which has been a good friend in my iOS development career.

I was using Cisco anyconnect in the past (let’s say “the new” or “the good” solution), but dealing with updates on the client of the router on each OSX new version is something that can keep more than one out of the anyconnect option.

Here we will address two configuration, firstly we will explain the data needed to configure a Cisco IPSec VPN, and then we will go further explaining the steps needed to configure one, in the first step, we will address Cisco router configuration, and then we will be able to configure it on the MAC.

The IPSec has two steps to start, in first step manages the ISAKMP tunnel, and on the second step is created the IPSec tunnel for the data. The data to know before start is:

  • GROUP name
  • GROUP password
  • Username
  • Password
  • Local network
  • Remote VPN network

All the rest of the configuration can be fine-tuned, but isn’t important to the client (will work if not modified, but Apple does not support all the options on hashing does not support header compression).

Network traffic and NAT configuration

First we will specify clearly which IP addresses will be used localy, which address will be used remotely, and the traffic we will encrypt, for the example, the network will be:

  • Local network (*): 192.168.1.0/24
  • Remote VPN network (*): 192.168.2.0/24
  • VPN Pool name: VPN-POOL
  • VPN Pool address: 192.168.2.1-192.168.2.100

(*) Please note it would be a good idea to use another IP addresses, as many local networks are default configured with these adresses, and can make the VPN unusable, any 192.168.x.0/24 keeping x greater than 2 could be a good option.

We will configure the VPN Pool with the VPN remote addresses, the access-list to define traffic to encrypt and will modify the current NAT access-list to avoid NATing of the VPN traffic (**), we will assume the VPN access-list is 101 and the NATed access-list is 100:

ip local pool VPN-POOL 192.168.2.1 192.168.2.100
access-list 100 remark NAT
access-list 100 deny ip 192.168.10 0.0.0.255 192.168.2.0 0.0.0.255
access-list 100 permit ip 192.168.1.0 0.0.0.255 any
access-list 101 remark VPN Traffic
access-list 101 permit ip 192.168.2.0 0.0.0.255 192.168.1.0 0.0.0.255

(**) NAT configuration excluded from the example, any using access-list would work

ISAKMP negotiation

The first part of the ISAKMP configuration has nothing to do with the parameters to configure on the OSX, so just copying and pasting this will work, we are free to define more negotiation types here (just with other preference than 20). In the next part we are using MY_IPSEC_VPN_GROUP for the group, and MySharedKeyForTheIPSecVPNGroup as the password, please change with the data collected at the begining of the configuration, here you must change and with the prefered aaa authentication and authorization methods (normally in small routers local, but could be any)

crypto isakmp policy 20
encr 3des
authentication pre-share
group 2
crypto isakmp keepalive 20
crypto isakmp xauth timeout 60
!
crypto isakmp client configuration group MY_IPSEC_VPN_GROUP
key MySharedKeyForTheIPSecVPNGroup
pool VPN-POOL
acl 101
crypto isakmp profile VPNClient
description VPN Clients profile
match identity group MY_IPSEC_VPN_GROUP
client authentication list <Put here a local authentication method>
client authorization list <Put here a local authorization method>
client configuration address respond

If local authentication and authorization is used, it would be needed to configure a local user, to prevent local access to the router configuration, it would be needed to not specifing the privilege for the user:
username <VPN user> password <password>

Basic IPSec negotiation

The next step is to provide the basis of the IPSec tunnel, here we will assume 3DES for encryption and SHA for hashing, we have to remember here that the OSX does not provide header compression, so we should never enable it.

crypto ipsec security-association lifetime kilobytes 536870912
crypto ipsec security-association lifetime seconds 86400
crypto ipsec transform-set 3DES-SHA esp-3des esp-sha-hmac

Crypto map configuration

Here we will need to know the outer interface, for the example it would be Dialer1, but will need to be changed to whatever your outer interface will be. Here we can define more IPSec options, just taking note to have other preference than 31.

crypto dynamic-map DYNMAP 10
description VPN Clients
set transform-set 3DES-SHA
set isakmp-profile VPNClient
crypto map CLIENTMAP local-address Dialer1
crypto map CLIENTMAP 31 ipsec-isakmp dynamic DYNMAP discover

Assigning the crypto map configuration

The last step is configuring the crypto map in the outer interface, as in this example the outer interface is Dialer1, the crypto map will be aplied to that interface, please note the name of the crypto map is matched with the crypto map from the last step:

interface Dialer1
crypto map CLIENTMAP

Now we have the router configured, now we will have to configure the OSX.

  1. In setting, network, we wil click the + sign at the bottom left of the list of interfaces to add a new interface, we will choose VPN as interface type, and Cisco IPSec as VPN type. We can provide here any familiar name for the VPN.
  2. In the server address we will provide the outer address of our router, if dynamic, here we will put the name we use with our prevered dynamic DNS provider, a static address is always painless, but dynamic DNS works fine with Cisco routers
  3. On the name of the account we will put the username configured on the router
  4. Clicking on authentication configuration, we will provide the secret for the group, and the group name

We are able to click on the Connect button to test our VPN connection.

Hope this could be helpfull for anybody trying to configure an IPSec VPN in the Cisco routers to a MAC OSX client, I would like to know the problems people has configuring this kind of VPN, and if anybody has other preferences for the kind of client.

CocoaPods on Xcode 6 and Yosemite

This post is for anybody with problems updating CocoaPods, and unable to run the current pod executable.

Extracted from the CocoaPods GitHub Issues, find here the steps necessary to solve this problem and have a new brilliant pod executable working:
1. Open Xcode 6
2. Open Preferences (Menú Xcode-Preferences)
3. Click the Locations tab
4. Change the Command Line Tools version to Xcode 6.0
5. Uninstall from a terminal window cocoapods (all installed versions prompted)
$ sudo gem uninstall cocoapods
6. Uninstall xcodeproj (all installed versions prompted)
$ sudo gem uninstall xcodeproj
7. Install xcodeproj
$ sudo gem install xcodeproj
8. Install cocoapods (retry a second time if fails with a error)
$ sudo gem install cocoapods
9. Run pod –version to verify that it worked

Before doing a new installation I found the following error on executing pod:
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- xcodeproj/prebuilt/universal.x86_64-darwin14-2.0.0/xcodeproj_ext (LoadError)
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in `require'
from /Library/Ruby/Gems/2.0.0/gems/xcodeproj-0.16.1/lib/xcodeproj/ext.rb:6:in `rescue in '
from /Library/Ruby/Gems/2.0.0/gems/xcodeproj-0.16.1/lib/xcodeproj/ext.rb:3:in `'
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in `require'
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in `require'
from /Library/Ruby/Gems/2.0.0/gems/xcodeproj-0.16.1/lib/xcodeproj.rb:30:in `'
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in `require'
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in `require'
from /Library/Ruby/Gems/2.0.0/gems/cocoapods-0.32.1/lib/cocoapods.rb:2:in `'
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in `require'
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in `require'
from /Library/Ruby/Gems/2.0.0/gems/cocoapods-0.32.1/bin/pod:32:in `'
from /usr/bin/pod:23:in `load'
from /usr/bin/pod:23:in `<main>'

Without doing the steps above, I found imposible to install the updated version of cocoa pods, the installation failed with error:
Fetching: cocoapods-core-0.33.1.gem (100%)
Successfully installed cocoapods-core-0.33.1
Fetching: claide-0.6.1.gem (100%)
Successfully installed claide-0.6.1
Fetching: xcodeproj-0.17.0.gem (100%)
Building native extensions. This could take a while...
ERROR: Error installing cocoapods:
ERROR: Failed to build gem native extension.

"/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/ruby" -rubygems /Library/Ruby/Gems/2.0.0/gems/rake-10.1.1/bin/rake RUBYARCHDIR=/Library/Ruby/Gems/2.0.0/gems/xcodeproj-0.17.0/ext RUBYLIBDIR=/Library/Ruby/Gems/2.0.0/gems/xcodeproj-0.17.0/ext
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/ruby extconf.rb
checking for -std=c99 option to compiler... *** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers. Check the mkmf.log file for more details. You may
need configuration options.

Provided configuration options:
--with-opt-dir
--without-opt-dir
--with-opt-include
--without-opt-include=${opt-dir}/include
--with-opt-lib
--without-opt-lib=${opt-dir}/lib
--with-make-prog
--without-make-prog
--srcdir=.
--curdir
--ruby=/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/ruby
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/mkmf.rb:434:in `try_do': The compiler failed to generate an executable file. (RuntimeError)
You have to install development tools first.
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/mkmf.rb:549:in `block in try_compile'
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/mkmf.rb:502:in `with_werror'
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/mkmf.rb:549:in `try_compile'
from extconf.rb:24:in `block in

'
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/mkmf.rb:895:in `block in checking_for'
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/mkmf.rb:340:in `block (2 levels) in postpone'
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/mkmf.rb:310:in `open'
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/mkmf.rb:340:in `block in postpone'
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/mkmf.rb:310:in `open'
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/mkmf.rb:336:in `postpone'
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/mkmf.rb:894:in `checking_for'
from extconf.rb:23:in `
'
rake aborted!
Command failed with status (1): [/System/Library/Frameworks/Ruby.framework/...]
/Library/Ruby/Gems/2.0.0/gems/xcodeproj-0.17.0/ext/xcodeproj/Rakefile:37:in `block in '
Tasks: TOP => default => ext
(See full trace by running task with --trace)

Gem files will remain installed in /Library/Ruby/Gems/2.0.0/gems/xcodeproj-0.17.0 for inspection.
Results logged to /Library/Ruby/Gems/2.0.0/gems/xcodeproj-0.17.0/ext/xcodeproj/gem_make.out

Hope this could help somebody

mod_auth_mysql, mod_authn_dbd, apache 2.4, php and the nightmare of upgrading to ubuntu 14.04

Hi, allthough I know this is mainly a IOS blog, I’ve got this problem this Eastern and I have found no places with real info to solve, so I will try to explain quite a bit how to configure apache basic mysql authentication in ubuntu 14.04.

The first thing to notice is that ubuntu 14.04 comes bundled with apache 2.4, MySQL 5.5 and PHP 5.5. So this document will.

The second is that this kind of validation is not the state-of-the-art or mood validation, so we’ll assume a migration from an older version which was working great in another LTS till 14.04 launch…

We will start hapy and confident with a current working mod_auth_mysql configuration in a 12.04 ubuntu server machine, with an apache domain configuration like this (ommited non-relevant lines:

<Directory /path/to/validated/directory>

AuthName "**String to show the user on the frontend**"
AuthType Basic
Auth_MySQL On
AuthBasicAuthoritative Off
AuthUserFile "/dev/null"
Auth_MySQL_Host **db_host**
Auth_MySQL_DB **db_schema**
Auth_MySQL_User **db_user**
Auth_MySQL_Password **db_password**
Auth_MySQL_Password_Table **db_auth_table**

#optional
Auth_MySQL_Group_Table **db_group_table**
Auth_MySQL_Username_Field **user_field_in_auth_table**
Auth_MySQL_Password_Field **password_field_in_auth_table**
# Plaintext, Crypt_DES, Mysql, PHP_MD5
Auth_MySQL_Encryption_Types Plaintext
Auth_MySQL_Group_Field **group_field_in_group_table
Auth_MySQL_Empty_Passwords off

require valid-user

# optional
require group **group_to_check_against**

</Directory>

* This configuration may require further changes to match your’s

So after upgrading to Ubuntu 14.04, apache does not validate config because maybe auth_mysql or other modules are not activated in apache. The documentation here makes you scream, as you can see AuthMySQL, Auth_MySQL and Auth_MysqlEnable for enabling the module, and apache is falling with “Invalid command ‘AuthMySQL’, perhaps misspelled or defined by a module not included in the server configuration”, you don’t know if configuration has changed or was working in the past but was wrong, everything seems right (apache starts) after re-enabling the module with the command (if the module was enabled in the 12.04 installation, why ubuntu didn’t left if enabled in the new one?):

a2enmod auth_mysql

When you believe you have a lucky day and all will work like a charm right now, the real problem begins, apache 2.4 on ubuntu 14.04 fails validation and keeps reporting 401 errors and “[:error] [pid xxxx] No requires line available” in the log file.

After some search, you may realized apache 2.2 left support for mod_auth_mysql, but at that version where still working, seems the lucky days for mod_auth_mysql has gone away (but still on ubuntu repository…).

Then you notice 2.2 and up has a new integrated validation schema you should use instead of the mod_auth_mysql solution, so create a new config with the info from the apache documentation site (what could be wrong, you need info, go to the source). The apache website prints a configuration like this:

# mod_dbd configuration
DBDriver pgsql
DBDParams "dbname=apacheauth user=apache password=xxxxxx"

DBDMin  4
DBDKeep 8
DBDMax  20
DBDExptime 300

<Directory /usr/www/myhost/private>
# core authentication and mod_auth_basic configuration
# for mod_authn_dbd
AuthType Basic
AuthName "My Server"
AuthBasicProvider dbd

# core authorization configuration
Require valid-user

# mod_authn_dbd SQL query to authenticate a user
AuthDBDUserPWQuery \
"SELECT password FROM authn WHERE user = %s"
</Directory>

As this configuration uses postgreSQL as database and uses a upper caching layer, we’ll try the easy one and delete the caching part (we are not a big site [I guess, no big site will use this configuration today]) and will make the configuration work for sure, we can always enable caching latter.

The final configuration keeps as this (I’ll reduce the less important lines assuming they are fine):

DBDriver mysql
DBDParams "dbname=**db_schema** user=**db_user** password=**db_password**"

<Directory /var/www/php/pesca/pesca3/privat>
AuthName "**String to show the user on the frontend**"
AuthType Basic

AuthBasicProvider dbd
AuthDBDUserPWQuery "SELECT **password_fileld** FROM TBLCLI WHERE STRUID=%s"

Require valid-user
</Directory>

No way, first we have to make sure all the packages to make mod_authn_dbd to use a mysql server are installed to avoid apache starting errors, so after the error: “DBD: Can’t load driver file apr_dbd_mysql.so” the first thing to do is install libaprutil1-dbd-mysql with the command:

sudo apt-get install libaprutil1-dbd-mysql

The second thing to do is make sure all the module dependencies to make mod_authn_dbd connect to the mysql server are satisfied or apache2 service will refuse to start:

  • dbd
  • authz_core
  • authz_dbd
  • authz_user

Now is where everything comes to gray, you will notice and/or try to do some of these things to clear the mess (please try any combination and shake firmly):

  • It seems to not connect to the mySQL server begging there’s no password
  • Mysql md5 and sha1 encryptions are incompatible with what apache understand for sha or md5, you may try to add some CONCAT(‘{SHA}:’, sha1(**password_field**)) without success
  • Maybe there’s a problem with the user, maybe we should add some ‘ around %s, that SELECT will not execute on the mysql server alone (no way)
  • plain password support does not exists in linux (clear difference here as it seems it really works in Unix, still some out there? I can here the eco…)
  • It seems default field for apache validation is password, maybe it don’t likes mine, maybe a “AS password” wil help in the validation
  • Try to generate an external password generation program to insert them in the database so apache could retrieve their sha password (some people has done this with success)

The final fact to make it work, is:

  • Thanks to Ubuntu guys or a problem in the apache documentation (hope not because this mistake is here since 2.2 documentation), the DBD configuration line doesn’t work with password=xxx but with pass=xxx
  • The plain text is of no use anymore, BUT an old behaviour is still working with the MySQL ENCRYPT(**password_field**) with the following limitations:
    • Doesn’t provide high security encription (no problem, we were trying to make it work, and these are intramachine communications)
    • The ENCRYPT funcion will use just 8 length passwords, and discard the rest of the password (I now know it, will tell my “customers”)
    • The ENCRYPT funcion is very old and nobody recomends it’s use (I now know it, please don’t convert to obsolete and delete from mysql functions in the future)

So the final configuration ends in a way like this:

DBDriver mysql
DBDParams "dbname=**db_schema** user=**db_user** pass=**db_password**"
DBDMin  4
DBDKeep 8
DBDMax  20
DBDExptime 300

<Directory /path/to/validated/directory>

AuthName "**String to show the user on the frontend**"
AuthType Basic

AuthBasicProvider dbd
AuthDBDUserPWQuery "SELECT ENCRYPT(**password_field**) AS password FROM **validation_table** WHERE **user_field**=%s"

Require valid-user
</Directory>

You should start with just 1 job for validation, feel free to change to your needs, as memory is not a problem here I left the numbers from the apache doc example.

This would work without the AS password part of the MySQL instance, but I prefer to left it here to make it clear.

In PHP you can access the authenticated username and password the same way it was before with auth_mysql with the variables $_SERVER[‘PHP_AUTH_USER’] and $_SERVER[‘PHP_AUTH_PW’].
Any other fields added here will be available in any apache script, so there will be no need to launch another db query.

Hello world!

Hello, world!
There’s no better title to start a blog about programming, and you don’t have to change the default title for the first post!

It seems yesterday the day I saw that phrase for the first time (I believe it was Basic, but who knows for sure), and I’ve seen languages and languages going by since then with the same phrase… Pascal, C, assembler, Visual Basic, C++, .NET (in some different flavors), PHP, Java, javascript (with some different esteroids…), Objective-C…
This blog is about the last one, Objective-C. This blog comes to fullfill the hole left by my engineering teachers who told me no word about other things that C. Surprisingly right now all those old languages has found their hole in Spain and can be learned everywhere (I born in the incorrect date or the incorrect place…). Time goes by, and now the old languages compete with the brilliant baby ones side by side. Babies comes saying “Hey, oldy, where do think you’re going, you don’t have even namespaces” while Objective-C and his band keeps saying… “Hey, dudes, beg you could still be here telling things like this thirty years from now…”.

You can always look back in time and check the old multilanguage static website/resume we’re leaving behind at http://pau.fazerbcn.org. It’s been lot of years and lot of projects in different scenarios.
I’ll post here my thinkings and news about Objective-C, and specifically when used in IOS devices, IOS programming blogging is a huge world where the biggest challenge is to choose the subject to talk about, hope you’ll like my digressions about this funny world, ¿do you think there’s place for “another IOS blog” on the Internet?