Blending local Linux apps into the Citrix XenDesktop Virtual Desktop

With the XenDesktop 7 and XenApp 6.5 Feature Pack 2, now local Microsoft windows applications can be seen without having to escape from your VDI or Hosted Shared desktop.
http://support.citrix.com/proddocs/topic/xendesktop-7/laa-overview.html

Back in 2011, I worked on the development of the prototype for the similar concept that allows blending the local Linux applications into the Virtual Desktop.

Technologies we used for the development of this prototype:
Citrix Virtual Channel SDK, Citrix WinFram API SDK, Google’s Protocol Buffers, C++, Visual C#, WinAPI, Xlib.

Here is the demo

Advertisements

Quickly generate icons for iOS apps

It can be painful generating icons of different sizes for your application, if you do not know how to script and automate the image processing on Photoshop/Gimp. But there are time saver alternatives that can simplify the process.

I always start with 1024 X 1024 image and use these utility apps to generate icons in a matter of seconds.

1. Prepo (I would give 5 Star Rating to this App)

It is easy to use, generate all different sizes of icons for iPhone/iPad and Universal Apps. (With Round Corner and Shine Effects)
More Details- http://wearemothership.com/work/prepo/

Prepo

2. http://iconswitch.me/

As stated on website, it is really two step iOS icon generator – 1) Upload and 2) Download.
This online tool is generating icons of following sizes.

Image Size (px) Used for
29 X 29 Spotlight and Settings
72 X 72 Home screen for iPad
50 X 50 Spotlight for iPad
58 X 58 Spotlight and Settings for iPhone/iPad with retina display
57 X 57 App Store and Home screen on iPhone/iPod touch
114 X 114 Home screen for iPhone with retina display

3. http://www.quirco.com/iPhoneIcon/

This online utility provides options to add glossy effect, round corners and drop shadow effect, but sometimes require manual image scaling to adjust icon size. Generating very limited sizes of icons.

Image Size (px) Used for
57 X 57 App Store and Home screen on iPhone/iPod touch
72 X 72 Home screen for iPad
114 X 114 Home screen for iPhone with retina display

Cisco Jabber URI in iOS Apps

You can use Jabber URIs in your iOS apps, for example, tapping a contact’s picture might start a Jabber call. Once you have constructed the appropriate Jabber URI, simply use openURL to initiate its actions.

Jabber-URI-iOS-Apps

Link to Gist

How can I determine if a Jabber is installed?

Your iOS app can simply pass the ciscojabber: scheme to canOpenURL to determine if a Jabber is installed on the device. A return value of true indicates that the Jabber is installed.

What can I do if a Jabber is not installed?

If the Jabber is not installed, your app should alert the user, and direct them to the App Store. Ideally, your app should use openURL with an argument of itms-apps://itunes.apple.com/us/app/cisco-jabber-for-ipad/id540243083?mt=8&uo=4 to navigate directly to the Jabber for iPad install page.

For more detail on launching the Cisco Jabber application visit http://developer.cisco.com/web/jabber-developer/the-jabber-application


Character Substitution and Permutation

Recently I came across the challenge to generate a list of all possible passwords for an overheard password with the permutation of character substitution.

The substitutions can be anything the user finds easy to remember, such as: ‘a’=’@’ or ‘A’ or ‘a’, ‘b’=’8’ or ‘B’ or ‘b’ , ‘k’=’|<‘ or ‘k’ or ‘K’ , ‘o’=’0’ or ‘O’ or ‘o’

With that the password “abook” can have following combinations.

abook_password_substitution_permutation

Here is the solution in java.
github repository – https://github.com/divyen/Password_Character_Substitution

package password_character_substitution;

import java.util.ArrayList;
import java.util.HashMap;

public class Password_Character_Substitution {

    static HashMap<Character, String[]> mappings = new HashMap<Character, String[]>();

    public static void main(String[] args) {
        init_character_mapping();

        ArrayList passwords = generate_password_possibilities("abook");

        for(int i=0;i<passwords.size();i++) {
            System.out.print(passwords.get(i) + "\t\t");
            if(i%10==0) {
                System.out.println("");
            }
        }
        System.out.println("");
        System.out.println("Number of Password Combinations:" + passwords.size());
    }

    static ArrayList generate_password_possibilities(String overheardpassword) {
        ArrayList password_list = new ArrayList();
        if (overheardpassword != null && overheardpassword.length()!=0) {
            generate_password_helper(password_list, "", overheardpassword);
        }
        return password_list;
    }

