Tuesday, December 23, 2014

Javascript Client Side File Size Validation

When you attempt to upload a file that is larger than the web server will accept, it just stops processing. It might be OK, but you don't have a way to be notified. It would be nice to be able to do have something like the following code snippet.
$("#editDialog form").submit(function( event ) {
    return validateFileSize('profile_image', 1024*1024*2, 'Profile Image', event);
});
The solution is very simple with the HTML5 file reader functionality. We can add some JavaScript to run before we attempt to send the bad files. The following achieves the validation needed.
function validateFileSize(id, limit, label, event) {
    if (typeof FileReader !== "undefined" && document.getElementById(id).files.length > 0) {
        var size = document.getElementById(id).files[0].size;
        if (size > limit) {
            alert(label + ' is too large.  The file must be less than ' + formatSize(limit) + '.');
            event.preventDefault();
            return false;
        }
    }
    return true;
}
I am utilizing my JavaScript function from my previous post JavaScript Format File Size Truncate Decimals. This allows me to format the file size very nicely.
function formatSize(bytes, decimals) {
    if (!!!bytes) return 'n/a';
    var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'],
        i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024))),
        decMult = Math.pow(10, decimals || 2);
    return (Math.round((bytes / Math.pow(1024, i)) * decMult)) / decMult + ' ' + sizes[i];
}

Friday, December 19, 2014

Checking For Network Reachabilty In Xamarin

Just ran into this little gem. Everything that I found on how to detect network reachability in says that the following code should be used.
await Network.IsReachable(url, new TimeSpan(NetworkTimeout))
This worked on every iOS device I could get, except the most important device - the client's. It works on iPhone 4s, 5, and 5s, also it worked on my iPad, but not the client's iPhone 5. After much research and frustration, I started diving into the Network.InternetConnectionStatus() function to see if that would be fruitful. I tried the following:
return !Network.InternetConnectionStatus().HasFlag(NetworkStatus.NotReachable);
which naturally (for Xamarin) it is not reliable. I ended up trying the following setup, which seemed to work for on my devices.
var networkstatus = Network.InternetConnectionStatus();
return 
    networkstatus.HasFlag(NetworkStatus.ReachableViaWiFiNetwork) || 
    networkstatus.HasFlag(NetworkStatus.ReachableViaCarrierDataNetwork);
After pushing the build out to the client, he was able to log in. This way has some downsides, as it doesn't check to see if you can actually reach the site you want, but at least you can detect if there is network connectivity.

I would love to submit a bug, but I am not sure how to reliably recreate the issue. It is little things like this that do not build my confidence in Xamarin.

Wednesday, December 17, 2014

Xamarin Forms Non-Native CheckBox

Having experience developing iOS applications, I know that there is no "check box" per say. When I searched for a Xamarin Forms built in check box and was left with only an native implementation, this would have been acceptable, except that they were causing some significant performance issues/lag when a view containing the controls would be added to the navigation stack.

In my last couple posts, I dove into creating non-native controls in Xamarin Forms. I can build on that knowledge to build a Xamarin Forms checkbox hopefully improve performance. This definitely renders a lot faster.
<localcontrol:CheckBoxView Checked="{Binding SomeBooleanProperty}" DefaultText="Check Box Text" ReadOnly="true" HorizontalOptions="FillAndExpand" TextColor="#000000" FontSize="12" />
The source code...
<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
       x:Class="IntPonApp.Controls.CheckBoxView">

 <StackLayout x:Name="CheckBoxStack" Orientation="Horizontal">
  <StackLayout.GestureRecognizers>
   <TapGestureRecognizer 
      Command="{Binding CheckCommand}"
      CommandParameter="#" />
  </StackLayout.GestureRecognizers>
  <Image x:Name="boxImage" 
      Source="{Binding BoxImageSource}" />
  <Label x:Name="textLabel" 
      Text="{Binding Text}" 
      LineBreakMode="WordWrap" 
      XAlign="Center" 
      HorizontalOptions="StartAndExpand" 
      VerticalOptions="Center" 
      TextColor="{Binding TextColor}" 
      Font="{Binding Font}" />
 </StackLayout>
 
</ContentView>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Labs;
using CustomControls;
using System.Diagnostics;
using System.Windows.Input;

