2008-01-15 Stephane Delcroix <sdelcroix@novell.com>
[mono.git] / mcs / class / corlib / System.Security.Policy / Url.cs
index 3c12d538acc8b452dcc280f4d41114d004f3e4f9..b048856d2eeddfa7592196aeaeb8777f883aa1dc 100644 (file)
@@ -3,14 +3,11 @@
 //
 // Author
 //     Duncan Mak (duncan@ximian.com)
-//     Sebastien Pouliot (spouliot@motus.com)
+//     Sebastien Pouliot  <sebastien@ximian.com>
 //
 // (C) 2003 Ximian, Inc (http://www.ximian.com)
 // (C) 2004 Motus Technologies Inc. (http://www.motus.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-using System;
 using System.Globalization;
+using System.Runtime.InteropServices;
 using System.Security.Permissions;
-using System.Security.Policy;
+
+using Mono.Security;
 
 namespace System.Security.Policy {
 
-        [Serializable]
+       [Serializable]
+#if NET_2_0
+       [ComVisible (true)]
+#endif
         public sealed class Url: IIdentityPermissionFactory, IBuiltInEvidence {
 
-                string origin_url;
+                private string origin_url;
                 
                 public Url (string name)
+                       : this (name, false)
                 {
-                       origin_url = Prepare (name);
                 }
 
+               internal Url (string name, bool validated) 
+               {
+                       origin_url = validated ? name : Prepare (name);
+               }
+
+               // methods
+
                 public object Copy ()
                 {
-                        return new Url (origin_url);
+                       // dont re-validate the Url
+                        return new Url (origin_url, true);
                 }
 
                 public IPermission CreateIdentityPermission (Evidence evidence)
@@ -61,19 +70,34 @@ namespace System.Security.Policy {
 
                 public override bool Equals (object o)
                 {
-                       if (o is System.Security.Policy.Url)
-                               return (String.Compare (((Url) o).Value, Value, true, CultureInfo.InvariantCulture) == 0);
-                       return false;
+                       Url u = (o as System.Security.Policy.Url);
+                       if (u == null)
+                               return false;
+
+                       string url1 = u.Value;
+                       string url2 = origin_url;
+#if NET_2_0
+                       if (url1.IndexOf (Uri.SchemeDelimiter) < 0)
+                               url1 = "file://" + url1;
+                       if (url2.IndexOf (Uri.SchemeDelimiter) < 0)
+                               url2 = "file://" + url2;
+#endif
+                       return (String.Compare (url1, url2, true, CultureInfo.InvariantCulture) == 0);
                 }
 
                 public override int GetHashCode ()
                 {
-                        return origin_url.GetHashCode ();
+                       string s = origin_url;
+#if NET_2_0
+                       if (s.IndexOf (Uri.SchemeDelimiter) < 0)
+                               s = "file://" + s;
+#endif
+                        return s.GetHashCode ();
                 }
 
                 public override string ToString ()
                 {
-                       SecurityElement element = new SecurityElement (typeof (System.Security.Policy.Url).FullName);
+                       SecurityElement element = new SecurityElement ("System.Security.Policy.Url");
                        element.AddAttribute ("version", "1");
                        element.AddChild (new SecurityElement ("Url", origin_url));
                        return element.ToString ();
@@ -85,60 +109,83 @@ namespace System.Security.Policy {
 
                // interface IBuiltInEvidence
 
-               [MonoTODO]
                int IBuiltInEvidence.GetRequiredSize (bool verbose) 
                {
-                       return 0;
+                       return (verbose ? 3 : 1) + origin_url.Length;
                }
 
-               [MonoTODO]
+               [MonoTODO ("IBuiltInEvidence")]
                int IBuiltInEvidence.InitFromBuffer (char [] buffer, int position) 
                {
                        return 0;
                }
 
-               [MonoTODO]
+               [MonoTODO ("IBuiltInEvidence")]
                int IBuiltInEvidence.OutputToBuffer (char [] buffer, int position, bool verbose) 
                {
                        return 0;
                }
 
                // internal
-
-               [MonoTODO ("missing site validation")]
-               internal static string Prepare (string url) 
+#if NET_2_0
+               private string Prepare (string url) 
                {
                        if (url == null)
                                throw new ArgumentNullException ("Url");
                        if (url == String.Empty)
                                throw new FormatException (Locale.GetText ("Invalid (empty) Url"));
 
-                       // is a protocol specified
-                       int protocolPos = url.IndexOf ("://");
-                       if (protocolPos == -1)
-                               return "file://" + url.ToUpperInvariant ();
-                       
-                       if (url.StartsWith ("file://"))
-                               return "file://" + url.Substring (7).ToUpperInvariant ();
-
-                       // add a trailing slash if none (lonely one) is present
-                       if (url.LastIndexOf ("/") == protocolPos + 2)
-                               return url + "/";
-                       else
-                               return url;
-               }
+                       int protocolPos = url.IndexOf (Uri.SchemeDelimiter);    // '://'
+                       if (protocolPos > 0) {
+                               if (url.StartsWith ("file://")) {
+                                       // convert file url into uppercase
+                                       url = "file://" + url.Substring (7);
+                               }
+                               // don't escape and don't reduce (e.g. '.' and '..')
+                               Uri uri = new Uri (url, false, false);
+                               url = uri.ToString ();
+                       }
+
+                       int lastpos = url.Length - 1;
+                       if (url [lastpos] == '/')
+                               url = url.Substring (0, lastpos);
 
-               internal static bool Compare (string mask, string url) 
+                       return url;
+               }
+#else
+               private string Prepare (string url) 
                {
-                       int wildcard = mask.LastIndexOf ("*");
-                       if (wildcard > 0) {
-                               // partial match with a wildcard at the end
-                               return (String.Compare (mask, 0, url, 0, wildcard, true, CultureInfo.InvariantCulture) == 0);
+                       if (url == null)
+                               throw new ArgumentNullException ("Url");
+                       if (url == String.Empty)
+                               throw new FormatException (Locale.GetText ("Invalid (empty) Url"));
+
+                       int protocolPos = url.IndexOf (Uri.SchemeDelimiter);    // '://'
+                       if (protocolPos > 0) {
+                               if (url.StartsWith ("file://")) {
+                                       // convert file url into uppercase
+                                       url = "file://" + url.Substring (7).ToUpperInvariant ();
+                               } else {
+                                       // add a trailing slash if none (lonely one) is present
+                                       if (url.LastIndexOf ("/") == protocolPos + 2)
+                                               url += "/";
+                               }
+                       } else {
+                               // add file scheme (default) and convert url to uppercase
+                               url = "file://" + url.ToUpperInvariant ();
                        }
+
+                       // don't escape and don't reduce (e.g. '.' and '..')
+                       Uri uri = new Uri (url, false, false);
+                       if ((uri.Host.IndexOf ('*') < 0) || (uri.Host.Length < 2)) // lone star case
+                               url = uri.ToString ();
                        else {
-                               // exact match
-                               return (String.Compare (mask, url, true, CultureInfo.InvariantCulture) == 0);
+                               string msg = Locale.GetText ("Invalid * character in url");
+                               throw new ArgumentException (msg, "name");
                        }
+
+                       return url;
                }
-        }
+#endif
+       }
 }