2 // permview.cs: Managed Permission Viewer for .NET assemblies
5 // Sebastien Pouliot <sebastien@ximian.com>
7 // Copyright (C) 2004-2007 Novell, Inc (http://www.novell.com)
11 using System.Collections;
13 using System.Reflection;
14 using System.Security;
15 using System.Security.Permissions;
20 [assembly: AssemblyTitle ("Mono PermView")]
21 [assembly: AssemblyDescription ("Managed Permission Viewer for .NET assemblies")]
23 namespace Mono.Tools {
25 class SecurityElementComparer : IComparer {
27 public int Compare (object x, object y)
29 SecurityElement sx = (x as SecurityElement);
30 SecurityElement sy = (y as SecurityElement);
32 return (sy == null) ? 0 : -1;
36 // compare by name (type name, method name, action name)
37 return String.Compare (sx.Attribute ("Name"), sy.Attribute ("Name"));
43 private const string NotSpecified = "\tNot specified.";
45 static private void Help ()
47 Console.WriteLine ("Usage: permview [options] assembly{0}", Environment.NewLine);
48 Console.WriteLine ("where options are:");
49 Console.WriteLine (" -output filename Output information into specified file.");
50 Console.WriteLine (" -decl Show declarative security attributes on classes and methods.");
51 Console.WriteLine (" -xml Output in XML format");
52 Console.WriteLine (" -help Show help informations (this text)");
56 static bool declarative = false;
57 static bool xmloutput = false;
59 static TextWriter ProcessOptions (string[] args)
61 TextWriter tw = Console.Out;
62 for (int i=0; i < args.Length - 1; i++) {
63 switch (args [i].ToUpper ()) {
72 tw = (TextWriter) new StreamWriter (args [++i]);
94 static bool ProcessAssemblyOnly (TextWriter tw, AssemblyDefinition ad)
97 string minimal = NotSpecified + Environment.NewLine;
98 string optional = NotSpecified + Environment.NewLine;
99 string refused = NotSpecified + Environment.NewLine;
101 foreach (SecurityDeclaration decl in ad.SecurityDeclarations) {
102 switch (decl.Action) {
103 case Mono.Cecil.SecurityAction.RequestMinimum:
104 minimal = decl.PermissionSet.ToString ();
106 case Mono.Cecil.SecurityAction.RequestOptional:
107 optional = decl.PermissionSet.ToString ();
109 case Mono.Cecil.SecurityAction.RequestRefuse:
110 refused = decl.PermissionSet.ToString ();
113 tw.WriteLine ("Invalid assembly level declaration {0}{1}{2}",
114 decl.Action, Environment.NewLine, decl.PermissionSet);
120 tw.WriteLine ("Minimal Permission Set:");
121 tw.WriteLine (minimal);
122 tw.WriteLine ("Optional Permission Set:");
123 tw.WriteLine (optional);
124 tw.WriteLine ("Refused Permission Set:");
125 tw.WriteLine (refused);
129 static void ShowSecurity (TextWriter tw, string header, SecurityDeclarationCollection declarations)
131 foreach (SecurityDeclaration declsec in declarations) {
132 tw.WriteLine ("{0} {1} Permission Set:{2}{3}", header,
133 declsec.Action, Environment.NewLine, declsec.PermissionSet);
137 static bool ProcessAssemblyComplete (TextWriter tw, AssemblyDefinition ad)
139 if (ad.SecurityDeclarations.Count > 0) {
140 ShowSecurity (tw, "Assembly", ad.SecurityDeclarations);
143 foreach (ModuleDefinition module in ad.Modules) {
145 foreach (TypeDefinition type in module.Types) {
147 if (type.SecurityDeclarations.Count > 0) {
148 ShowSecurity (tw, "Class " + type.ToString (), ad.SecurityDeclarations);
151 foreach (MethodDefinition method in type.Methods) {
152 if (method.SecurityDeclarations.Count > 0) {
153 ShowSecurity (tw, "Method " + method.ToString (), method.SecurityDeclarations);
161 static void AddAttribute (SecurityElement se, string attr, string value)
163 value = value.Replace ("&", "&");
164 se.AddAttribute (attr, value);
167 static SecurityElement AddSecurityXml (SecurityDeclarationCollection declarations)
169 ArrayList list = new ArrayList ();
170 foreach (SecurityDeclaration declsec in declarations) {
171 SecurityElement child = new SecurityElement ("Action");
172 AddAttribute (child, "Name", declsec.Action.ToString ());
173 child.AddChild (declsec.PermissionSet.ToXml ());
177 list.Sort (Comparer);
179 SecurityElement se = new SecurityElement ("Actions");
180 foreach (SecurityElement child in list) {
186 static SecurityElementComparer comparer;
187 static IComparer Comparer {
189 if (comparer == null)
190 comparer = new SecurityElementComparer ();
195 static bool ProcessAssemblyXml (TextWriter tw, AssemblyDefinition ad)
197 SecurityElement se = new SecurityElement ("Assembly");
198 se.AddAttribute ("Name", ad.Name.FullName);
200 if (ad.SecurityDeclarations.Count > 0) {
201 se.AddChild (AddSecurityXml (ad.SecurityDeclarations));
204 ArrayList tlist = new ArrayList ();
205 ArrayList mlist = new ArrayList ();
207 foreach (ModuleDefinition module in ad.Modules) {
209 foreach (TypeDefinition type in module.Types) {
211 SecurityElement klass = new SecurityElement ("Class");
212 SecurityElement methods = new SecurityElement ("Methods");
214 SecurityElement typelem = null;
215 if (type.SecurityDeclarations.Count > 0) {
216 typelem = AddSecurityXml (type.SecurityDeclarations);
222 foreach (MethodDefinition method in type.Methods) {
223 if (method.SecurityDeclarations.Count > 0) {
224 SecurityElement meth = new SecurityElement ("Method");
225 AddAttribute (meth, "Name", method.ToString ());
226 meth.AddChild (AddSecurityXml (method.SecurityDeclarations));
232 mlist.Sort (Comparer);
233 foreach (SecurityElement method in mlist) {
234 methods.AddChild (method);
237 if ((typelem != null) || ((methods.Children != null) && (methods.Children.Count > 0))) {
238 AddAttribute (klass, "Name", type.ToString ());
240 klass.AddChild (typelem);
241 if ((methods.Children != null) && (methods.Children.Count > 0))
242 klass.AddChild (methods);
248 tlist.Sort (Comparer);
249 foreach (SecurityElement type in tlist) {
254 tw.WriteLine (se.ToString ());
259 static int Main (string[] args)
262 Console.WriteLine (new AssemblyInfo ().ToString ());
263 if (args.Length == 0) {
268 TextWriter tw = ProcessOptions (args);
272 string assemblyName = args [args.Length - 1];
273 AssemblyDefinition ad = AssemblyFactory.GetAssembly (assemblyName);
275 bool complete = false;
278 // full output (assembly+classes+methods)
279 complete = ProcessAssemblyComplete (tw, ad);
280 } else if (xmloutput) {
281 // full output in XML (for easier diffs after c14n)
282 complete = ProcessAssemblyXml (tw, ad);
284 // default (assembly only)
285 complete = ProcessAssemblyOnly (tw, ad);
289 Console.Error.WriteLine ("Couldn't reflect informations.");
293 Console.Error.WriteLine ("Couldn't load assembly '{0}'.", assemblyName);
298 catch (Exception e) {
299 Console.Error.WriteLine ("Error: " + e.ToString ());