Error validating Xml against Xsd Schema - validation

I have the following Xml which I want to validate against Xsd Schema (below).
I am trying to validate the Xml against the given Xsd Schema using the C# function given below. I am getting this generic kind error message "Data at the root level is invalid. Line 1, position 1". This happens at "while(vr.Read())".
Can you please explain what is the cause and resolution to this problem or is there a way I can troubleshoot these type of generic errors.
As you can see from my Xsd schema that it has references to other child xsd files also. I am wondering if it has something to do with the error.
Warm Regards
XML File
<?xml version="1.0" encoding="utf-8"?>
<n1:Form109495CTransmittalUpstream xmlns="urn:us:gov:treasury:irs:ext:aca:air:6.2" xmlns:irs="urn:us:gov:treasury:irs:common" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:n1="urn:us:gov:treasury:irs:msg:form1094-1095Ctransmitterupstreammessage" xsi:schemaLocation="urn:us:gov:treasury:irs:msg:form1094-1095Ctransmitterupstreammessage IRS-Form1094-1095CTransmitterUpstreamMessage.xsd">
<Form1094CUpstreamDetail recordType="C" lineNum="0">
<--MORE XML TAGS HERE -->
</Form1094CUpstreamDetail>
</n1:Form109495CTransmittalUpstream>
XSD Schema
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="urn:us:gov:treasury:irs:msg:form1094-1095Ctransmitterupstreammessage"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:irs="urn:us:gov:treasury:irs:common"
xmlns:air6.2="urn:us:gov:treasury:irs:ext:aca:air:6.2"
targetNamespace="urn:us:gov:treasury:irs:msg:form1094-1095Ctransmitterupstreammessage"
elementFormDefault="qualified" attributeFormDefault="unqualified" version="1.0">
<xsd:annotation>
<xsd:appinfo>
<release>ACA Release 6.2</release>
</xsd:appinfo>
<xsd:documentation>Form-1094C (Issuer) Transmittal and Form 1095C - Transmittal of Health Insurance Coverage Statements
<VersionNum>5.2</VersionNum>
<VersionEffectiveBeginDt>2015-01-06</VersionEffectiveBeginDt>
</xsd:documentation>
</xsd:annotation>
<!-- ===== Imports ===== -->
<xsd:import namespace="urn:us:gov:treasury:irs:common" schemaLocation="common-IRS-CAC.xsd"/>
<xsd:import namespace="urn:us:gov:treasury:irs:ext:aca:air:6.2"
schemaLocation="ext-IRS-EXT-ACA-AIR-6.2.xsd"/>
<xsd:element name="Form109495CTransmittalUpstream" type="Form109495CTransmittalUpstreamType">
<xsd:annotation>
<xsd:documentation>
<Component>
<DictionaryEntryNm>Form109495C Transmission Upstream</DictionaryEntryNm>
<MajorVersionNum>1</MajorVersionNum>
<MinorVersionNum>1</MinorVersionNum>
<VersionEffectiveBeginDt>2015-01-06</VersionEffectiveBeginDt>
<VersionDescriptionTxt>Initial Version</VersionDescriptionTxt>
<DescriptionTxt>The elements associated with 1094C data generated EOY report</DescriptionTxt>
</Component>
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:complexType name="Form109495CTransmittalUpstreamType">
<xsd:annotation>
<xsd:documentation>
<Component>
<DictionaryEntryNm>Form109495C Transmission Upstream Type</DictionaryEntryNm>
<MajorVersionNum>1</MajorVersionNum>
<MinorVersionNum>1</MinorVersionNum>
<VersionEffectiveBeginDt>2014-11-05</VersionEffectiveBeginDt>
<VersionDescriptionTxt>Initial Version</VersionDescriptionTxt>
<DescriptionTxt>Transmission type for 1094C forms upstream data generated EOY report</DescriptionTxt>
</Component>
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element ref="air6.2:Form1094CUpstreamDetail" minOccurs="1" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
Following is the C# Validation Function:
/// <SUMMARY>
/// This method validates an xml string against an xml schema.
/// </SUMMARY>
/// <PARAM name="xml">StringReader containing xml</PARAM>
/// <PARAM name="schemaNamespace">XML Schema Namespace</PARAM>
/// <PARAM name="schemaUri">XML Schema Uri</PARAM>
/// <RETURNS>bool</RETURNS>
public bool ValidXmlDoc(StringReader xml,
string schemaNamespace, string schemaUri)
{
// Continue?
if(xml == null || schemaNamespace == null || schemaUri == null)
{
return false;
}
isValidXml = true;
XmlValidatingReader vr;
XmlTextReader tr;
XmlSchemaCollection schemaCol = new XmlSchemaCollection();
schemaCol.Add(schemaNamespace, schemaUri);
try
{
// Read the xml.
tr = new XmlTextReader(xml);
// Create the validator.
vr = new XmlValidatingReader(tr);
// Set the validation tyep.
vr.ValidationType = ValidationType.Schema;
// Add the schema.
if(schemaCol != null)
{
vr.Schemas.Add(schemaCol);
}
// Set the validation event handler.
vr.ValidationEventHandler +=
new ValidationEventHandler(ValidationCallBack);
// Read the xml schema.
while(vr.Read())
{
}
vr.Close();
return isValidXml;
}
catch(Exception ex)
{
this.ValidationError = ex.Message;
return false;
}
finally
{
// Clean up...
vr = null;
tr = null;
}
}