    static void generate_password_helper(ArrayList password_list, String password_prefix, String password_remaining) {
        char password_char = password_remaining.substring(0, 1).charAt(0);
        String[] replacements = mappings.get(Character.valueOf(password_char));

        if (password_remaining.length() == 1) {
            if (replacements != null) {
                for (int i = 0; i < replacements.length; i++) {
                    password_list.add(password_prefix + replacements[i]);
                }
            } else {
                password_list.add(password_prefix + password_char);
            }
        } else {

            if (replacements != null) {
                for (int i = 0; i < replacements.length; i++) {
                    generate_password_helper(password_list, password_prefix + replacements[i], password_remaining.substring(1));
                }
            } else {
                generate_password_helper(password_list, password_prefix + password_char, password_remaining.substring(1));
            }
        }
    }

    static void init_character_mapping() {
        mappings.put(Character.valueOf('a'), new String[]{"a", "A", "@"});
        mappings.put(Character.valueOf('b'), new String[]{"b", "B", "8","|3"});
        mappings.put(Character.valueOf('c'), new String[]{"c", "C"});
        mappings.put(Character.valueOf('d'), new String[]{"d", "D"});
        mappings.put(Character.valueOf('e'), new String[]{"e", "E", "3"});
        mappings.put(Character.valueOf('f'), new String[]{"f", "F"});
        mappings.put(Character.valueOf('g'), new String[]{"g", "G", "9", "6"});
        mappings.put(Character.valueOf('h'), new String[]{"h", "H"});
        mappings.put(Character.valueOf('i'), new String[]{"i", "I", "!", "1"});
        mappings.put(Character.valueOf('j'), new String[]{"j", "J"});
        mappings.put(Character.valueOf('k'), new String[]{"k", "K", "|<"});
        mappings.put(Character.valueOf('l'), new String[]{"l", "L"});
        mappings.put(Character.valueOf('m'), new String[]{"m", "M"});
        mappings.put(Character.valueOf('n'), new String[]{"n", "N"});
        mappings.put(Character.valueOf('o'), new String[]{"o", "O", "0"});
        mappings.put(Character.valueOf('p'), new String[]{"p", "P", "9"});
        mappings.put(Character.valueOf('q'), new String[]{"Q", "q"});
        mappings.put(Character.valueOf('r'), new String[]{"r", "R"});
        mappings.put(Character.valueOf('s'), new String[]{"s", "S", "$", "5"});
        mappings.put(Character.valueOf('t'), new String[]{"t", "T", "7"});
        mappings.put(Character.valueOf('u'), new String[]{"u", "U", "you"});
        mappings.put(Character.valueOf('v'), new String[]{"v", "V"});
        mappings.put(Character.valueOf('w'), new String[]{"w", "W"});
        mappings.put(Character.valueOf('x'), new String[]{"x", "X"});
        mappings.put(Character.valueOf('y'), new String[]{"y", "Y"});
        mappings.put(Character.valueOf('z'), new String[]{"z", "Z"});
        mappings.put(Character.valueOf(' '), new String[]{"?"});
        mappings.put(Character.valueOf('1'), new String[]{"1", "!"});
        mappings.put(Character.valueOf('2'), new String[]{"2", "Z"});
        mappings.put(Character.valueOf('3'), new String[]{"3", "E"});
        mappings.put(Character.valueOf('4'), new String[]{"4", "?"});
        mappings.put(Character.valueOf('5'), new String[]{"5", "S", "s", "$"});
        mappings.put(Character.valueOf('6'), new String[]{"6"});
        mappings.put(Character.valueOf('7'), new String[]{"7", "T"});
        mappings.put(Character.valueOf('8'), new String[]{"8", "B"});
        mappings.put(Character.valueOf('9'), new String[]{"9"});
        mappings.put(Character.valueOf('0'), new String[]{"0", "0", "O"});
    }
}

Using XCode with multiple developer IDs

I have Xcode 4.5.2 loaded with developer certificates and provisioning profiles from both my individual developer account and enterprise team account.

With this setup, when I tried to run my application on the iOS device I came across the error message “A valid provisioning profile for this executable was not found”.

valid_provisioning_profile_was_not_found

On my application build settings, code signing identity was set to Automatic Profile Selector, which was defaulting to my enterprise account, where I have not created provisioning profiles for my personal applications.

To overcome this error, you can go to Project -> Build Settings -> Code Signing Identity and set specific provisioning profile you want to use during run, instead of choosing automatic profile selector.

Configure Citrix Receiver for Mac with non-secure (HTTP) stores

Citrix Receiver for Mac (11.6) allows to add only secure (https) stores.

If you are trying to add http store URL you may be getting this message – “Certificate Not Trusted – The Server might not be secure”.

So to add an http based store we need to generate the configuration URL from  http://community.citrix.com/MacReceiverSetupUrlGenerator/

Enter Store Description, Store Address and Click Generate URL

Click on the Generated URL and this should launch and configure your Citrix Receiver with the specified store.

Click Continue and login into Store.

HTML5-Developing WebSocket Server using C# .NET

WebSocket provides the bi-directional communication, which allows data to be sent back and forth at the same time, without requiring to request from server or client. So once the WebSocket connection is established, data can be pushed across without either side having to ask for it.

