File: Introspection.cs

package info (click to toggle)
aircrack-ng 1%3A1.6%2Bgit20210130.91820bc-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 19,056 kB
  • sloc: ansic: 67,045; cs: 5,392; sh: 3,773; python: 2,565; pascal: 1,074; asm: 570; makefile: 253; cpp: 46
file content (310 lines) | stat: -rw-r--r-- 9,417 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
// Copyright 2006 Alp Toker <alp@atoker.com>
// This software is made available under the MIT License
// See COPYING for details

using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Text;
using System.Reflection;

namespace NDesk.DBus
{
	//TODO: complete this class
	class Introspector
	{
		const string NAMESPACE = "http://www.freedesktop.org/standards/dbus";
		const string PUBLIC_IDENTIFIER = "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN";
		const string SYSTEM_IDENTIFIER = "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd";

		public StringBuilder sb;
		public string xml;
		public ObjectPath root_path = ObjectPath.Root;

		protected XmlWriter writer;

		public Introspector ()
		{
			XmlWriterSettings settings = new XmlWriterSettings ();
			settings.Indent = true;
			settings.IndentChars = ("  ");
			settings.OmitXmlDeclaration = true;

			sb = new StringBuilder ();

			writer = XmlWriter.Create (sb, settings);
		}

		static string GetProductDescription ()
		{
			String version;

			Assembly assembly = Assembly.GetExecutingAssembly ();
			AssemblyName aname = assembly.GetName ();

			AssemblyInformationalVersionAttribute iversion = Attribute.GetCustomAttribute (assembly, typeof (AssemblyInformationalVersionAttribute)) as AssemblyInformationalVersionAttribute;

			if (iversion != null)
				version = iversion.InformationalVersion;
			else
				version = aname.Version.ToString ();

			return aname.Name + " " + version;
		}

		public void WriteStart ()
		{
			writer.WriteDocType ("node", PUBLIC_IDENTIFIER, SYSTEM_IDENTIFIER, null);

			writer.WriteComment (" " + GetProductDescription () + " ");

			//the root node element
			writer.WriteStartElement ("node");
		}

		public void WriteNode (string name)
		{
			writer.WriteStartElement ("node");
			writer.WriteAttributeString ("name", name);
			writer.WriteEndElement ();
		}

		public void WriteEnd ()
		{
			/*
			WriteEnum (typeof (org.freedesktop.DBus.NameFlag));
			WriteEnum (typeof (org.freedesktop.DBus.NameReply));
			WriteEnum (typeof (org.freedesktop.DBus.ReleaseNameReply));
			WriteEnum (typeof (org.freedesktop.DBus.StartReply));
			WriteInterface (typeof (org.freedesktop.DBus.IBus));
			*/

			writer.WriteEndElement ();

			writer.Flush ();
			xml = sb.ToString ();
		}

		//public void WriteNode ()
		public void WriteType (Type target_type)
		{
			//writer.WriteStartElement ("node");

			//TODO: non-well-known introspection has paths as well, which we don't do yet. read the spec again
			//hackishly just remove the root '/' to make the path relative for now
			//writer.WriteAttributeString ("name", target_path.Value.Substring (1));
			//writer.WriteAttributeString ("name", "test");

			//reflect our own interface manually
			WriteInterface (typeof (org.freedesktop.DBus.Introspectable));

			//reflect the target interface
			if (target_type != null) {
				WriteInterface (target_type);

				foreach (Type ifType in target_type.GetInterfaces ())
					WriteInterface (ifType);
			}

			//TODO: review recursion of interfaces and inheritance hierarchy

			//writer.WriteEndElement ();
		}

		public void WriteArg (ParameterInfo pi)
		{
			WriteArg (pi.ParameterType, Mapper.GetArgumentName (pi), pi.IsOut, false);
		}

		public void WriteArgReverse (ParameterInfo pi)
		{
			WriteArg (pi.ParameterType, Mapper.GetArgumentName (pi), pi.IsOut, true);
		}

		//TODO: clean up and get rid of reverse (or argIsOut) parm
		public void WriteArg (Type argType, string argName, bool argIsOut, bool reverse)
		{
			argType = argIsOut ? argType.GetElementType () : argType;
			if (argType == typeof (void))
				return;

			writer.WriteStartElement ("arg");

			if (!String.IsNullOrEmpty (argName))
				writer.WriteAttributeString ("name", argName);

			//we can't rely on the default direction (qt-dbus requires a direction at time of writing), so we use a boolean to reverse the parameter direction and make it explicit

			if (argIsOut)
				writer.WriteAttributeString ("direction", !reverse ? "out" : "in");
			else
				writer.WriteAttributeString ("direction", !reverse ? "in" : "out");

			Signature sig = Signature.GetSig (argType);

			//TODO: avoid writing null (DType.Invalid) to the XML stream
			writer.WriteAttributeString ("type", sig.Value);

			//annotations aren't valid in an arg element, so this is disabled
			//if (argType.IsEnum)
			//	WriteAnnotation ("org.ndesk.DBus.Enum", Mapper.GetInterfaceName (argType));

			writer.WriteEndElement ();
		}

