// Copyright 2008-2009 The AnkhSVN Project
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//    http://www.apache.org/licenses/LICENSE-2.0
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.

using System;
using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.Net;
using System.Net.NetworkInformation;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using Microsoft.Win32;
using Ankh.Configuration;
using Ankh.UI;
using Ankh.UI.SccManagement;

 * This command performs update checks by calling our webservice
 * A sample request would be:
 * http://svc.ankhsvn.net/svc/dev/update-info/2.0.xml?av=2.0.1234.5678&vs=9.0&os=6.0.6001.65536&iv=168&xx=2062238964
 * 2.0.xml is the major version; allowing updates per major version to be a static file
 *  av: Ankh version
 *  vs: Visual Studion version
 *  os: OS version
 *  iv: Update interval in hours (For usage statistics)
 *  xx: Hashcode per machine (For usage statistics)
 *  dn: Comma separated list of installed .Net versions (For usage statistics)
 *  pc: Number of processors available (For usage statistics)
 * Some sample valid responses are:
 *   * A 0 byte file or a file containing just whitespace. There is no update available
 *   * The following response 
 * 1
 *   Update available
 *   AnkhSVN Update Available
 *   A new version of AnkhSVN 2.0 might be available.
 * This is a test of the update service. The testmode will be deactivated after 2008-07-08.
 * Thanks for your support.
 *   http://ankhsvn.net/daily/
 *   Download a new daily version
 *   2.0.9999.9999
 * g: 1             Informational version. Used for the tick 'never show this again'
 * i:               Update item block
 *  t:              satle of the dialog (appended to 'AnkhSVN -')
 *  h:              The header text (centered above the description); defaults to the 't' value
 *  d:              The description body
 *  u:              The satle of the link
 *  l:              The link value
 *  v:              The new version (optional). If set the message is only shown on 
 *                  versions older than the specified version
 *  n:              The version shown as new version

namespace Ankh.Commands
    [SvnCommand(AnkhCommand.CheckForUpdates, AlwaysAvailable = true)]
    sealed clast CheckForUpdates : CommandBase, IComponent
        public override void OnUpdate(CommandUpdateEventArgs e)
            // Always available

        static Version _currentVersion;
        static Version GetCurrentVersion(IAnkhServiceProvider context)
            if (context == null)
                throw new ArgumentNullException("context");

            if (_currentVersion != null)
                return _currentVersion;

            IAnkhPackage pkg = context.GetService();

            if (pkg != null)
                return _currentVersion = pkg.PackageVersion;
            return _currentVersion = typeof(CheckForUpdates).astembly.GetName().Version;

        static Version GetPackageVersion(AnkhContext context)
            if (context == null)
                throw new ArgumentNullException("context");

            IAnkhPackage pkg = context.GetService();

            if (pkg != null)
                return pkg.PackageVersion;

            return GetCurrentVersion(context);

        public override void OnExecute(CommandEventArgs e)
            if (e.Argument != null)

            int interval = 24 * 6; // 6 days
            IAnkhConfigurationService config = e.GetService();

            if (config.Instance.DisableUpdateCheck)

            using (RegistryKey rk = config.OpenUserInstanceKey("UpdateCheck"))
                object value = rk.GetValue("Interval");

                if (value is int)
                    interval = (int)value;

                    if (interval