You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
232
mcs/class/referencesource/System.Web/HttpFileCollection.cs
Normal file
232
mcs/class/referencesource/System.Web/HttpFileCollection.cs
Normal file
@ -0,0 +1,232 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="HttpFileCollection.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* Collection of posted files for the request intrinsic
|
||||
*
|
||||
* Copyright (c) 1998 Microsoft Corporation
|
||||
*/
|
||||
|
||||
namespace System.Web {
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Web.Util;
|
||||
|
||||
/// <devdoc>
|
||||
/// <para>
|
||||
/// Accesses incoming files uploaded by a client (using
|
||||
/// multipart MIME and the Http Content-Type of multipart/formdata).
|
||||
/// </para>
|
||||
/// </devdoc>
|
||||
public sealed class HttpFileCollection : NameObjectCollectionBase {
|
||||
// cached All[] arrays
|
||||
private HttpPostedFile[] _all;
|
||||
private String[] _allKeys;
|
||||
|
||||
// for implementing granular request validation
|
||||
private ValidateStringCallback _validationCallback;
|
||||
private HashSet<HttpPostedFile> _filesAwaitingValidation;
|
||||
|
||||
|
||||
[SuppressMessage("Microsoft.Globalization", "CA1309:UseOrdinalStringComparison", MessageId = "System.Collections.Specialized.NameObjectCollectionBase.#ctor(System.Collections.IEqualityComparer)", Justification = @"By design")]
|
||||
internal HttpFileCollection()
|
||||
: base(StringComparer.InvariantCultureIgnoreCase) {
|
||||
}
|
||||
|
||||
// This copy constructor is used by the granular request validation feature. Since these collections are immutable
|
||||
// once created, it's ok for us to have two collections containing the same data.
|
||||
internal HttpFileCollection(HttpFileCollection col)
|
||||
: this() {
|
||||
|
||||
// We explicitly don't copy validation-related fields, as we want the copy to "reset" validation state.
|
||||
|
||||
// Copy the file references from the original collection into this instance
|
||||
for (int i = 0; i < col.Count; i++) {
|
||||
ThrowIfMaxHttpCollectionKeysExceeded();
|
||||
string key = col.BaseGetKey(i);
|
||||
object value = col.BaseGet(i);
|
||||
BaseAdd(key, value);
|
||||
}
|
||||
|
||||
IsReadOnly = col.IsReadOnly;
|
||||
}
|
||||
|
||||
/// <devdoc>
|
||||
/// <para>[To be supplied.]</para>
|
||||
/// </devdoc>
|
||||
public void CopyTo(Array dest, int index) {
|
||||
if (_all == null) {
|
||||
int n = Count;
|
||||
HttpPostedFile[] all = new HttpPostedFile[n];
|
||||
for (int i = 0; i < n; i++)
|
||||
all[i] = Get(i);
|
||||
_all = all; // wait until end of loop to set _all reference in case Get throws
|
||||
}
|
||||
|
||||
if (_all != null) {
|
||||
_all.CopyTo(dest, index);
|
||||
}
|
||||
}
|
||||
|
||||
internal void AddFile(String key, HttpPostedFile file) {
|
||||
ThrowIfMaxHttpCollectionKeysExceeded();
|
||||
|
||||
_all = null;
|
||||
_allKeys = null;
|
||||
|
||||
BaseAdd(key, file);
|
||||
}
|
||||
|
||||
// MSRC 12038: limit the maximum number of items that can be added to the collection,
|
||||
// as a large number of items potentially can result in too many hash collisions that may cause DoS
|
||||
private void ThrowIfMaxHttpCollectionKeysExceeded() {
|
||||
if (Count >= AppSettings.MaxHttpCollectionKeys) {
|
||||
throw new InvalidOperationException(SR.GetString(SR.CollectionCountExceeded_HttpValueCollection, AppSettings.MaxHttpCollectionKeys));
|
||||
}
|
||||
}
|
||||
|
||||
internal void EnableGranularValidation(ValidateStringCallback validationCallback) {
|
||||
// Iterate over all the files, adding each to the set containing the files awaiting validation.
|
||||
// Unlike dictionaries, HashSet<T> can contain null keys, so don't need to special-case them.
|
||||
_filesAwaitingValidation = new HashSet<HttpPostedFile>();
|
||||
for (int i = 0; i < Count; i++) {
|
||||
_filesAwaitingValidation.Add((HttpPostedFile)BaseGet(i));
|
||||
}
|
||||
_validationCallback = validationCallback;
|
||||
}
|
||||
|
||||
private void EnsureFileValidated(HttpPostedFile file) {
|
||||
if (_filesAwaitingValidation == null) {
|
||||
// If dynamic validation hasn't been enabled, no-op.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_filesAwaitingValidation.Contains(file)) {
|
||||
// If this file has already been validated (or is excluded), no-op.
|
||||
return;
|
||||
}
|
||||
|
||||
// If validation fails, the callback will throw an exception. If validation succeeds,
|
||||
// we can remove it from the candidates list. Key is unused.
|
||||
_validationCallback(null /* key */, file.FileName);
|
||||
_filesAwaitingValidation.Remove(file);
|
||||
}
|
||||
|
||||
//
|
||||
// Access by name
|
||||
//
|
||||
|
||||
|
||||
/// <devdoc>
|
||||
/// <para>
|
||||
/// Returns a file from
|
||||
/// the collection by file name.
|
||||
/// </para>
|
||||
/// </devdoc>
|
||||
public HttpPostedFile Get(String name) {
|
||||
HttpPostedFile file = (HttpPostedFile)BaseGet(name);
|
||||
if (file != null) {
|
||||
EnsureFileValidated(file);
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
/// <devdoc>
|
||||
/// Returns all files from this collection that match the given name.
|
||||
/// This is to support multi-file uploads (either via HTML5 or JS emulators).
|
||||
/// This method returns a new collection instance for each invocation and callers are
|
||||
/// encouraged to call this method once per name per request.
|
||||
/// </devdoc>
|
||||
|
||||
[SuppressMessage("Microsoft.Globalization", "CA1309:UseOrdinalStringComparison", MessageId = "System.String.Equals(System.String,System.String,System.StringComparison)", Justification = @"By design")]
|
||||
public IList<HttpPostedFile> GetMultiple(string name) {
|
||||
List<HttpPostedFile> result = new List<HttpPostedFile>();
|
||||
for (int i = 0; i < Count; i++) {
|
||||
string key = GetKey(i);
|
||||
// Use InvariantCultureIgnoreCase since this is the comparison used for this collection
|
||||
if (String.Equals(key, name, StringComparison.InvariantCultureIgnoreCase)) {
|
||||
// Call the Get() method instead of looking at the _all array directly
|
||||
// to ensure that request validation happens for the file.
|
||||
result.Add(Get(i));
|
||||
}
|
||||
}
|
||||
return result.AsReadOnly();
|
||||
}
|
||||
|
||||
|
||||
/// <devdoc>
|
||||
/// <para>Returns item value from collection.</para>
|
||||
/// </devdoc>
|
||||
public HttpPostedFile this[String name]
|
||||
{
|
||||
get { return Get(name);}
|
||||
}
|
||||
|
||||
//
|
||||
// Indexed access
|
||||
//
|
||||
|
||||
|
||||
/// <devdoc>
|
||||
/// <para>
|
||||
/// Returns a file from
|
||||
/// the file collection by index.
|
||||
/// </para>
|
||||
/// </devdoc>
|
||||
public HttpPostedFile Get(int index) {
|
||||
HttpPostedFile file = (HttpPostedFile)BaseGet(index);
|
||||
if (file != null) {
|
||||
EnsureFileValidated(file);
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
/// <devdoc>
|
||||
/// <para>
|
||||
/// Returns key name from collection.
|
||||
/// </para>
|
||||
/// </devdoc>
|
||||
public String GetKey(int index) {
|
||||
return BaseGetKey(index);
|
||||
}
|
||||
|
||||
|
||||
/// <devdoc>
|
||||
/// <para>
|
||||
/// Returns an
|
||||
/// item from the collection.
|
||||
/// </para>
|
||||
/// </devdoc>
|
||||
public HttpPostedFile this[int index]
|
||||
{
|
||||
get { return Get(index);}
|
||||
}
|
||||
|
||||
//
|
||||
// Access to keys and values as arrays
|
||||
//
|
||||
|
||||
|
||||
/// <devdoc>
|
||||
/// <para>
|
||||
/// Creates an
|
||||
/// array of keys in the collection.
|
||||
/// </para>
|
||||
/// </devdoc>
|
||||
public String[] AllKeys {
|
||||
get {
|
||||
if (_allKeys == null)
|
||||
_allKeys = BaseGetAllKeys();
|
||||
|
||||
return _allKeys;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user