Following is the best references to get started with understanding all about websockets and its benefits.

All about HTML5 WebSocket
http://www.websocket.org/aboutwebsocket.html

Benefits of WebSocket (Reduce unnecessary network overhead and latency)
http://www.websocket.org/quantum.html

There are many WebSocket libraries available to support the development of WebSocket server in C# .net, but the most efficient, and one of the easiest to use is the Alchemy Websockets (http://alchemywebsockets.net/)

The current version (2.2.1.238) supports the latest Google chrome, Mozilla Firefox, Safari on mac/windows and mobile devices (iPhone/iPad).

To begin with the development of WebSocket Server, goto the github repository at https://github.com/Olivine-Labs/Alchemy-Websockets and download the source code.

Open “Alchemy.sln” solution with Visual Studio.

Change Solution Configuration from “Debug” to “Release” mode and build the “Alchemy” project.

Create a new Visual C# Console Application project and name it “AlchemyWebSocketServer”. Go to “References” -> Add Reference -> Browse and add reference to “Alchemy.dll” file.

update the “Program.cs” with this code – https://gist.github.com/2976928.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Alchemy;
using Alchemy.Classes;
using System.Collections.Concurrent;
using System.Threading;


namespace AlchemyWebSocketServer
{
    class Program
    {
        //Thread-safe collection of Online Connections.
        protected static ConcurrentDictionary OnlineConnections = new ConcurrentDictionary();
        
        static void Main(string[] args)
        {
            // instantiate a new server - acceptable port and IP range,
            // and set up your methods.

            var  aServer = new WebSocketServer(8100,System.Net.IPAddress.Any)
            {
                                  OnReceive = OnReceive,
                                  OnSend = OnSend,
                                  OnConnected = OnConnect,
                                  OnDisconnect = OnDisconnect,
                                  TimeOut = new TimeSpan(0, 5, 0)
            };
            aServer.Start();


            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.Title = "Alchemy WebSocket Server";
            Console.WriteLine("Running Alchemy WebSocket Server ...");
            Console.WriteLine("[Type \"exit\" and hit enter to stop the server]"); 


            // Accept commands on the console and keep it alive
            var command = string.Empty;
            while (command != "exit")
            {
                command = Console.ReadLine();
            }

            aServer.Stop();

        }

        public static void OnConnect(UserContext aContext)
        {
            
            Console.WriteLine("Client Connected From : " + aContext.ClientAddress.ToString());
            
            // Create a new Connection Object to save client context information
            var conn= new Connection {Context=aContext};

            // Add a connection Object to thread-safe collection
            OnlineConnections.TryAdd(aContext.ClientAddress.ToString(), conn);
            
        }

       

        public static void OnReceive(UserContext aContext)
        {
            try
            {
                Console.WriteLine("Data Received From [" + aContext.ClientAddress.ToString() + "] - " + aContext.DataFrame.ToString());

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message.ToString());
            }
            
        }
        public static void OnSend(UserContext aContext)
        {            
            Console.WriteLine("Data Sent To : " + aContext.ClientAddress.ToString());
        }
        public static void OnDisconnect(UserContext aContext)
        {
            Console.WriteLine("Client Disconnected : " + aContext.ClientAddress.ToString());

            // Remove the connection Object from the thread-safe collection
            Connection conn;
            OnlineConnections.TryRemove(aContext.ClientAddress.ToString(),out conn);

            // Dispose timer to stop sending messages to the client.
            conn.timer.Dispose();
        }
    }

    public class Connection
    {
        public System.Threading.Timer timer;
        public UserContext Context { get; set; }
        public Connection() {
            this.timer = new System.Threading.Timer(this.TimerCallback, null, 0, 1000);
        }

        private void TimerCallback(object state)
        {
            try
            {
                // Sending Data to the Client
                Context.Send("[" + Context.ClientAddress.ToString() + "] " + System.DateTime.Now.ToString());
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

        }
    }
}

Build and run the "AlchemyWebSocketServer".

Here we are ready for testing the websocket server with html5 websocket client.

Create a “client.html” file with this code – https://gist.github.com/a9409a82d2379d52e9af  and publish it on your webserver.

Note: If websocket server and webserver are running on the different machines, make sure to change the websocket server address (‘ws://localhost:8100’) with correct IP address or hostname.

Now lets see how it works. Open up browser and navigate to the URL where you have published “client.html”.
Its working fine for me on Google Chrome (19.0.1084.56 m), Mozilla Firefox (13.0), Safari (5.1.7 – 7534.57.2), Safari on iPhone/iPad (iOS 5.1.1-9B206)

Console Messages

Isn’t that so simple to implement websocket with your favorite language C# .NET.
Thanks to OLIVINE LABS (http://olivinelabs.com/) for making this library available under MIT and LGPL licenses.