Jb Evain wrote:
I'll have to add support for that. As a very sad workaround, you can
go back to Cecil 0.6.x as found in Mono 2.8.
That won't work, as I'm working on a mono.merge implementation using
cecil 0.9 :-)
I'll see what I can do in implementing this myself, maybe I can provide
a patch...
I didn't find the exact format of this in the ECMA-335, only them
mentioning calling "ToXML()" on the CustomAttribute...
However, since .NET 1.x seems to be the only place where the XML format
is used, I have implemented the ToXml()/FromXml() functions myself and
included them in AssemblyReader.cs/AssemblyWriter.cs.
The current implementation is somewhat incomplete in that it
a) doesn't allow to write permissionsets for .NET 1.1 assemblies and
b) writes blob-style permissionsets including XML strings when modifying
.NET 1.1 assemblies (which I'm not sure .NET 2.0 and above can handle)
Any chance of this going in to the main sources? I'll attach my code
below. The downside is it adds a dependency to System.Xml.dll.
Thanks for the help on this (pointing me in the right direction), I
really thought there was something wrong with our merge process :-)
Simon
--
AssemblyReader.cs:
SecurityAttribute ParseXmlSecurityDeclaration(string xmlString)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlString);
XmlNode permissionSet = xmlDoc.SelectSingleNode("/PermissionSet");
if (permissionSet == null)
return null;
XmlNode permissionSetClass =
permissionSet.SelectSingleNode("@class"); // check version?
if (permissionSetClass == null)
return null;
if (permissionSetClass.Value != "System.Security.PermissionSet")
return null;
XmlNode iPermission = permissionSet.SelectSingleNode("IPermission");
if (iPermission == null)
return null;
XmlNode iPermissionClass = iPermission.SelectSingleNode("@class");
// check version?
if (iPermissionClass == null)
return null;
// Create Namespace & Name from FullName, AssemblyName can be
ignored since we look it up.
Collection<string> classNamespace = new
Collection<string>(iPermissionClass.Value.Split(',')[0].Split('.'));
string className = classNamespace[classNamespace.Count - 1];
classNamespace.RemoveAt(classNamespace.Count - 1);
SecurityAttribute attribute = new
SecurityAttribute(module.TypeSystem.LookupType(string.Join(".",
classNamespace.ToArray()), className));
attribute.properties = new Collection<CustomAttributeNamedArgument>(1);
foreach (XmlAttribute xmlAttr in iPermission.Attributes)
{
if ((xmlAttr.Name != "class") && (xmlAttr.Name != "version"))
{
attribute.properties.Add(new CustomAttributeNamedArgument(
xmlAttr.Name,
new CustomAttributeArgument(
module.TypeSystem.String,
xmlAttr.Value)));
}
}
return attribute;
}
void ReadXmlSecurityDeclaration(uint signature, SecurityDeclaration
declaration)
{
var blob = ReadBlob(signature);
string xmlString = Encoding.Unicode.GetString(blob, 0, blob.Length);
var attributes = new Collection<SecurityAttribute>(1);
var attribute = ParseXmlSecurityDeclaration(xmlString);
attributes.Add (attribute);
declaration.security_attributes = attributes;
}
AssemblyWriter.cs:
SignatureWriter GetXmlSecurityDeclarationSignature(SecurityDeclaration
declaration)
{
SecurityAttribute sa = declaration.SecurityAttributes[0];
TypeReference attrType = sa.AttributeType;
AssemblyNameReference attrAsm = (AssemblyNameReference)attrType.Scope;
string className = attrType.FullName + ", " + attrAsm.FullName;
XmlDocument xmlDoc = new XmlDocument();
XmlElement permissionSet = xmlDoc.CreateElement("PermissionSet");
permissionSet.SetAttribute("class", "System.Security.PermissionSet");
permissionSet.SetAttribute("version", "1");
XmlElement iPermission = xmlDoc.CreateElement("IPermission");
iPermission.SetAttribute("class", className);
iPermission.SetAttribute("version", "1");
foreach (var arg in sa.Properties)
{
iPermission.SetAttribute(arg.Name, arg.Argument.Value.ToString());
}
permissionSet.AppendChild(iPermission);
xmlDoc.AppendChild(permissionSet);
string xmlDocString = xmlDoc.InnerXml;
byte[] bytes = Encoding.Unicode.GetBytes(xmlDocString);
var signature = CreateSignatureWriter();
signature.WriteBytes(bytes);
return signature;
}
SignatureWriter GetSecurityDeclarationSignature(SecurityDeclaration
declaration)
{
var signature = CreateSignatureWriter();
if (!declaration.resolved)
{
signature.WriteBytes(declaration.GetBlob());
return signature;
}
if (module.Runtime <= TargetRuntime.Net_1_1)
{
return GetXmlSecurityDeclarationSignature(declaration);
}
//... old non-1.1 code as before
}
--
--
mono-cecil