System.Drawing: added email to icon and test file headers
[mono.git] / mcs / class / Microsoft.Build.Utilities / Mono.XBuild.Utilities / MSBuildUtils.cs
1 //
2 // Utilities.cs:
3 //
4 // Author:
5 //      Ankit Jain (jankit@novell.com)
6 //
7 // Copyright (c) 2009 Novell, Inc (http://www.novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28 #if NET_2_0
29
30 using System;
31 using System.Collections;
32 using System.Text;
33 using System.IO;
34 using System.Runtime.InteropServices;
35
36 namespace Mono.XBuild.Utilities {
37         internal static class MSBuildUtils {
38
39                 public readonly static bool RunningOnMac;
40                 public readonly static bool RunningOnWindows;
41                 static Hashtable charsToEscape;
42
43                 static MSBuildUtils ()
44                 {
45                         RunningOnWindows = Path.DirectorySeparatorChar == '\\';
46                         RunningOnMac = !RunningOnWindows && IsRunningOnMac ();
47
48                         charsToEscape = new Hashtable ();
49                         
50                         charsToEscape.Add ('$', null);
51                         charsToEscape.Add ('%', null);
52                         charsToEscape.Add ('\'', null);
53                         charsToEscape.Add ('(', null);
54                         charsToEscape.Add (')', null);
55                         charsToEscape.Add ('*', null);
56                         charsToEscape.Add (';', null);
57                         charsToEscape.Add ('?', null);
58                         charsToEscape.Add ('@', null);
59                 }
60         
61                 public static string Escape (string unescapedExpression)
62                 {
63                         StringBuilder sb = new StringBuilder ();
64                         
65                         foreach (char c in unescapedExpression) {
66                                 if (charsToEscape.Contains (c))
67                                         sb.AppendFormat ("%{0:x2}", (int) c);
68                                 else
69                                         sb.Append (c);
70                         }
71                         
72                         return sb.ToString ();
73                 }
74                 
75                 // FIXME: add tests for this
76                 internal static string Unescape (string escapedExpression)
77                 {
78                         StringBuilder sb = new StringBuilder ();
79                         
80                         int i = 0;
81                         while (i < escapedExpression.Length) {
82                                 sb.Append (Uri.HexUnescape (escapedExpression, ref i));
83                         }
84                         
85                         return sb.ToString ();
86                 }
87
88                 internal static string UnescapeFromXml (string text)
89                 {
90                         StringBuilder sb = new StringBuilder ();
91                         for (int i = 0; i < text.Length; i++) {
92                                 char c1 = text[i];
93                                 if (c1 == '&') {
94                                         int end = text.IndexOf (';', i);
95                                         if (end == -1)
96                                                 throw new FormatException ("Unterminated XML entity.");
97                                         string entity = text.Substring (i+1, end - i - 1);
98                                         switch (entity) {
99                                         case "lt":
100                                                 sb.Append ('<');
101                                                 break;
102                                         case "gt":
103                                                 sb.Append ('>');
104                                                 break;
105                                         case "amp":
106                                                 sb.Append ('&');
107                                                 break;
108                                         case "apos":
109                                                 sb.Append ('\'');
110                                                 break;
111                                         case "quot":
112                                                 sb.Append ('"');
113                                                 break;
114                                         default:
115                                                 throw new FormatException ("Unrecogised XML entity '&" + entity + ";'.");
116                                         }
117                                         i = end;
118                                 } else
119                                         sb.Append (c1);
120                         }
121                         return sb.ToString ();
122                 }
123
124                 [DllImport ("libc")]
125                 static extern int uname (IntPtr buf);
126
127                 //From Managed.Windows.Forms/XplatUI
128                 static bool IsRunningOnMac ()
129                 {
130                         IntPtr buf = IntPtr.Zero;
131                         try {
132                                 buf = System.Runtime.InteropServices.Marshal.AllocHGlobal (8192);
133                                 // This is a hacktastic way of getting sysname from uname ()
134                                 if (uname (buf) == 0) {
135                                         string os = System.Runtime.InteropServices.Marshal.PtrToStringAnsi (buf);
136                                         if (os == "Darwin")
137                                                 return true;
138                                 }
139                         } catch {
140                         } finally {
141                                 if (buf != IntPtr.Zero)
142                                         System.Runtime.InteropServices.Marshal.FreeHGlobal (buf);
143                         }
144                         return false;
145                 }
146
147                 internal static string FromMSBuildPath (string relPath)
148                 {
149                         string result = null;
150                         FromMSBuildPath (String.Empty, relPath, out result);
151                         return result;
152                 }
153
154                 internal static bool FromMSBuildPath (string basePath, string relPath, out string resultPath)
155                 {
156                         resultPath = relPath;
157                         
158                         if (string.IsNullOrEmpty (relPath))
159                                 return false;
160                         
161                         string path = relPath;
162                         if (!RunningOnWindows)
163                                 path = path.Replace ("\\", "/");
164                         
165                         path = Unescape (path);
166
167                         if (char.IsLetter (path [0]) && path.Length > 1 && path[1] == ':') {
168                                 if (RunningOnWindows) {
169                                         resultPath = path; // Return the escaped value
170                                         return true;
171                                 } else
172                                         return false;
173                         }
174                         
175                         if (basePath != null)
176                                 path = Path.Combine (basePath, path);
177                         
178                         if (System.IO.File.Exists (path) || System.IO.Directory.Exists (path)){
179                                 resultPath = Path.GetFullPath (path);
180                                 return true;
181                         }
182                                 
183                         if (Path.IsPathRooted (path) && !RunningOnWindows) {
184                                         
185                                 // Windows paths are case-insensitive. When mapping an absolute path
186                                 // we can try to find the correct case for the path.
187                                 
188                                 string[] names = path.Substring (1).Split ('/');
189                                 string part = "/";
190                                 
191                                 for (int n=0; n<names.Length; n++) {
192                                         string[] entries;
193
194                                         if (names [n] == ".."){
195                                                 if (part == "/")
196                                                         return false; // Can go further back. It's not an existing file
197                                                 part = Path.GetFullPath (part + "/..");
198                                                 continue;
199                                         }
200                                         
201                                         entries = Directory.GetFileSystemEntries (part);
202                                         
203                                         string fpath = null;
204                                         foreach (string e in entries) {
205                                                 if (string.Compare (Path.GetFileName (e), names[n], true) == 0) {
206                                                         fpath = e;
207                                                         break;
208                                                 }
209                                         }
210                                         if (fpath == null) {
211                                                 // Part of the path does not exist. Can't do any more checking.
212                                                 part = Path.GetFullPath (part);
213                                                 for (; n < names.Length; n++)
214                                                         part += "/" + names[n];
215                                                 resultPath = part;
216                                                 return true;
217                                         }
218
219                                         part = fpath;
220                                 }
221                                 resultPath = Path.GetFullPath (part);
222                         } else {
223                                 resultPath = Path.GetFullPath (path);
224                         }
225                         return true;
226                 }
227         }
228
229 }
230
231 #endif