namespace Check123Mobile.Controls
{
    public partial class CheckBoxView
    {
        #region Properties

        /// <summary>
        /// The width request in inches property.
        /// </summary>
        public static readonly BindableProperty CheckedProperty =
            BindableProperty.Create<CheckBoxView, bool>(
                p => p.Checked, false
                , propertyChanged: new BindableProperty.BindingPropertyChangedDelegate<bool>(
                    (BindableObject obj, bool oldPlaceHolderValue, bool newPlaceHolderValue) =>
                    {
                        var cbv = (CheckBoxView)obj;
                        cbv.BoxImageSource = cbv.GetCheckBoxImageSource();
                    })
                );

        protected static readonly BindableProperty BoxImageSourceProperty =
            BindableProperty.Create<CheckBoxView, ImageSource>(
                p => p.BoxImageSource, null);

        /// <summary>
        /// The read only property.
        /// </summary>
        public static readonly BindableProperty ReadOnlyProperty =
            BindableProperty.Create<CheckBoxView, bool>(
                p => p.ReadOnly, false);

        /// <summary>
        /// The checked text property.
        /// </summary>
        public static readonly BindableProperty CheckedTextProperty =
            BindableProperty.Create<CheckBoxView, string>(
                p => p.CheckedText, string.Empty);

        /// <summary>
        /// The unchecked text property.
        /// </summary>
        public static readonly BindableProperty UncheckedTextProperty =
            BindableProperty.Create<CheckBoxView, string>(
                p => p.UncheckedText, string.Empty);

        /// <summary>
        /// The checked image property.
        /// </summary>
        public static readonly BindableProperty CheckedImageProperty =
            BindableProperty.Create<CheckBoxView, string>(
                p => p.CheckedImage, string.Empty);

        /// <summary>
        /// The unchecked image property.
        /// </summary>
        public static readonly BindableProperty UncheckedImageProperty =
            BindableProperty.Create<CheckBoxView, string>(
                p => p.UncheckedImage, string.Empty);

        /// <summary>
        /// The default text property.
        /// </summary>
        public static readonly BindableProperty DefaultTextProperty =
            BindableProperty.Create<CheckBoxView, string>(
                p => p.Text, string.Empty);

        /// <summary>
        /// Identifies the TextColor bindable property.
        /// </summary>
        /// 
        /// <remarks/>
        public static readonly BindableProperty TextColorProperty =
            BindableProperty.Create<CheckBoxView, Color>(
                p => p.TextColor, Color.Black);

        /// <summary>
        /// The font size property
        /// </summary>
        public static readonly BindableProperty FontSizeProperty =
            BindableProperty.Create<CheckBoxView, double>(
                p => p.FontSize, -1);

        /// <summary>
        /// The font name property.
        /// </summary>
        public static readonly BindableProperty FontNameProperty =
            BindableProperty.Create<CheckBoxView, string>(
                p => p.FontName, string.Empty);

        public static ImageSource CheckedImageSource { get; protected set; }

        public static ImageSource UncheckedImageSource { get; protected set; }

        /// <summary>
        /// The checked changed event.
        /// </summary>
        public EventHandler<EventArgs<bool>> CheckedChanged;