AFAIK XmlValidatingReader is obsolete. I think you would be much better of using XmlReader. In order to control URI resolutions(should schema has references to other schemes as relative paths) you could create your own XML URL resolver class by inheriting from XmlUrlResolver and overriding ResolveUri method. Then assign it to the XmlResolver member of XmlReaderSettings class. But I hope things would not deteriorate to that, though.:) Hopefully.:) Here is schematic code I could suggest:
XmlTextReader reader = new XmlTextReader(pathToXSD);
XmlSchema schema = XmlSchema.Read(reader, ValidationEventHandler);
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
settings.ValidationEventHandler += new ValidationEventHandler(ValidationEventHandler);
settings.Schemas.Add(schema);
using (StringReader xmlStream = new StringReader(xml))
{
using (XmlReader xmlReader = XmlReader.Create(xmlStream, settings))
{
while (xmlReader.Read()) { }
}
}

Related

How change namespace of Soap ns2 message in %SOAP.Webclient

I've created a soap client connection using the wizard of Atelier and it has created all messages (request and response) and the business operation object.
This soap connection will be used to connecto with other SOAP Webservices (changing the URL) but the namespace of the envelope will be different for the destination.
I've done a change into the Soap class to add my namespace for the envelope
Property Namespace As %String
Parameter SETTINGS = "Namespace:Basic";
Method methodFind(idEspecialist As %String(REQUIRED=1), actList As %ListOfObjects(Myapp.ns2.actType") [ Final, ProcedureBlock = 1, SoapBindingStyle = document, SoapBodyUse = literal, WebMethod ]
{
Quit ..WebMethod("methodFind").Invoke($this,..Namespace_"/methodFind",.idEspecialist,.actList)
}
and it works, only I have to create a new BO item in the producction and set the namespace for the destination.
But the ns.actType has the property namespace in the definition (as I said, this object has been created with the wizard of Atelire (SOAP)) and it is used for all BO.
/// created from: http://mywsservice.salutic.org/EspecialistWS?wsdl=EspecialistWSSoap.wsdl
Class Myapp.ns2.actoType Extends (%SerialObject, %XML.Adaptor) [ ProcedureBlock ]
{
Parameter ELEMENTQUALIFIED = 1;
Parameter NAMESPACE = "http://mywsservice.salutic.org/";
Parameter XMLNAME = "actType";
Parameter XMLSEQUENCE = 1;
Property ActCode As %String(MAXLEN = "", XMLNAME = "ActCode") [ Required ];
Property description As %String(MAXLEN = "", XMLNAME = "description") [ Required ];
......
......
}
So, when the invokeClient method is creating the SOAP Envelope, it looks like this:
<?xml version="1.0" encoding="UTF-8" ?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:s='http://www.w3.org/2001/XMLSchema'>
<SOAP-ENV:Body>
<methodFind xmlns="http://customer.namespace.org/">
<idEspecialist xsi:type="s:string">TAC</idEspecialist>
<actList>
<act xmlns:s01="http://mywsservice.salutic.org/" xsi:type="s01:actoType">
<ActCode xsi:type="s:string">1032001</ActCode>
<description xsi:type="s:string">Torax</description>
</act>
</actList>
</methodFind>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Is there any way to change the namespace of the node programmatically?
Best regards,
Kurro López
I can't see your code to give specifics but when the client object is created it should have a %SOAP.SessionHeader that has a NAMESPACE property. It should be attached to the HeadersOut property of the SOAP.WebClient
This is all from memory though so you need to check.

How can I add "Organization" declaration into SP's metadata (Spring SAML)?

Is there any way to include the informations about the Organization into the generated SP's metadata with Spring Security? Because by default I can't see it included in the generated metadata XML.
What I'm currently getting
I've tried to create a custom class SAMLMetadataGenerator which extends the framework's class MetadataGenerator, and then tried to Override the buildExtensions method in the following way:
public class SAMLMetadataGenerator extends MetadataGenerator {
#Override
protected Extensions buildExtensions(String entityBaseURL, String entityAlias) {
super.setIncludeDiscoveryExtension(true);
Extensions extensions = super.buildExtensions(entityBaseURL, entityAlias);
if (extensions != null)
extensions.getUnknownXMLObjects().add(generateOrganization());
return extensions;
}
private Organization generateOrganization() {
OrganizationBuilder organizationBuilder = new OrganizationBuilder();
Organization organization = organizationBuilder.buildObject();
OrganizationNameBuilder organizationNameBuilder = new OrganizationNameBuilder();
OrganizationName organizationName = organizationNameBuilder.buildObject();
organizationName.setName(new LocalizedString("ACME", "en"));
OrganizationDisplayNameBuilder displayNameBuilder = new OrganizationDisplayNameBuilder();
OrganizationDisplayName organizationDisplayName = displayNameBuilder
.buildObject();
organizationDisplayName.setName(new LocalizedString("ACME Corporation", "en"));
OrganizationURLBuilder organizationURLBuilder = new OrganizationURLBuilder();
OrganizationURL organizationURL = organizationURLBuilder.buildObject();
organizationURL.setURL(new LocalizedString("http://spid.serviceprovider.it", "it"));
organization.getOrganizationNames().add(organizationName);
organization.getDisplayNames().add(organizationDisplayName);
organization.getURLs().add(organizationURL);
return organization;
}
}
This way the produced SP's metadata is then:
<md:EntityDescriptor
xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="com_xegiy84105_spring_sp" entityID="com:xegiy84105:spring:sp">
<!-- Other things here -->
<md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<md:Extensions>
<idpdisco:DiscoveryResponse
xmlns:idpdisco="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" Binding="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" Location="http://localhost:8091/DM-WEB/saml/login?disco=true" index="0"/>
<md:Organization>
<md:OrganizationName xml:lang="en">ACME</md:OrganizationName>
<md:OrganizationDisplayName xml:lang="en">ACME Corporation</md:OrganizationDisplayName>
<md:OrganizationURL xml:lang="it">http://spid.serviceprovider.it</md:OrganizationURL>
</md:Organization>
</md:Extensions>
<!-- Other things here -->
</md:SPSSODescriptor>
</md:EntityDescriptor>
How it should really be
But the "Organization" block should be inserted without being surrounded by <md:Extensions/> and it should be placed as a direct child of the <md:EntityDescriptor/> block similiar to the following snippet:
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
entityID="https://spid.serviceprovider.it"
ID="_0j40cj0848d8e3jncjdjss...">
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
[...]
</ds:Signature>
<md:SPSSODescriptor
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"
AuthnRequestsSigned="true"
WantAssertionsSigned="true">
[...]
</md:SPSSODescriptor>
<md:Organization>
<OrganizationName xml:lang="it">Service provider</OrganizationName>
<OrganizationDisplayName xml:lang="it">Nome service provider</OrganizationDisplayName>
<OrganizationURL xml:lang="it">http://spid.serviceprovider.it</OrganizationURL>
</md:Organization>
</md:EntityDescriptor>
What is the correct way to achieve this goal?
Thanks.
The reason it's in the extensions is this:
extensions.getUnknownXMLObjects().add(generateOrganization());
according to the docs for MetadataGenerator you can use:
generateMetadata()
which returns an EntityDescriptor, which you can add the org to:
setOrganization(generateOrganization());

How do I open an internally created pdf in Xamarin.Android via a FileProvider in the default system pdf app?

I created a .pdf file in the private local directory I got via (I try to work with the minimum of permissions):
string targetBaseDir = Environment.GetFolderPath(
Environment.SpecialFolder.Personal,
Environment.SpecialFolderOption.Create
);
The official Android documentation suggests that file should be shared via a FileProvider.
I also tried to get some code to start an intent, and I'm currently at:
var fileUri = Android.Net.Uri.Parse(filePath);
var intent = new Intent();
intent.SetFlags(ActivityFlags.ClearTop);
intent.SetFlags(ActivityFlags.NewTask);
intent.SetAction(Intent.ActionView);
intent.SetType("application/pdf");
intent.PutExtra(Intent.ExtraStream, fileUri);
intent.AddFlags(ActivityFlags.GrantReadUriPermission);
Android.App.Application.Context.StartActivity(intent);
This starts the share dialog for a pdf file but while the Adobe Pdf reader gets opened it shows an empty view and not my pdf file.
You need to wrap your URI with FileProvider. Since android uri will give you file:// while FileProvider will give you content://, which you actually need:
public static Android.Net.Uri WrapFileWithUri(Context context,Java.IO.File file)
{
Android.Net.Uri result;
if (Build.VERSION.SdkInt < (BuildVersionCodes)24)
{
result = Android.Net.Uri.FromFile(file);
}
else
{
result = FileProvider.GetUriForFile(context, context.ApplicationContext.PackageName + ".provider", file);
}
return result;
}
File can be createed this way:
var file = new Java.IO.File(filePath);
Then you can open it:
public static void View(Context context, string path, string mimeType)
{
Intent viewIntent = new Intent(Intent.ActionView);
Java.IO.File document = new Java.IO.File(path);
viewIntent.SetDataAndType(UriResolver.WrapFileWithUri(context,document),mimeType);
viewIntent.SetFlags(ActivityFlags.NewTask);
viewIntent.AddFlags(ActivityFlags.GrantReadUriPermission);
context.StartActivity(Intent.CreateChooser(viewIntent, "your text"));
}
Be aware, that this line
viewIntent.SetDataAndType(UriResolver.WrapFileWithUri(context,document),mimeType);
does not equal to SetData and SetType separate commands.
And yes, you need to add FileProvider to your manifest:
<provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.provider" android:exported="false" android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="#xml/provider_paths" />
</provider>
Also you need to create Resources\xml folder with provider_paths.xml file:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
<files-path name="internal_files" path="." />
</paths>

Spring Web Flow validator not found

I am trying to do form validation in Spring Web Flow. For this I am using a validator class, which is named after the model. Just like it is stated in the documentation.
The validator gets instantiated as a bean but is never called during validation. Any pointers on that issue?
flow config
<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow-2.4.xsd">
<view-state id="createTotpKeyView" view="/templates/totp/create/create" model="key">
<on-entry>
<evaluate expression="createTotpKeyAction"/>
</on-entry>
<transition on="submit" to="successfullyCreated" bind="true" validate="true"/>
</view-state>
<end-state id="successfullyCreated" view="/templates/totp/create/success"/>
</flow>
This is the action that is called in the view-state.
createTotpKeyAction
#Component
public class CreateTotpKeyAction implements Action
{
String uid = "random";
#Override
public Event execute(RequestContext context) throws Exception
{
try
{
// Create a TOTP key and put it in the view scope
TOTPKey totpKey = client.createTotpKeyForUid(uid, null);
context.getViewScope().put("key", totpKey);
return new Event(this, "success");
}
catch (Exception e)
{
log.error("Error while creating TOTP key for user: " + uid + ".\n" + e.getMessage());
// Put response message in flash scope to show it once
context.getFlashScope().put("fetchingError", true);
return new Event(this, "error");
}
}
}
This is the validator I am trying to use. EDIT renamed to match documentation.
KeyValidator
#Component
public class KeyValidator
{
[...]
public void validateCreateTotpKeyView(TOTPKey key, ValidationContext context)
{
System.out.println("VALIDATE VIEW STATE");
}
public void validate(TOTPKey key, ValidationContext context)
{
System.out.println("DEFAULT VALIDATE");
}
}
I also tried different naming schemes such as TOTPKeyValidator or TotpKeyValidator. None of them worked.
The only thing that is working, is creating a validation method in the TOTPKey class, but I don't want to use that approach.
In addition this is the log file produced during the attempted validation
Log
Mapping request with URI '/totp/create' to flow with id 'totp/create'
Resuming flow execution with key 'e5s1
Locking conversation 5
Getting flow execution with key 'e5s1'
Getting FlowDefinition with id 'totp/create'
Resuming in org.springframework.webflow.mvc.servlet.MvcExternalContext#2b551393
Restoring [FlowVariable#3b66a2de name = 'key', valueFactory = [BeanFactoryVariableValueFactory#2fbc89 type = TOTPKey]]
Processing user event 'submit'
Resolved model twofa.core.domain.TOTPKey#505439d0
Binding to model
Adding default mapping for parameter 'execution'
Adding default mapping for parameter 'totpKeyId'
Adding default mapping for parameter 'token'
Adding empty value mapping for parameter 'eventId_submit'
Validating model
Event 'submit' returned from view [ServletMvcView#19f8532f view = org.springframework.web.servlet.view.velocity.VelocityLayoutView: name '/templates/totp/create/create'; URL [/templates/totp/create/create.vm]]
Executing [Transition#2feb5361 on = submit, to = successfullyCreated]
Exiting state 'createTotpKeyView'
Entering state 'successfullyCreated' of flow 'totp/create'
Executing org.springframework.webflow.action.ViewFactoryActionAdapter#423fa131
Rendering MVC [org.springframework.web.servlet.view.velocity.VelocityLayoutView: name '/templates/totp/create/success'; URL [/templates/totp/create/success.vm]] with model map [{currentUser=null, flashScope=map[[empty]], flowRequestContext=[RequestControlContextImpl#70144045 externalContext = org.springframework.webflow.mvc.servlet.MvcExternalContext#2b551393, currentEvent = submit, requestScope = map[[empty]], attributes = map[[empty]], messageContext = [DefaultMessageContext#149807b4 sourceMessages = map[[null] -> list[[empty]]]], flowExecution = [FlowExecutionImpl#1c4b2c3e flow = 'totp/create', flowSessions = list[[FlowSessionImpl#6eea5d26 flow = 'totp/create', state = 'successfullyCreated', scope = map['key' -> twofa.core.domain.TOTPKey#73f32d0a]]]]], flowExecutionKey=e5s1, flowExecutionUrl=/totp/create?execution=e5s1, key=twofa.core.domain.TOTPKey#73f32d0a}]
Finished executing org.springframework.webflow.action.ViewFactoryActionAdapter#423fa131; result = success
Completed transition execution. As a result, the flow execution has ended
Removing flow execution '[Ended execution of 'totp/create']' from repository
Ending conversation 5
Unlocking conversation 5
It says Validating Model but nothing happens...
It came down to a wrong import statement in my validator class.
Using org.relaxng.datatype.ValidationContext instead of org.springframework.binding.validation.ValidationContext will not work.

Sitecore Media Library MaxSize

In Sitecore, I'd like to set Upload MaxSize only for image files.
We can update Media.MaxSizeInDatabase to set the MaxSize, but this setting includes all files in Media Library.
Is there any way to set MaxSize only for image files? Or, can I create any validation for this??
Thank you in advance!!
========= Update ==========
I tried to use all code and setting, but it was not working. I think Code is fine, but I might have to make sure the place of configurations. When I add "xmlns:patch" attribute in on the top, like below
<?xml version="1.0" encoding="UTF-8"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
It show error "Unrecongnized attribute xmlns:patch". So, I added the configurations in "/configuration/sitecore" element in a web.config, like below
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
.....
<sitecore database="SqlServer">
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<processors>
<uiUpload>
<processor mode="on" type="ImageMaxSize.ImageItemValidator2, Sitecore.Kernel" patch:before="processor[#type='Sitecore.Pipelines.Upload.CheckSize, Sitecore.Kernel']">
<restrictedExtensions hint="raw:AddRestrictedExtension">
<!-- Be sure to prefix with a dot -->
<extension>.jpg</extension>
<extension>.jepg</extension>
<extension>.png</extension>
<extension>.bmp</extension>
</restrictedExtensions>
</processor>
</uiUpload>
</processors>
</sitecore>
</configuration>
This is not working
You can patch in your own processor into uiUpload to check the file size for certain types, in a very similar way to this post from Mike Reynolds to restrict certain file types to be upload.
public class ImageCheckSize : UploadProcessor
{
public List<string> RestrictedExtensions { get; set; }
public ImageCheckSize()
{
RestrictedExtensions = new List<string>();
}
public void Process(UploadArgs args)
{
Assert.ArgumentNotNull((object) args, "args");
if (args.Destination == UploadDestination.File)
return;
foreach (string index in args.Files)
{
HttpPostedFile file = args.Files[index];
if (!string.IsNullOrEmpty(file.FileName) && IsRestrictedExtension(file.FileName))
{
if ((long) file.ContentLength > MaxImageSizeInDatabase)
{
args.ErrorText = string.Format("The image \"{0}\" is too big to be uploaded. The maximum size for uploading images is {1}.", file.FileName, MainUtil.FormatSize(MaxImageSizeInDatabase));
Log.Warn(args.ErrorText, this);
args.AbortPipeline();
break;
}
}
}
}
private bool IsRestrictedExtension(string filename)
{
return RestrictedExtensions.Exists(restrictedExtension => string.Equals(restrictedExtension, Path.GetExtension(filename), StringComparison.CurrentCultureIgnoreCase));
}
public static long MaxImageSizeInDatabase
{
get
{
return Sitecore.Configuration.Settings.GetLongSetting("Media.MaxImageSizeInDatabase", 524288000L);
}
}
}
And then add in the required config changes. Create a new config file in /App_Config/Includes (e.g. ImageSizeCheck.config)
<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<processors>
<uiUpload>
<processor mode="on" type="Custom.Business.Pipeline.Upload.ImageCheckSize, Custom.Business"
patch:before="processor[#type='Sitecore.Pipelines.Upload.CheckSize, Sitecore.Kernel']">
<restrictedExtensions hint="list">
<extension>.jpg</extension>
<extension>.png</extension>
</restrictedExtensions>
</processor>
</uiUpload>
</processors>
<settings>
<setting name="Media.MaxImageSizeInDatabase" value="1MB" />
</settings>
</sitecore>
</configuration>
You will also need to add another processor into attachFile processors to handle if the user attaches a new file to an existing media item - use dotPeek to see the implementation in Sitecore.Pipelines.Attach.CheckSize,Sitecore.Kernel.
One caveat to this is that the displayed error message is not too friendly, but the error is logged correctly in the log files :(

Resources