		public void WriteMethod (MethodInfo mi)
		{
			writer.WriteStartElement ("method");
			writer.WriteAttributeString ("name", mi.Name);

			foreach (ParameterInfo pi in mi.GetParameters ())
				WriteArg (pi);

			//Mono <= 1.1.13 doesn't support MethodInfo.ReturnParameter, so avoid it
			//WriteArgReverse (mi.ReturnParameter);
			WriteArg (mi.ReturnType, Mapper.GetArgumentName (mi.ReturnTypeCustomAttributes, "ret"), false, true);

			WriteAnnotations (mi);

			writer.WriteEndElement ();
		}

		public void WriteProperty (PropertyInfo pri)
		{
			//expose properties as dbus properties
			writer.WriteStartElement ("property");
			writer.WriteAttributeString ("name", pri.Name);
			writer.WriteAttributeString ("type", Signature.GetSig (pri.PropertyType).Value);
			string access = (pri.CanRead ? "read" : String.Empty) + (pri.CanWrite ? "write" : String.Empty);
			writer.WriteAttributeString ("access", access);
			WriteAnnotations (pri);
			writer.WriteEndElement ();

			//expose properties as methods also
			//it may not be worth doing this in the long run
			/*
			if (pri.CanRead) {
				writer.WriteStartElement ("method");
				writer.WriteAttributeString ("name", "Get" + pri.Name);
				WriteArgReverse (pri.GetGetMethod ().ReturnParameter);
				writer.WriteEndElement ();
			}

			if (pri.CanWrite) {
				writer.WriteStartElement ("method");
				writer.WriteAttributeString ("name", "Set" + pri.Name);
				foreach (ParameterInfo pi in pri.GetSetMethod ().GetParameters ())
					WriteArg (pi);
				writer.WriteEndElement ();
			}
			*/
		}

		public void WriteSignal (EventInfo ei)
		{
			writer.WriteStartElement ("signal");
			writer.WriteAttributeString ("name", ei.Name);

			foreach (ParameterInfo pi in ei.EventHandlerType.GetMethod ("Invoke").GetParameters ())
				WriteArgReverse (pi);

			WriteAnnotations (ei);

			//no need to consider the delegate return value as dbus doesn't support it
			writer.WriteEndElement ();
		}

		const BindingFlags relevantBindingFlags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;

		public void WriteInterface (Type type)
		{
			if (type == null)
				return;

			//TODO: this is unreliable, fix it
			if (!Mapper.IsPublic (type))
				return;

			writer.WriteStartElement ("interface");

			writer.WriteAttributeString ("name", Mapper.GetInterfaceName (type));

			/*
			foreach (MemberInfo mbi in type.GetMembers (relevantBindingFlags)) {
				switch (mbi.MemberType) {
					case MemberTypes.Method:
						if (!((MethodInfo)mbi).IsSpecialName)
							WriteMethod ((MethodInfo)mbi);
						break;
					case MemberTypes.Event:
						WriteSignal ((EventInfo)mbi);
						break;
					case MemberTypes.Property:
						WriteProperty ((PropertyInfo)mbi);
						break;
					default:
						Console.Error.WriteLine ("Warning: Unhandled MemberType '{0}' encountered while introspecting {1}", mbi.MemberType, type.FullName);
						break;
				}
			}
			*/

			foreach (MethodInfo mi in type.GetMethods (relevantBindingFlags))
				if (!mi.IsSpecialName)
					WriteMethod (mi);

			foreach (EventInfo ei in type.GetEvents (relevantBindingFlags))
				WriteSignal (ei);

			foreach (PropertyInfo pri in type.GetProperties (relevantBindingFlags))
				WriteProperty (pri);

			//TODO: indexers

			//TODO: attributes as annotations?

			writer.WriteEndElement ();

			//this recursion seems somewhat inelegant
			WriteInterface (type.BaseType);
		}

		public void WriteAnnotations (ICustomAttributeProvider attrProvider)
		{
			if (Mapper.IsDeprecated (attrProvider))
				WriteAnnotation ("org.freedesktop.DBus.Deprecated", "true");
		}

		public void WriteAnnotation (string name, string value)
		{
			writer.WriteStartElement ("annotation");

			writer.WriteAttributeString ("name", name);
			writer.WriteAttributeString ("value", value);

			writer.WriteEndElement ();
		}

		//this is not in the spec, and is not finalized
		public void WriteEnum (Type type)
		{
			writer.WriteStartElement ("enum");
			writer.WriteAttributeString ("name", Mapper.GetInterfaceName (type));
			writer.WriteAttributeString ("type", Signature.GetSig (type.GetElementType ()).Value);
			writer.WriteAttributeString ("flags", (type.IsDefined (typeof (FlagsAttribute), false)) ? "true" : "false");

			string[] names = Enum.GetNames (type);

			int i = 0;
			foreach (Enum val in Enum.GetValues (type)) {
				writer.WriteStartElement ("element");
				writer.WriteAttributeString ("name", names[i++]);
				writer.WriteAttributeString ("value", val.ToString ("d"));
				writer.WriteEndElement ();
			}

			writer.WriteEndElement ();
		}
	}
}