New e-d-s backend which indexes all local addressbooks and calendars.
[beagle.git] / Util / UriFu.cs
blob483229fcc0ab13dc882830f5154a9c863acfcbfc
1 //
2 // UriFu.cs
3 //
4 // Copyright (C) 2004 Novell, Inc.
5 //
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in all
16 // copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 // SOFTWARE.
27 using System;
28 using System.Collections;
29 using System.Text;
31 namespace Beagle.Util {
33 public class UriFu {
35 private UriFu () { } // class is static
37 static public Uri PathToFileUri (string path)
39 string uriStr = StringFu.PathToQuotedFileUri (path);
40 return new Uri (uriStr, true);
43 static public Uri UriStringToUri (string path)
45 // Decode our pre-encoded 'odd' characters into their real values
46 int i = 0, pos = 0;
47 while ((i = path.IndexOf ('%', pos)) != -1) {
48 pos = i;
49 char unescaped = UriFu.HexUnescape (path, ref pos);
50 if (unescaped < '!' || unescaped > '~') {
51 path = path.Remove (i, 3);
52 path = path.Insert (i, new String(unescaped, 1));
53 pos -= 2;
57 // Paths from the file:// indexer need (re)quoting. For example,
58 // valid characters such as @ need to be converted to their hex
59 // values.
60 if (path.StartsWith ("file://")) {
61 // Remove the file:// prefix
62 path = path.Substring (7);
64 return PathToFileUri (path);
67 // Currently, no other protocols need extra processing
68 return new Uri (path, true);
71 static public String UriToSerializableString (Uri uri)
73 int i;
74 string ret;
75 StringBuilder builder = new StringBuilder ();
77 // The ToString() of a file:// URI is not always representative of
78 // what it was constructed from. For example, it will return a
79 // # (which was inputted as %23) as %23, whereas the more standard
80 // behaviour for other escaped-characters is to return them as
81 // their actual character. (e.g. %40 gets returned as @)
82 // On the other hand, the LocalPath of a file:// URI does seem to
83 // return the literal # so we use that instead.
84 if (uri.IsFile)
85 ret = Uri.UriSchemeFile + Uri.SchemeDelimiter + uri.LocalPath;
86 else
87 ret = uri.ToString ();
89 // XmlSerializer is happy to serialize 'odd' characters, but doesn't
90 // like to deserialize them. So we encode all 'odd' characters now.
91 for (i = 0; i < ret.Length; i++)
92 if ((ret [i] < '!') || (ret [i] > '~' && ret [i] < 256))
93 builder.Append (Uri.HexEscape (ret [i]));
94 else
95 builder.Append (ret [i]);
97 return builder.ToString ();
100 // Stolen from Mono SVN 20050319
101 // Fixes bug where non-ASCII characters couldn't be decoded
102 // FIXME: Go back to using Uri.HexUnescape when new Mono 1.1.5+ is
103 // readily available.
104 public static char HexUnescape (string pattern, ref int index)
106 if (pattern == null)
107 throw new ArgumentException ("pattern");
109 if (index < 0 || index >= pattern.Length)
110 throw new ArgumentOutOfRangeException ("index");
112 if (!Uri.IsHexEncoding (pattern, index))
113 return pattern [index++];
115 int stage = 0;
116 int c = 0;
117 int b = 0;
118 bool looped = false;
119 do {
120 index++;
121 int msb = Uri.FromHex (pattern [index++]);
122 int lsb = Uri.FromHex (pattern [index++]);
123 b = (msb << 4) + lsb;
124 if (!Uri.IsHexEncoding (pattern, index)) {
125 if (looped)
126 c += (b - 0x80) << ((stage - 1) * 6);
127 else
128 c = b;
129 break;
130 } else if (stage == 0) {
131 if (b < 0xc0)
132 return (char) b;
133 else if (b < 0xE0) {
134 c = b - 0xc0;
135 stage = 2;
136 } else if (b < 0xF0) {
137 c = b - 0xe0;
138 stage = 3;
139 } else if (b < 0xF8) {
140 c = b - 0xf0;
141 stage = 4;
142 } else if (b < 0xFB) {
143 c = b - 0xf8;
144 stage = 5;
145 } else if (b < 0xFE) {
146 c = b - 0xfc;
147 stage = 6;
149 c <<= (stage - 1) * 6;
150 } else {
151 c += (b - 0x80) << ((stage - 1) * 6);
153 stage--;
154 looped = true;
155 } while (stage > 0);
157 return (char) c;
160 static public String LocalPathFromUri (Uri uri)
162 if (uri == null)
163 return "";
164 // FIXME: Can we assume "a directory", if it is not a file?
165 // If so, return the path of that directory.
166 if (uri.IsFile)
167 return uri.LocalPath;
168 else
169 return "";
172 //////////////////////////////////
174 static public bool Equals (Uri uri1, Uri uri2)
176 return uri1.ToString () == uri2.ToString ();
179 static public int Compare (Uri uri1, Uri uri2)
181 return String.Compare (uri1.ToString (), uri2.ToString ());
184 //////////////////////////////////
186 public class Comparer : IComparer
188 public int Compare(object uri1, object uri2)
190 return String.Compare(uri1.ToString(), uri2.ToString());
194 public class Hasher : IHashCodeProvider
196 public int GetHashCode(object o)
198 return o.ToString().GetHashCode();
202 static Comparer the_comparer = new Comparer ();
203 static Hasher the_hasher = new Hasher ();
205 // Returns a hash table that does the right thing when
206 // the key is a Uri.
207 static public Hashtable NewHashtable ()
209 return new Hashtable (the_hasher, the_comparer);
212 //////////////////////////////////
214 static public string UrisToString (ICollection list_of_uris)
216 StringBuilder sb = new StringBuilder ("!@#");
218 foreach (Uri uri in list_of_uris) {
219 sb.Append (" ");
220 sb.Append (UriToSerializableString (uri).Replace (" ", "%20"));
223 return sb.ToString ();
226 static public ICollection StringToUris (string list_of_uris_as_string)
228 string [] parts = list_of_uris_as_string.Split (' ');
230 if (parts.Length == 0 || parts [0] != "!@#")
231 return null;
233 ArrayList uri_array = new ArrayList ();
234 for (int i = 1; i < parts.Length; ++i) {
235 try {
236 Uri uri = UriStringToUri (parts [i]);
237 uri_array.Add (uri);
238 } catch (Exception ex) {
239 Logger.Log.Debug ("Caught exception converting '{0}' to a Uri", parts [i]);
243 return uri_array;