/* Copyright (c) Citrix Systems Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* * Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
namespace XenAdmin.Core
{
public static class StringUtility
{
///
/// Parses strings of the form "hostname:port"
///
///
///
///
///
public static bool TryParseHostname(string s, int defaultPort, out string hostname, out int port)
{
try
{
int i = s.IndexOf(':');
if (i != -1)
{
hostname = s.Substring(0, i).Trim();
port = int.Parse(s.Substring(i + 1).Trim());
}
else
{
hostname = s;
port = defaultPort; // Program.DEFAULT_XEN_PORT;
}
return true;
}
catch (Exception)
{
hostname = null;
port = 0;
return false;
}
}
public static int NaturalCompare(string s1, string s2)
{
if (string.Compare(s1, s2, StringComparison.CurrentCultureIgnoreCase) == 0)
{
// Strings are identical
return 0;
}
if (s1 == null)
return -1;
if (s2 == null)
return 1;
char[] chars1 = s1.ToCharArray();
char[] chars2 = s2.ToCharArray();
// Compare strings char by char
int min = Math.Min(chars1.Length, chars2.Length);
for (int i = 0; i < min; i++)
{
char c1 = chars1[i];
char c2 = chars2[i];
bool c1IsDigit = char.IsDigit(c1);
bool c2IsDigit = char.IsDigit(c2);
if (!c1IsDigit && !c2IsDigit)
{
// Two non-digits. Do a string (i.e. alphabetical) comparison.
int tmp = String.Compare(s1.Substring(i, 1), s2.Substring(i, 1), StringComparison.CurrentCultureIgnoreCase);
if (tmp == 0)
continue; // Identical non-digits. Move onto next character.
else
return tmp;
}
else if (c1IsDigit && c2IsDigit)
{
// See how many digits there are in a row in each string.
int j = 1;
while (i + j < chars1.Length && char.IsDigit(chars1[i + j]))
j++;
int k = 1;
while (i + k < chars2.Length && char.IsDigit(chars2[i + k]))
k++;
// A number that is shorter in decimal places must be smaller.
if (j < k)
{
return -1;
}
else if (k < j)
{
return 1;
}
// The two integers have the same number of digits. Compare them digit by digit.
for (int m = i; m < i + j; m++)
{
if (chars1[m] != chars2[m])
return chars1[m] - chars2[m];
}
// Skip the characters we've already compared, so we don't have to do them again. (CA-50738)
// (It's only j-1, not j, because we get one more in the loop increment).
i += j - 1;
continue;
}
else
{
// We're comparing a digit to a non-digit.
return String.Compare(s1.Substring(i, 1), s2.Substring(i, 1), StringComparison.CurrentCultureIgnoreCase);
}
}
// The shorter string comes first.
return chars1.Length - chars2.Length;
}
private static readonly Regex IPRegex = new Regex(@"^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$");
private static readonly Regex IPRegex0 = new Regex(@"^([0]{1,3})\.([0]{1,3})\.([0]{1,3})\.([0]{1,3})$");
public static bool IsIPAddress(string s)
{
if (string.IsNullOrEmpty(s))
return false;
// check the general form is ok
Match m = IPRegex.Match(s);
if (!m.Success)
return false;
// check the individual numbers are in range, easier to do this as a parse than with the regex
for (int i = 1; i < 3; i++)
{
int v;
if (!int.TryParse(m.Groups[i].Value, out v))
return false;
if (v > 255)
return false;
}
Match m2 = IPRegex0.Match(s);
if (m2.Success)
return false;
return true;
}
}
}