1 // Copyright 2006 Alp Toker <alp@atoker.com>
2 // This software is made available under the MIT License
3 // See COPYING for details
4 
5 using System;
6 using System.Text;
7 using System.Collections.Generic;
8 
9 namespace NDesk.DBus
10 {
11 	public class BadAddressException : Exception
12 	{
BadAddressException(string reason)13 		public BadAddressException (string reason) : base (reason) {}
14 	}
15 
16 	class AddressEntry
17 	{
18 		public string Method;
19 		public IDictionary<string,string> Properties = new Dictionary<string,string> ();
20 
ToString()21 		public override string ToString ()
22 		{
23 			StringBuilder sb = new StringBuilder ();
24 			sb.Append (Method);
25 			sb.Append (':');
26 
27 			bool first = true;
28 			foreach (KeyValuePair<string,string> prop in Properties) {
29 				if (first)
30 					first = false;
31 				else
32 					sb.Append (',');
33 
34 				sb.Append (prop.Key);
35 				sb.Append ('=');
36 				sb.Append (Escape (prop.Value));
37 			}
38 
39 			return sb.ToString ();
40 		}
41 
Escape(string str)42 		static string Escape (string str)
43 		{
44 			if (str == null)
45 				return String.Empty;
46 
47 			StringBuilder sb = new StringBuilder ();
48 			int len = str.Length;
49 
50 			for (int i = 0 ; i != len ; i++) {
51 				char c = str[i];
52 
53 				//everything other than the optionally escaped chars _must_ be escaped
54 				if (Char.IsLetterOrDigit (c) || c == '-' || c == '_' || c == '/' || c == '\\' || c == '.')
55 					sb.Append (c);
56 				else
57 					sb.Append (Uri.HexEscape (c));
58 			}
59 
60 			return sb.ToString ();
61 		}
62 
Unescape(string str)63 		static string Unescape (string str)
64 		{
65 			if (str == null)
66 				return String.Empty;
67 
68 			StringBuilder sb = new StringBuilder ();
69 			int len = str.Length;
70 			int i = 0;
71 			while (i != len) {
72 				if (Uri.IsHexEncoding (str, i))
73 					sb.Append (Uri.HexUnescape (str, ref i));
74 				else
75 					sb.Append (str[i++]);
76 			}
77 
78 			return sb.ToString ();
79 		}
80 
81 
Parse(string s)82 		public static AddressEntry Parse (string s)
83 		{
84 			AddressEntry entry = new AddressEntry ();
85 
86 			string[] parts = s.Split (':');
87 
88 			if (parts.Length < 2)
89 				throw new BadAddressException ("No colon found");
90 			if (parts.Length > 2)
91 				throw new BadAddressException ("Too many colons found");
92 
93 			entry.Method = parts[0];
94 
95 			foreach (string propStr in parts[1].Split (',')) {
96 				parts = propStr.Split ('=');
97 
98 				if (parts.Length < 2)
99 					throw new BadAddressException ("No equals sign found");
100 				if (parts.Length > 2)
101 					throw new BadAddressException ("Too many equals signs found");
102 
103 				entry.Properties[parts[0]] = Unescape (parts[1]);
104 			}
105 
106 			return entry;
107 		}
108 	}
109 
110 	static class Address
111 	{
112 		//(unix:(path|abstract)=.*,guid=.*|tcp:host=.*(,port=.*)?);? ...
Parse(string addresses)113 		public static AddressEntry[] Parse (string addresses)
114 		{
115 			if (addresses == null)
116 				throw new ArgumentNullException (addresses);
117 
118 			List<AddressEntry> entries = new List<AddressEntry> ();
119 
120 			foreach (string entryStr in addresses.Split (';'))
121 				entries.Add (AddressEntry.Parse (entryStr));
122 
123 			return entries.ToArray ();
124 		}
125 
126 		const string SYSTEM_BUS_ADDRESS = "unix:path=/var/run/dbus/system_bus_socket";
127 		public static string System
128 		{
129 			get {
130 				string addr = Environment.GetEnvironmentVariable ("DBUS_SYSTEM_BUS_ADDRESS");
131 
132 				if (String.IsNullOrEmpty (addr))
133 					addr = SYSTEM_BUS_ADDRESS;
134 
135 				return addr;
136 			}
137 		}
138 
139 		public static string Session
140 		{
141 			get {
142 				return Environment.GetEnvironmentVariable ("DBUS_SESSION_BUS_ADDRESS");
143 			}
144 		}
145 
146 		public static string Starter
147 		{
148 			get {
149 				return Environment.GetEnvironmentVariable ("DBUS_STARTER_ADDRESS");
150 			}
151 		}
152 
153 		public static string StarterBusType
154 		{
155 			get {
156 				return Environment.GetEnvironmentVariable ("DBUS_STARTER_BUS_TYPE");
157 			}
158 		}
159 	}
160 }
161