        /// <summary>
        /// Gets or sets a value indicating whether the control is checked.
        /// </summary>
        /// <value>The checked state.</value>
        public bool Checked
        {
            get
            {
                return this.GetValue<bool>(CheckedProperty);
            }

            set
            {
                this.SetValue(CheckedProperty, value);
                var eventHandler = this.CheckedChanged;
                if (eventHandler != null)
                {
                    eventHandler.Invoke(this, value);
                }
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether the control is checked.
        /// </summary>
        /// <value>The checked state.</value>
        public bool ReadOnly
        {
            get
            {
                return this.GetValue<bool>(ReadOnlyProperty);
            }

            set
            {
                this.SetValue(ReadOnlyProperty, value);
            }
        }

        /// <summary>
        /// Gets or sets a value indicating the checked text.
        /// </summary>
        /// <value>The checked state.</value>
        /// <remarks>
        /// Overwrites the default text property if set when checkbox is checked.
        /// </remarks>
        public string CheckedText
        {
            get
            {
                return this.GetValue<string>(CheckedTextProperty);
            }

            set
            {
                this.SetValue(CheckedTextProperty, value);
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether the control is checked.
        /// </summary>
        /// <value>The checked state.</value>
        /// <remarks>
        /// Overwrites the default text property if set when checkbox is checked.
        /// </remarks>
        public string UncheckedText
        {
            get
            {
                return this.GetValue<string>(UncheckedTextProperty);
            }

            set
            {
                this.SetValue(UncheckedTextProperty, value);
            }
        }

        public ImageSource BoxImageSource
        {
            get
            {

                return this.GetValue<ImageSource>(BoxImageSourceProperty) ?? GetCheckBoxImageSource();
            }

            set
            {
                this.SetValue(BoxImageSourceProperty, value);
            }
        }

        /// <summary>
        /// Gets or sets a value indicating the checked text.
        /// </summary>
        /// <value>The checked state.</value>
        /// <remarks>
        /// Overwrites the default text property if set when checkbox is checked.
        /// </remarks>
        public string CheckedImage
        {
            get
            {
                return this.GetValue<string>(CheckedImageProperty);
            }

            set
            {
                this.SetValue(CheckedImageProperty, value);
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether the control is checked.
        /// </summary>
        /// <value>The checked state.</value>
        /// <remarks>
        /// Overwrites the default text property if set when checkbox is checked.
        /// </remarks>
        public string UncheckedImage
        {
            get
            {
                return this.GetValue<string>(UncheckedImageProperty);
            }

            set
            {
                this.SetValue(UncheckedImageProperty, value);
            }
        }

        /// <summary>
        /// Gets or sets the text.
        /// </summary>
        public string DefaultText
        {
            get
            {
                return this.GetValue<string>(DefaultTextProperty);
            }

            set
            {
                this.SetValue(DefaultTextProperty, value);
            }
        }

        public Color TextColor
        {
            get
            {
                return this.GetValue<Color>(TextColorProperty);
            }

            set
            {
                this.SetValue(TextColorProperty, value);
            }
        }

        /// <summary>
        /// Gets or sets the size of the font.
        /// </summary>
        /// <value>The size of the font.</value>
        public double FontSize
        {
            get
            {
                return (double)GetValue(FontSizeProperty);
            }
            set
            {
                SetValue(FontSizeProperty, value);
            }
        }

        /// <summary>
        /// Gets or sets the name of the font.
        /// </summary>
        /// <value>The name of the font.</value>
        public string FontName
        {
            get
            {
                return (string)GetValue(FontNameProperty);
            }
            set
            {
                SetValue(FontNameProperty, value);
            }
        }

        public Font Font
        {
            get
            {
                return Font.SystemFontOfSize(FontSize);
            }
        }

        public string Text
        {
            get
            {
                return this.Checked
                    ? (string.IsNullOrEmpty(this.CheckedText) ? this.DefaultText : this.CheckedText)
                        : (string.IsNullOrEmpty(this.UncheckedText) ? this.DefaultText : this.UncheckedText);
            }
        }

        public ICommand CheckCommand { get; protected set; }

        #endregion Properties

        #region Constructor

        public CheckBoxView()
        {
            CheckCommand = new Command((object s) =>
                {
                    if (!ReadOnly)
                    {
                        Checked = !Checked;
                    }
                });
            InitializeComponent();
            LoadImages();
            CheckBoxStack.BindingContext = this;
            boxImage.BindingContext = this;
            textLabel.BindingContext = this;
        }

        #endregion Constructor
         
        #region Image Functions

        protected void LoadImages()
        {
            if (CheckedImageSource == null)
            {
                CheckedImageSource = ImageSource.FromResource(GetCheckedImage());
            }
            if (UncheckedImageSource == null)
            {
                UncheckedImageSource = ImageSource.FromResource(GetUncheckedImage());
            }
        }

        private ImageSource GetCheckBoxImageSource()
        {
            return this.Checked ? CheckedImageSource : UncheckedImageSource;
        }

        private string GetCheckBoxImage()
        {
            return this.Checked
                        ? GetCheckedImage()
                        : GetUncheckedImage();
        }

        private string GetCheckedImage()
        {
            return (string.IsNullOrEmpty(this.CheckedImage) ?
                            "Check123Mobile.Resources.checked_checkbox.png" :
                            this.CheckedImage);
        }

        private string GetUncheckedImage()
        {
            return (string.IsNullOrEmpty(this.UncheckedImage) ?
                            "Check123Mobile.Resources.unchecked_checkbox.png" :
                            this.UncheckedImage);
        }

        #endregion Image Functions
    }
}

Friday, November 28, 2014

Windows 7 IKEv2 VPN "Verifying User and Password..."

I VPN quite often and recently something changed on my old laptop running Windows 7 which prevented me from connecting. I was able to connect using my laptop running Windows 8. After some hunting I came across this TechNet thread.

The fix ended up being very simple, but not intuitive.
  1. View your network adaptors by going to Control Panel > Network and Internet > Network Connection
  2. Right-click on the offending VPN adapter and click Properties
  3. Click on the Security tab
  4. Change the "Type of VPN" value from IKEv2 to Point to Point Tunneling Protocol (PPTP)
  5. Click OK
From the thread:
It seems that when this property is set to Automatic the WAN Miniport defaults to IKEv2 (and gets stuck if this is not the VPN type used).
Translated: it is a feature not a bug.

Now attempt to connect again. Short of other issues, it will connect successfully.

Thursday, November 20, 2014

Git Filter-Branch Saves The Day Again

Disclaimer

You can really mess things up, make sure you back up your files/repositories before you wield this axe.

Removing a large file from a Git repository

Recently I committed and pushed a commit to my remote repository. The push took an unusually long time. Looking at the commit, I discovered that I had committed/pushed a vagrant box into the repository. Doh! Now the repository was ~500MB. Here is what I did to clean up the repository and remove the large file.

I can't remember where I found this command (I may have assembled it from many locations). It is supposed to remove all references and the file from the repository.
git filter-branch --prune-empty -d /dev/shm/scratch --index-filter "git rm --cached -f --ignore-unmatch ubuntu-precise32-intpon.box" --tag-name-filter cat -- --all
This seemed to clean up the git tree, but didn't actually remove the file from the repository. So, on we go...

I ran across an Atlassian page which detailed several new steps to remove a large file. I skipped the first 3 steps because the above command seemed to do the same thing.

The next step was to prune all of the reflog references from now on back.
git reflog expire --expire=now --all

Then repack the repository by running the garbage collector and pruning old objects.
git gc --prune=now

Finally, push all your changes back to the remote repository.
git push origin master --force

Looking at my repository, it was back at ~45MB. I can pretend it never happened and life is good again. As long as I don't tell anyone about it.

Changing the author information

If you are committing to a public repository, you may not want your private email address exposed to the world. GitHub's change author info page has an excellent script that can fix that issue if you accidentally commit with the wrong email address. In case the page changes or disappears, here is the script:
#!/bin/sh
 
git filter-branch --env-filter '
 
OLD_EMAIL="your-old-email@example.com"
CORRECT_NAME="Your Correct Name"
CORRECT_EMAIL="your-correct-email@example.com"
 
if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]
then
export GIT_COMMITTER_NAME="$CORRECT_NAME"
export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]
then
export GIT_AUTHOR_NAME="$CORRECT_NAME"
export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL"
fi
' --tag-name-filter cat -- --branches --tags
Once it completes, you need to push the changes to the remote repository.
git push --force --tags origin 'refs/heads/*'
Your email is now changed.

Tuesday, October 21, 2014

A JUnit XSL Transform For PHPUnit Logging

I recently worked on a PHP application with a PHPUnit test suite. Not finding a good way to view the test run results, I settled on logging the output into JUnit format and then applied the style sheet to the XML file so that I can through the XML file into a browser.
time phpunit --testsuite "Application Test Suite" --log-junit public/testresults.xml & sed -i 's//\n/g' public/testresults.xml
Not sure why, but finding a decent transform for the JUnit output was more diffcult than expected. I decided to extended an XSL transform in this StackOverflow answer. It is a pretty good start, plain text, but I can work with it.

After applying Bootstrap styling, the end result is a pleasantly styled JUnit view in a browser. For some reason, FireFox was not applying the bootstrap CSS file, so I just brought in the styles that I needed, thus the style block.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" encoding="UTF-8" indent="yes"/>

    <xsl:template match="/testsuites">
        <!-- <xsl:text disable-output-escaping='yes'>&lt;!DOCTYPE html></xsl:text> -->
        <html class="no-js" lang="en">
        <head>
            <meta charset="utf-8" />
            <meta http-equiv="X-UA-Compatible" content="IE=edge" />
            <title>PHPUnit Test Results</title>
            <meta name="description" content="" />
            <meta name="viewport" content="width=device-width, initial-scale=1" />
            <!-- <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" /> -->
            <style>
                html {
                  font-family: sans-serif;
                  -webkit-text-size-adjust: 100%;
                      -ms-text-size-adjust: 100%;
                  font-size: 10px;
                  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
                }
                body {
                  margin: 0;
                  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
                  font-size: 14px;
                  line-height: 1.42857143;
                  color: #333;
                  background-color: #fff;
                }
                article,
                aside,
                details,
                figcaption,
                figure,
                footer,
                header,
                hgroup,
                main,
                nav,
                section,
                summary {
                  display: block;
                }
                hr {
                  height: 0;
                  -webkit-box-sizing: content-box;
                     -moz-box-sizing: content-box;
                          box-sizing: content-box;
                }
                pre {
                  overflow: auto;
                  font-family: monospace, monospace;
                  font-size: 1em;
                }

                .container {
                  padding-right: 15px;
                  padding-left: 15px;
                  margin-right: auto;
                  margin-left: auto;
                }
                .page-header {
                    padding-bottom: 9px;
                    margin: 40px 0 20px;
                    border-bottom: 1px solid #eee;
                }
                .failure, .error {
                    padding: 0px 20px;
                }
                .failure pre, .error pre {
                    border: 1px solid #DDD;
                    padding: 10px;
                }
            </style>
        </head>
        <body>
            <div class="container">
                <xsl:apply-templates select="testsuite" />
            </div>
        </body>
        </html>
    </xsl:template>

    <xsl:template match="testsuite">
        <header class="page-header">
        <h1>Testsuite: <xsl:value-of select="@name" /></h1>
        <div>
            <xsl:text>
            Tests run: </xsl:text>
            <xsl:value-of select="@tests" />
            <xsl:text>, Failures: </xsl:text>
            <xsl:value-of select="@failures" />
            <xsl:text>, Errors: </xsl:text>
            <xsl:value-of select="@errors" />
            <xsl:text>, Time elapsed: </xsl:text>
            <xsl:value-of select="@time" />
            <xsl:text> sec</xsl:text>
        </div>
        </header>
        <xsl:apply-templates select="system-out" />
        <xsl:apply-templates select="system-err" />
        <div>
            <xsl:apply-templates select="//testcase" />
        </div>
    </xsl:template>

    <xsl:template match="testcase">
        <p>
            <xsl:text>
            Testcase: </xsl:text>
            <xsl:value-of select="@name" />
            <xsl:text> took </xsl:text>
            <xsl:value-of select="@time" />
        </p>
        <xsl:apply-templates select="failure" />
        <xsl:apply-templates select="error" />
    </xsl:template>

    <xsl:template match="failure">
        <div class="failure">
            <span style="color: #ff4136;">
                <xsl:text>
                    Failure:
                </xsl:text>
                <xsl:value-of select="@type" />
            </span>
            <pre>
                <xsl:value-of select="." />
            </pre>
        </div>
    </xsl:template>

    <xsl:template match="error">
        <div class="error">
            <span style="color: #F00;">
                <xsl:text>
                    Error:
                </xsl:text>
                <xsl:value-of select="@type" />
            </span>
            <pre>
                <xsl:value-of select="." />
            </pre>
        </div>
    </xsl:template>

    <xsl:template match="system-out">
        <div>
            <xsl:text>
            ------ Standard output ------
            </xsl:text>
            <pre>
                <xsl:value-of select="." />
            </pre>
        </div>
    </xsl:template>

    <xsl:template match="system-err">
        <div>
            <xsl:text>
            ------ Error output ------
            </xsl:text>
            <pre>
                <xsl:value-of select="." />
            </pre>
        </div>
    </xsl:template>

</xsl:stylesheet>