/// <summary>
 /// Creates an <see cref="ODataWriter" /> to write an entry.
 /// </summary>
 /// <returns>The created writer.</returns>
 /// <remarks>The write must flush the output when it's finished (inside the last Write call).</remarks>
 internal virtual ODataWriter CreateODataEntryWriter()
 {
     DebugUtils.CheckNoExternalCallers();
     throw this.CreatePayloadKindNotSupportedException(ODataPayloadKind.Entry);
 }
Esempio n. 2
0
        internal static string GetStatusMessage(int statusCode)
        {
            DebugUtils.CheckNoExternalCallers();

            // Non-localized messages for status codes.
            // These are the recommended reason phrases as per HTTP RFC 2616, Section 6.1.1
            switch (statusCode)
            {
            case 100:
                return("Continue");

            case 101:
                return("Switching Protocols");

            case 200:
                return("OK");

            case 201:
                return("Created");

            case 202:
                return("Accepted");

            case 203:
                return("Non-Authoritative Information");

            case 204:
                return("No Content");

            case 205:
                return("Reset Content");

            case 206:
                return("Partial Content");

            case 300:
                return("Multiple Choices");

            case 301:
                return("Moved Permanently");

            case 302:
                return("Found");

            case 303:
                return("See Other");

            case 304:
                return("Not Modified");

            case 305:
                return("Use Proxy");

            case 307:
                return("Temporary Redirect");

            case 400:
                return("Bad Request");

            case 401:
                return("Unauthorized");

            case 402:
                return("Payment Required");

            case 403:
                return("Forbidden");

            case 404:
                return("Not Found");

            case 405:
                return("Method Not Allowed");

            case 406:
                return("Not Acceptable");

            case 407:
                return("Proxy Authentication Required");

            case 408:
                return("Request Time-out");

            case 409:
                return("Conflict");

            case 410:
                return("Gone");

            case 411:
                return("Length Required");

            case 412:
                return("Precondition Failed");

            case 413:
                return("Request Entity Too Large");

            case 414:
                return("Request-URI Too Large");

            case 415:
                return("Unsupported Media Type");

            case 416:
                return("Requested range not satisfiable");

            case 417:
                return("Expectation Failed");

            case 500:
                return("Internal Server Error");

            case 501:
                return("Not Implemented");

            case 502:
                return("Bad Gateway");

            case 503:
                return("Service Unavailable");

            case 504:
                return("Gateway Time-out");

            case 505:
                return("HTTP Version not supported");

            default:
                return("Unknown Status Code");
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Enumerates each charset part in the specified Accept-Charset header.
        /// </summary>
        /// <param name="headerValue">Non-null and non-empty header value for Accept-Charset.</param>
        /// <returns>
        /// A (non-sorted) enumeration of CharsetPart elements, which include
        /// a charset name and a quality (preference) value, normalized to 0-1000.
        /// </returns>
        private static IEnumerable <CharsetPart> AcceptCharsetParts(string headerValue)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(!String.IsNullOrEmpty(headerValue), "!String.IsNullOrEmpty(headerValuer)");

            // PERF: optimize for common patterns.
            bool commaRequired = false; // Whether a comma should be found
            int  headerIndex   = 0;     // Index of character being procesed on headerValue.
            int  headerStart;           // Index into headerValue for the start of the charset name.
            int  headerNameEnd;         // Index into headerValue for the end of the charset name (+1).
            int  headerEnd;             // Index into headerValue for this charset part (+1).
            int  qualityValue;          // Normalized qvalue for this charset.

            while (headerIndex < headerValue.Length)
            {
                if (SkipWhitespace(headerValue, ref headerIndex))
                {
                    yield break;
                }

                if (headerValue[headerIndex] == ',')
                {
                    commaRequired = false;
                    headerIndex++;
                    continue;
                }

                if (commaRequired)
                {
                    // Comma missing between charset elements.
                    throw new ODataContentTypeException(Strings.HttpUtils_MissingSeparatorBetweenCharsets(headerValue));
                }

                headerStart   = headerIndex;
                headerNameEnd = headerStart;

                bool endReached = ReadToken(headerValue, ref headerNameEnd);
                if (headerNameEnd == headerIndex)
                {
                    // Invalid (empty) charset name.
                    throw new ODataContentTypeException(Strings.HttpUtils_InvalidCharsetName(headerValue));
                }

                if (endReached)
                {
                    qualityValue = 1000;
                    headerEnd    = headerNameEnd;
                }
                else
                {
                    char afterNameChar = headerValue[headerNameEnd];
                    if (IsHttpSeparator(afterNameChar))
                    {
                        if (afterNameChar == ';')
                        {
                            if (ReadLiteral(headerValue, headerNameEnd, ";q="))
                            {
                                // Unexpected end of qvalue.
                                throw new ODataContentTypeException(Strings.HttpUtils_UnexpectedEndOfQValue(headerValue));
                            }

                            headerEnd = headerNameEnd + 3;
                            ReadQualityValue(headerValue, ref headerEnd, out qualityValue);
                        }
                        else
                        {
                            qualityValue = 1000;
                            headerEnd    = headerNameEnd;
                        }
                    }
                    else
                    {
                        // Invalid separator character.
                        throw new ODataContentTypeException(Strings.HttpUtils_InvalidSeparatorBetweenCharsets(headerValue));
                    }
                }

                yield return(new CharsetPart(headerValue.Substring(headerStart, headerNameEnd - headerStart), qualityValue));

                // Prepare for next charset; we require at least one comma before we process it.
                commaRequired = true;
                headerIndex   = headerEnd;
            }
        }
Esempio n. 4
0
 /// <summary>
 /// Adds a property to the Properties collection which must have been previously populated by CreateNewEntry.
 /// </summary>
 /// <param name="properties">The value of the Properties property to add the property to.</param>
 /// <param name="propertyToAdd">The property to add.</param>
 internal static void AddPropertyToPropertiesList(IEnumerable <ODataProperty> properties, ODataProperty propertyToAdd)
 {
     DebugUtils.CheckNoExternalCallers();
     Debug.Assert(propertyToAdd != null, "propertyToAdd != null");
     ReaderUtils.GetPropertiesList(properties).Add(propertyToAdd);
 }
Esempio n. 5
0
        /// <summary>
        /// Does an ordinal ignore case comparision of the given MIME type parameter name.
        /// </summary>
        /// <param name="parameterName1">First parameter name.</param>
        /// <param name="parameterName2">Second parameter name.</param>
        /// <returns>returns true if the parameter names are the same.</returns>
        internal static bool CompareMediaTypeParameterNames(string parameterName1, string parameterName2)
        {
            DebugUtils.CheckNoExternalCallers();

            return(string.Equals(parameterName1, parameterName2, StringComparison.OrdinalIgnoreCase));
        }
 /// <summary>
 /// Asynchronous flush operation. This will flush all buffered bytes to the underlying stream through asynchronous writes.
 /// </summary>
 /// <returns>The task representing the asynchronous flush operation.</returns>
 internal Task FlushAsync()
 {
     DebugUtils.CheckNoExternalCallers();
     return(this.FlushAsyncInternal());
 }
        /// <summary>
        /// Reads from the batch stream while ensuring that we stop reading at each boundary.
        /// </summary>
        /// <param name="userBuffer">The byte array to read bytes into.</param>
        /// <param name="userBufferOffset">The offset in the buffer where to start reading bytes into.</param>
        /// <param name="count">The number of bytes to read.</param>
        /// <returns>The number of bytes actually read.</returns>
        internal int ReadWithDelimiter(byte[] userBuffer, int userBufferOffset, int count)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(userBuffer != null, "userBuffer != null");
            Debug.Assert(userBufferOffset >= 0 && userBufferOffset < userBuffer.Length, "Offset must be within the range of the user buffer.");
            Debug.Assert(count >= 0, "count >= 0");
            Debug.Assert(this.batchEncoding != null, "Batch encoding should have been established on first call to SkipToBoundary.");

            if (count == 0)
            {
                // Nothing to read.
                return(0);
            }

            int remainingNumberOfBytesToRead            = count;
            ODataBatchReaderStreamScanResult scanResult = ODataBatchReaderStreamScanResult.NoMatch;

            while (remainingNumberOfBytesToRead > 0 && scanResult != ODataBatchReaderStreamScanResult.Match)
            {
                int  boundaryStartPosition, boundaryEndPosition;
                bool isEndBoundary, isParentBoundary;
                scanResult = this.batchBuffer.ScanForBoundary(
                    this.CurrentBoundaries,
                    remainingNumberOfBytesToRead,
                    out boundaryStartPosition,
                    out boundaryEndPosition,
                    out isEndBoundary,
                    out isParentBoundary);

                int bytesBeforeBoundaryStart;
                switch (scanResult)
                {
                case ODataBatchReaderStreamScanResult.NoMatch:
                    // The boundary was not found in the buffer or after the required number of bytes to be read;
                    // Check whether we can satisfy the full read request from the buffer
                    // or whether we have to split the request and read more data into the buffer.
                    if (this.batchBuffer.NumberOfBytesInBuffer >= remainingNumberOfBytesToRead)
                    {
                        // we can satisfy the full read request from the buffer
                        Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, userBuffer, userBufferOffset, remainingNumberOfBytesToRead);
                        this.batchBuffer.SkipTo(this.batchBuffer.CurrentReadPosition + remainingNumberOfBytesToRead);
                        return(count);
                    }
                    else
                    {
                        // we can only partially satisfy the read request
                        int availableBytesToRead = this.batchBuffer.NumberOfBytesInBuffer;
                        Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, userBuffer, userBufferOffset, availableBytesToRead);
                        remainingNumberOfBytesToRead -= availableBytesToRead;
                        userBufferOffset             += availableBytesToRead;

                        // we exhausted the buffer; if the underlying stream is not exceeded, refill the buffer
                        if (this.underlyingStreamExhausted)
                        {
                            // We cannot fully satisfy the read request since there are not enough bytes in the stream.
                            // Return the number of bytes we read.
                            this.batchBuffer.SkipTo(this.batchBuffer.CurrentReadPosition + availableBytesToRead);
                            return(count - remainingNumberOfBytesToRead);
                        }
                        else
                        {
                            this.underlyingStreamExhausted = this.batchBuffer.RefillFrom(this.inputContext.Stream, /*preserveFrom*/ ODataBatchReaderStreamBuffer.BufferLength);
                        }
                    }

                    break;

                case ODataBatchReaderStreamScanResult.PartialMatch:
                    // A partial match for the boundary was found at the end of the buffer.
                    // If the underlying stream is not exceeded, refill the buffer. Otherwise return
                    // the available bytes.
                    if (this.underlyingStreamExhausted)
                    {
                        // We cannot fully satisfy the read request since there are not enough bytes in the stream.
                        // Return the remaining bytes in the buffer independently of where a portentially boundary
                        // start was detected since no full boundary can ever be detected if the stream is exhausted.
                        int bytesToReturn = Math.Min(this.batchBuffer.NumberOfBytesInBuffer, remainingNumberOfBytesToRead);
                        Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, userBuffer, userBufferOffset, bytesToReturn);
                        this.batchBuffer.SkipTo(this.batchBuffer.CurrentReadPosition + bytesToReturn);
                        remainingNumberOfBytesToRead -= bytesToReturn;
                        return(count - remainingNumberOfBytesToRead);
                    }
                    else
                    {
                        // Copy the bytes prior to the potential boundary start into the user buffer, refill the buffer and continue.
                        bytesBeforeBoundaryStart = boundaryStartPosition - this.batchBuffer.CurrentReadPosition;
                        Debug.Assert(bytesBeforeBoundaryStart < remainingNumberOfBytesToRead, "When reporting a partial match we should never have read all the remaining bytes to read (or more).");

                        Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, userBuffer, userBufferOffset, bytesBeforeBoundaryStart);
                        remainingNumberOfBytesToRead -= bytesBeforeBoundaryStart;
                        userBufferOffset             += bytesBeforeBoundaryStart;

                        this.underlyingStreamExhausted = this.batchBuffer.RefillFrom(this.inputContext.Stream, /*preserveFrom*/ boundaryStartPosition);
                    }

                    break;

                case ODataBatchReaderStreamScanResult.Match:
                    // We found the full boundary match; copy everything before the boundary to the buffer
                    bytesBeforeBoundaryStart = boundaryStartPosition - this.batchBuffer.CurrentReadPosition;
                    Debug.Assert(bytesBeforeBoundaryStart <= remainingNumberOfBytesToRead, "When reporting a full match we should never have read more than the remaining bytes to read.");
                    Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, userBuffer, userBufferOffset, bytesBeforeBoundaryStart);
                    remainingNumberOfBytesToRead -= bytesBeforeBoundaryStart;
                    userBufferOffset             += bytesBeforeBoundaryStart;

                    // position the reader on the position of the boundary start
                    this.batchBuffer.SkipTo(boundaryStartPosition);

                    // return the number of bytes that were read
                    return(count - remainingNumberOfBytesToRead);

                default:
                    break;
                }
            }

            throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReaderStream_ReadWithDelimiter));
        }
 /// <summary>
 /// Asynchronously writes an <see cref="ODataError"/> as the message payload.
 /// </summary>
 /// <param name="error">The error to write.</param>
 /// <param name="includeDebugInformation">
 /// A flag indicating whether debug information (e.g., the inner error from the <paramref name="error"/>) should
 /// be included in the payload. This should only be used in debug scenarios.
 /// </param>
 /// <returns>A task representing the asynchronous operation of writing the error.</returns>
 /// <remarks>It is the responsibility of this method to flush the output before the task finishes.</remarks>
 internal virtual Task WriteErrorAsync(ODataError error, bool includeDebugInformation)
 {
     DebugUtils.CheckNoExternalCallers();
     throw this.CreatePayloadKindNotSupportedException(ODataPayloadKind.Error);
 }
 /// <summary>
 /// Asynchronously writes a singleton result of a $links query as the message payload.
 /// </summary>
 /// <param name="link">The link result to write as message payload.</param>
 /// <returns>A running task representing the writing of the link.</returns>
 /// <remarks>It is the responsibility of this method to flush the output before the task finishes.</remarks>
 internal virtual Task WriteEntityReferenceLinkAsync(ODataEntityReferenceLink link)
 {
     DebugUtils.CheckNoExternalCallers();
     throw this.CreatePayloadKindNotSupportedException(ODataPayloadKind.EntityReferenceLink);
 }
Esempio n. 10
0
 /// <summary>
 /// Asynchronously writes a service document with the specified <paramref name="defaultWorkspace"/>
 /// as message payload.
 /// </summary>
 /// <param name="defaultWorkspace">The default workspace to write in the service document.</param>
 /// <returns>A task representing the asynchronous operation of writing the service document.</returns>
 /// <remarks>It is the responsibility of this method to flush the output before the task finishes.</remarks>
 internal virtual Task WriteServiceDocumentAsync(ODataWorkspace defaultWorkspace)
 {
     DebugUtils.CheckNoExternalCallers();
     throw this.CreatePayloadKindNotSupportedException(ODataPayloadKind.ServiceDocument);
 }
Esempio n. 11
0
 /// <summary>
 /// Asynchronously writes an <see cref="ODataProperty"/> as message payload.
 /// </summary>
 /// <param name="property">The property to write</param>
 /// <returns>A task representing the asynchronous operation of writing the property.</returns>
 /// <remarks>It is the responsibility of this method to flush the output before the task finishes.</remarks>
 internal virtual Task WritePropertyAsync(ODataProperty property)
 {
     DebugUtils.CheckNoExternalCallers();
     throw this.CreatePayloadKindNotSupportedException(ODataPayloadKind.Property);
 }
Esempio n. 12
0
 /// <summary>
 /// Asynchronously creates an <see cref="ODataParameterWriter" /> to write a parameter payload.
 /// </summary>
 /// <param name="functionImport">The function import whose parameters will be written.</param>
 /// <returns>A running task for the created parameter writer.</returns>
 /// <remarks>The write must flush the output when it's finished (inside the last Write call).</remarks>
 internal virtual Task <ODataParameterWriter> CreateODataParameterWriterAsync(IEdmFunctionImport functionImport)
 {
     DebugUtils.CheckNoExternalCallers();
     throw this.CreatePayloadKindNotSupportedException(ODataPayloadKind.Error);
 }
Esempio n. 13
0
 /// <summary>
 /// Asynchronously creates an <see cref="ODataBatchWriter" /> to write a batch of requests or responses.
 /// </summary>
 /// <param name="batchBoundary">The boundary string for the batch structure itself.</param>
 /// <returns>A running task for the created batch writer.</returns>
 /// <remarks>We don't plan to make this public!</remarks>
 /// <remarks>
 /// The write must flush the output when it's finished (inside the last Write call).
 /// Since we don't want to support batch format extensibility (at least not yet) this method should remain internal.
 /// </remarks>
 internal virtual Task <ODataBatchWriter> CreateODataBatchWriterAsync(string batchBoundary)
 {
     DebugUtils.CheckNoExternalCallers();
     throw this.CreatePayloadKindNotSupportedException(ODataPayloadKind.Batch);
 }
Esempio n. 14
0
 /// <summary>
 /// Asynchronously creates an <see cref="ODataCollectionWriter" /> to write a collection of primitive or complex values (as result of a service operation invocation).
 /// </summary>
 /// <returns>A running task for the created collection writer.</returns>
 /// <remarks>The write must flush the output when it's finished (inside the last Write call).</remarks>
 internal virtual Task <ODataCollectionWriter> CreateODataCollectionWriterAsync()
 {
     DebugUtils.CheckNoExternalCallers();
     throw this.CreatePayloadKindNotSupportedException(ODataPayloadKind.Collection);
 }
Esempio n. 15
0
 /// <summary>
 /// Constructs an instance of the stream wrapper class.
 /// </summary>
 /// <param name="innerStream">Stream that is being wrapped.</param>
 internal NonDisposingStream(Stream innerStream)
 {
     DebugUtils.CheckNoExternalCallers();
     Debug.Assert(innerStream != null, "innerStream != null");
     this.innerStream = innerStream;
 }
Esempio n. 16
0
 /// <summary>
 /// Asynchronously writes a single value as the message body.
 /// </summary>
 /// <param name="value">The value to write.</param>
 /// <returns>A running task representing the writing of the value.</returns>
 /// <remarks>It is the responsibility of this method to flush the output before the task finishes.</remarks>
 internal virtual Task WriteValueAsync(object value)
 {
     DebugUtils.CheckNoExternalCallers();
     throw this.CreatePayloadKindNotSupportedException(ODataPayloadKind.Value);
 }
Esempio n. 17
0
 /// <summary>
 /// Gets the metadata builder for this stream reference value.
 /// </summary>
 /// <returns>The metadata builder used to compute links.</returns>
 internal ODataEntityMetadataBuilder GetMetadataBuilder()
 {
     DebugUtils.CheckNoExternalCallers();
     return(this.metadataBuilder);
 }
Esempio n. 18
0
 /// <summary>
 /// Writes the metadata document as the message body.
 /// </summary>
 /// <remarks>It is the responsibility of this method to flush the output before the method returns.</remarks>
 internal virtual void WriteMetadataDocument()
 {
     DebugUtils.CheckNoExternalCallers();
     throw this.CreatePayloadKindNotSupportedException(ODataPayloadKind.MetadataDocument);
 }
Esempio n. 19
0
        /// <summary>
        /// Scans the current buffer for the specified boundary.
        /// </summary>
        /// <param name="boundaries">The boundary strings to search for; this enumerable is sorted from the inner-most boundary
        /// to the top-most boundary. The boundary strings don't include the leading line terminator or the leading dashes.</param>
        /// <param name="maxDataBytesToScan">Stop if no boundary (or boundary start) is found after this number of bytes.</param>
        /// <param name="boundaryStartPosition">The start position of the boundary or -1 if not found.
        /// Note that the start position is the first byte of the leading line terminator.</param>
        /// <param name="boundaryEndPosition">The end position of the boundary or -1 if not found.
        /// Note that the end position is the last byte of the trailing line terminator.</param>
        /// <param name="isEndBoundary">true if the boundary is an end boundary (followed by two dashes); otherwise false.</param>
        /// <param name="isParentBoundary">true if the detected boundary is the parent boundary; otherwise false.</param>
        /// <returns>An enumeration value indicating whether the boundary was completely, partially or not found in the buffer.</returns>
        internal ODataBatchReaderStreamScanResult ScanForBoundary(
            IEnumerable <string> boundaries,
            int maxDataBytesToScan,
            out int boundaryStartPosition,
            out int boundaryEndPosition,
            out bool isEndBoundary,
            out bool isParentBoundary)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(boundaries != null, "boundaries != null");

            boundaryStartPosition = -1;
            boundaryEndPosition   = -1;
            isEndBoundary         = false;
            isParentBoundary      = false;

            int lineScanStartIndex = this.currentReadPosition;

            while (true)
            {
                // NOTE: a boundary has to start with a line terminator followed by two dashes ('-'),
                //       the actual boundary string, another two dashes (for an end boundary),
                //       optional whitespace characters and another line terminator.
                // NOTE: for WCF DS compatibility we do not require the leading line terminator.
                int lineEndStartPosition, boundaryDelimiterStartPosition;
                ODataBatchReaderStreamScanResult lineEndScanResult = this.ScanForBoundaryStart(
                    lineScanStartIndex,
                    maxDataBytesToScan,
                    out lineEndStartPosition,
                    out boundaryDelimiterStartPosition);

                switch (lineEndScanResult)
                {
                case ODataBatchReaderStreamScanResult.NoMatch:
                    // Did not find a line end or boundary delimiter in the buffer or after reading maxDataBytesToScan bytes.
                    // Report no boundary match.
                    return(ODataBatchReaderStreamScanResult.NoMatch);

                case ODataBatchReaderStreamScanResult.PartialMatch:
                    // Found a partial line end or boundary delimiter at the end of the buffer but before reading maxDataBytesToScan.
                    // Report a partial boundary match.
                    boundaryStartPosition = lineEndStartPosition < 0 ? boundaryDelimiterStartPosition : lineEndStartPosition;
                    return(ODataBatchReaderStreamScanResult.PartialMatch);

                case ODataBatchReaderStreamScanResult.Match:
                    // Found a full line end or boundary delimiter start ('--') before reading maxDataBytesToScan or
                    // hitting the end of the buffer. Start matching the boundary delimiters.
                    //
                    // Start with the expected boundary (the first one in the enumerable):
                    // * if we find a full match - return match because we are done
                    // * if we find a partial match - return partial match because we have to continue checking the expected boundary.
                    // * if we find no match - we know that it is not the expected boundary; check the parent boundary (if it exists).
                    isParentBoundary = false;
                    foreach (string boundary in boundaries)
                    {
                        ODataBatchReaderStreamScanResult boundaryMatch = this.MatchBoundary(
                            lineEndStartPosition,
                            boundaryDelimiterStartPosition,
                            boundary,
                            out boundaryStartPosition,
                            out boundaryEndPosition,
                            out isEndBoundary);
                        switch (boundaryMatch)
                        {
                        case ODataBatchReaderStreamScanResult.Match:
                            return(ODataBatchReaderStreamScanResult.Match);

                        case ODataBatchReaderStreamScanResult.PartialMatch:
                            boundaryEndPosition = -1;
                            isEndBoundary       = false;
                            return(ODataBatchReaderStreamScanResult.PartialMatch);

                        case ODataBatchReaderStreamScanResult.NoMatch:
                            // try the parent boundary (if any) or continue scanning
                            boundaryStartPosition = -1;
                            boundaryEndPosition   = -1;
                            isEndBoundary         = false;
                            isParentBoundary      = true;
                            break;

                        default:
                            throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReaderStreamBuffer_ScanForBoundary));
                        }
                    }

                    // If we could not match the boundary, try again starting at the current boundary start index. Or if we already did that
                    // move one character ahead.
                    lineScanStartIndex = lineScanStartIndex == boundaryDelimiterStartPosition
                            ? boundaryDelimiterStartPosition + 1
                            : boundaryDelimiterStartPosition;

                    break;

                default:
                    throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReaderStreamBuffer_ScanForBoundary));
                }
            }
        }
Esempio n. 20
0
 /// <summary>Specifies whether the WCF data services server behavior is enabled.</summary>
 /// <param name="usesV1Provider">true if the server uses V1 provider, otherwise, false.</param>
 /// <param name="alwaysUseDefaultXmlNamespaceForRootElement">true if the server is configured to leave prefixes off all root elements and anything else in the same namespace, otherwise, false.</param>
 public void EnableWcfDataServicesServerBehavior(bool usesV1Provider, bool alwaysUseDefaultXmlNamespaceForRootElement)
 {
     DebugUtils.CheckNoExternalCallers();
     this.EnableWcfDataServicesServerBehavior(usesV1Provider);
     this.alwaysUseDefaultXmlNamespaceForRootElement = alwaysUseDefaultXmlNamespaceForRootElement;
 }
        /// <summary>
        /// Reads a line (all bytes until a line feed) from the underlying stream.
        /// </summary>
        /// <returns>Returns the string that was read from the underyling stream (not including a terminating line feed).</returns>
        internal string ReadLine()
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(this.batchEncoding != null, "Batch encoding should have been established on first call to SkipToBoundary.");
            Debug.Assert(this.lineBuffer != null && this.lineBuffer.Length == LineBufferLength, "Line buffer should have been created.");

            // The number of bytes in the line buffer that make up the line.
            int lineBufferSize = 0;

            // Start with the pre-allocated line buffer array.
            byte[] bytesForString = this.lineBuffer;

            ODataBatchReaderStreamScanResult scanResult = ODataBatchReaderStreamScanResult.NoMatch;

            while (scanResult != ODataBatchReaderStreamScanResult.Match)
            {
                int byteCount, lineEndStartPosition, lineEndEndPosition;
                scanResult = this.batchBuffer.ScanForLineEnd(out lineEndStartPosition, out lineEndEndPosition);
                switch (scanResult)
                {
                case ODataBatchReaderStreamScanResult.NoMatch:
                    // Copy all the bytes in the batchBuffer into the result byte[] and then continue
                    byteCount = this.batchBuffer.NumberOfBytesInBuffer;
                    if (byteCount > 0)
                    {
                        ODataBatchUtils.EnsureArraySize(ref bytesForString, lineBufferSize, byteCount);
                        Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, bytesForString, lineBufferSize, byteCount);
                        lineBufferSize += byteCount;
                    }

                    if (this.underlyingStreamExhausted)
                    {
                        // Nothing more to read; stop looping
                        scanResult = ODataBatchReaderStreamScanResult.Match;
                        this.batchBuffer.SkipTo(this.batchBuffer.CurrentReadPosition + byteCount);
                    }
                    else
                    {
                        this.underlyingStreamExhausted = this.batchBuffer.RefillFrom(this.inputContext.Stream, /*preserveFrom*/ ODataBatchReaderStreamBuffer.BufferLength);
                    }

                    break;

                case ODataBatchReaderStreamScanResult.PartialMatch:
                    // We found the start of a line end in the buffer but could not verify whether we saw all of it.
                    // This can happen if a line end is represented as \r\n and we found \r at the very last position in the buffer.
                    // In this case we copy the bytes into the result byte[] and continue at the start of the line end; this will guarantee
                    // that the next scan will find the full line end, not find any additional bytes and then skip the full line end.
                    // It is safe to copy the string right here because we will also accept \r as a line end; we are just not sure whether there
                    // will be a subsequent \n.
                    // This can also happen if the last byte in the stream is \r.
                    byteCount = lineEndStartPosition - this.batchBuffer.CurrentReadPosition;
                    if (byteCount > 0)
                    {
                        ODataBatchUtils.EnsureArraySize(ref bytesForString, lineBufferSize, byteCount);
                        Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, bytesForString, lineBufferSize, byteCount);
                        lineBufferSize += byteCount;
                    }

                    if (this.underlyingStreamExhausted)
                    {
                        // Nothing more to read; stop looping
                        scanResult = ODataBatchReaderStreamScanResult.Match;
                        this.batchBuffer.SkipTo(lineEndStartPosition + 1);
                    }
                    else
                    {
                        this.underlyingStreamExhausted = this.batchBuffer.RefillFrom(this.inputContext.Stream, /*preserveFrom*/ lineEndStartPosition);
                    }

                    break;

                case ODataBatchReaderStreamScanResult.Match:
                    // We found a line end in the buffer
                    Debug.Assert(lineEndStartPosition >= this.batchBuffer.CurrentReadPosition, "Line end must be at or after current position.");
                    Debug.Assert(lineEndEndPosition < this.batchBuffer.CurrentReadPosition + this.batchBuffer.NumberOfBytesInBuffer, "Line end must finish withing buffer range.");

                    byteCount = lineEndStartPosition - this.batchBuffer.CurrentReadPosition;
                    if (byteCount > 0)
                    {
                        ODataBatchUtils.EnsureArraySize(ref bytesForString, lineBufferSize, byteCount);
                        Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, bytesForString, lineBufferSize, byteCount);
                        lineBufferSize += byteCount;
                    }

                    this.batchBuffer.SkipTo(lineEndEndPosition + 1);
                    break;

                default:
                    throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReaderStream_ReadLine));
                }
            }

            if (bytesForString == null)
            {
                return(string.Empty);
            }

            return(this.CurrentEncoding.GetString(bytesForString, 0, lineBufferSize));
        }
Esempio n. 22
0
 /// <summary>
 /// Determines if there is a JSON padding function defined.
 /// </summary>
 /// <returns>True if the JsonPCallback property is not null or emtpy.</returns>
 internal bool HasJsonPaddingFunction()
 {
     DebugUtils.CheckNoExternalCallers();
     return(!string.IsNullOrEmpty(this.JsonPCallback));
 }
Esempio n. 23
0
 /// <summary>
 /// Given the value of the Properties collection previously populated by CreateNewEntry
 /// this methods returns the internal List of properties which can be modified to add new properties.
 /// </summary>
 /// <param name="properties">The value of the Properties property to get the list for.</param>
 /// <returns>The underlying list of properties to modify.</returns>
 internal static List <ODataProperty> GetPropertiesList(IEnumerable <ODataProperty> properties)
 {
     DebugUtils.CheckNoExternalCallers();
     return(GetSourceListOfEnumerable(properties, "Properties"));
 }
Esempio n. 24
0
 /// <summary>
 /// Returns true to indicate that the annotation with the name <paramref name="annotationName"/> should not be writen, false otherwise.
 /// </summary>
 /// <param name="annotationName">The name of the annotation in question.</param>
 /// <returns>Returns true to indicate that the annotation with the name <paramref name="annotationName"/> should not be writen, false otherwise.</returns>
 internal bool ShouldSkipAnnotation(string annotationName)
 {
     DebugUtils.CheckNoExternalCallers();
     Debug.Assert(this.Version.HasValue, "The version should be set by now.");
     return(this.Version.Value < ODataVersion.V3 || this.ShouldIncludeAnnotation != null && !this.ShouldIncludeAnnotation(annotationName));
 }
Esempio n. 25
0
 /// <summary>
 /// Determines whether the given HTTP method is one that is accepted for queries. GET is accepted for queries.
 /// </summary>
 /// <param name="httpMethod">The HTTP method to check.</param>
 /// <returns>True if the given httpMethod is GET.</returns>
 internal static bool IsQueryMethod(string httpMethod)
 {
     DebugUtils.CheckNoExternalCallers();
     return(string.CompareOrdinal(httpMethod, ODataConstants.MethodGet) == 0);
 }
        /// <summary>
        /// Validates a collection item that was read to make sure it is valid (i.e., has the correct
        /// type name and type kind) with respect to the other items in the collection.
        /// </summary>
        /// <param name="collectionItemTypeName">The type name of the item from the payload.</param>
        /// <param name="collectionItemTypeKind">The type kind of the item from the payload.</param>
        internal void ValidateCollectionItem(string collectionItemTypeName, EdmTypeKind collectionItemTypeKind)
        {
            DebugUtils.CheckNoExternalCallers();

            // Only primitive and complex values are allowed in collections
            if (collectionItemTypeKind != EdmTypeKind.Primitive && collectionItemTypeKind != EdmTypeKind.Complex)
            {
                throw new ODataException(Strings.CollectionWithoutExpectedTypeValidator_InvalidItemTypeKind(collectionItemTypeKind));
            }

            if (this.itemTypeDerivedFromCollectionValue)
            {
                Debug.Assert(this.itemTypeName != null, "this.itemType != null");

                // If the collection has a type name assign missing item type names from it.
                collectionItemTypeName = collectionItemTypeName ?? this.itemTypeName;

                // If we have a type name from the collection, make sure the type names of all items match
                this.ValidateCollectionItemTypeNameAndKind(collectionItemTypeName, collectionItemTypeKind);
            }
            else
            {
                // If we don't have a type name from the collection, store the type name and type kind of the first non-null item.
                if (this.itemTypeKind == EdmTypeKind.None)
                {
                    // Compute the kind from the specified type name if available.
                    this.itemTypeKind = collectionItemTypeName == null
                        ? collectionItemTypeKind
                        : ComputeExpectedTypeKind(collectionItemTypeName, out this.primitiveItemType);

                    // If no payload type name is specified either default to Edm.String (for primitive type kinds) or leave the type name
                    // null (for complex items without type name)
                    if (collectionItemTypeName == null)
                    {
                        this.itemTypeKind = collectionItemTypeKind;
                        if (this.itemTypeKind == EdmTypeKind.Primitive)
                        {
                            this.itemTypeName      = Metadata.EdmConstants.EdmStringTypeName;
                            this.primitiveItemType = EdmCoreModel.Instance.GetString(/*isNullable*/ false).PrimitiveDefinition();
                        }
                        else
                        {
                            this.itemTypeName      = null;
                            this.primitiveItemType = null;
                        }
                    }
                    else
                    {
                        this.itemTypeKind = ComputeExpectedTypeKind(collectionItemTypeName, out this.primitiveItemType);
                        this.itemTypeName = collectionItemTypeName;
                    }
                }

                if (collectionItemTypeName == null && collectionItemTypeKind == EdmTypeKind.Primitive)
                {
                    // Default to Edm.String if no payload type is specified and the type kind is 'Primitive'
                    collectionItemTypeName = Metadata.EdmConstants.EdmStringTypeName;
                }

                // Validate the expected and actual type names and type kinds.
                // Note that we compute the expected type kind from the expected type name and thus the payload
                // type kind (passed to this method) might be different from the computed expected type kind.
                this.ValidateCollectionItemTypeNameAndKind(collectionItemTypeName, collectionItemTypeKind);
            }
        }
Esempio n. 27
0
        /// <summary>
        /// Reads a token or quoted-string value from the header.
        /// </summary>
        /// <param name="headerName">Name of the header.</param>
        /// <param name="headerText">Header text.</param>
        /// <param name="textIndex">Parsing index in <paramref name="headerText"/>.</param>
        /// <param name="isQuotedString">Returns true if the value is a quoted-string, false if the value is a token.</param>
        /// <param name="createException">Func to create the appropriate exception to throw from the given error message.</param>
        /// <returns>The token or quoted-string value that was read from the header.</returns>
        internal static string ReadTokenOrQuotedStringValue(string headerName, string headerText, ref int textIndex, out bool isQuotedString, Func <string, Exception> createException)
        {
            DebugUtils.CheckNoExternalCallers();

            //// NOTE: See RFC 2616, Sections 3.6 and 2.2 for the full grammar for HTTP parameter values
            ////
            //// parameter-value    =   token | quoted-string
            //// token              = 1*<any CHAR except CTLs or separators>
            //// CHAR               = <any US-ASCII character (octets 0 - 127)>
            //// CTL                = <any US-ASCII control character
            ////                      (octets 0 - 31) and DEL (127)>
            //// separators         = "(" | ")" | "<" | ">" | "@"
            ////                    | "," | ";" | ":" | "\" | <">
            ////                    | "/" | "[" | "]" | "?" | "="
            ////                    | "{" | "}" | SP | HT
            //// quoted-string      = ( <"> *(qdtext | quoted-pair ) <"> )
            //// qdtext             = <any TEXT except <">>
            //// TEXT               = <any OCTET except CTLs, but including LWS>
            //// quoted-pair        = "\" CHAR

            StringBuilder parameterValue = new StringBuilder();

            // Check if the value is quoted.
            isQuotedString = false;
            if (textIndex < headerText.Length)
            {
                if (headerText[textIndex] == '\"')
                {
                    textIndex++;
                    isQuotedString = true;
                }
            }

            char currentChar = default(char);

            while (textIndex < headerText.Length)
            {
                currentChar = headerText[textIndex];

                if (currentChar == '\\' || currentChar == '\"')
                {
                    if (!isQuotedString)
                    {
                        throw createException(Strings.HttpUtils_EscapeCharWithoutQuotes(headerName, headerText, textIndex, currentChar));
                    }

                    textIndex++;

                    // End of quoted parameter value.
                    if (currentChar == '\"')
                    {
                        break;
                    }

                    if (textIndex >= headerText.Length)
                    {
                        throw createException(Strings.HttpUtils_EscapeCharAtEnd(headerName, headerText, textIndex, currentChar));
                    }

                    currentChar = headerText[textIndex];
                }
                else
                {
                    if (!isQuotedString && !IsHttpToken(currentChar))
                    {
                        // If the given character is special, we stop processing.
                        break;
                    }

                    if (isQuotedString && !IsValidInQuotedHeaderValue(currentChar))
                    {
                        throw createException(Strings.HttpUtils_InvalidCharacterInQuotedParameterValue(headerName, headerText, textIndex, currentChar));
                    }
                }

                parameterValue.Append(currentChar);
                textIndex++;
            }

            if (isQuotedString && currentChar != '\"')
            {
                throw createException(Strings.HttpUtils_ClosingQuoteNotFound(headerName, headerText, textIndex));
            }

            return(parameterValue.ToString());
        }
 /// <summary>
 /// Constructor.
 /// </summary>
 internal FeedWithoutExpectedTypeValidator()
 {
     DebugUtils.CheckNoExternalCallers();
 }
Esempio n. 29
0
 /// <summary>
 /// Constructor which initializes the enumerable with an empty list storage.
 /// </summary>
 internal ReadOnlyEnumerable()
     : this(new List <T>())
 {
     DebugUtils.CheckNoExternalCallers();
 }
Esempio n. 30
0
        /// <summary>
        /// Creates an instance of the output context for the specified format.
        /// </summary>
        /// <param name="format">The format to create the context for.</param>
        /// <param name="message">The message to use.</param>
        /// <param name="encoding">The encoding to use.</param>
        /// <param name="messageWriterSettings">Configuration settings of the OData writer.</param>
        /// <param name="writingResponse">true if writing a response message; otherwise false.</param>
        /// <param name="model">The model to use.</param>
        /// <param name="urlResolver">The optional URL resolver to perform custom URL resolution for URLs written to the payload.</param>
        /// <returns>The newly created output context.</returns>
        internal static ODataOutputContext CreateOutputContext(
            ODataFormat format,
            ODataMessage message,
            Encoding encoding,
            ODataMessageWriterSettings messageWriterSettings,
            bool writingResponse,
            IEdmModel model,
            IODataUrlResolver urlResolver)
        {
            DebugUtils.CheckNoExternalCallers();

            if (format == ODataFormat.Atom)
            {
                return(ODataAtomOutputContext.Create(
                           format,
                           message,
                           encoding,
                           messageWriterSettings,
                           writingResponse,
                           model,
                           urlResolver));
            }

            if (format == ODataFormat.VerboseJson)
            {
                return(ODataJsonOutputContext.Create(
                           format,
                           message,
                           encoding,
                           messageWriterSettings,
                           writingResponse,
                           model,
                           urlResolver));
            }

            if (format == ODataFormat.Metadata)
            {
                return(ODataMetadataOutputContext.Create(
                           format,
                           message,
                           encoding,
                           messageWriterSettings,
                           writingResponse,
                           model,
                           urlResolver));
            }

            if (format == ODataFormat.Batch || format == ODataFormat.RawValue)
            {
                return(ODataRawOutputContext.Create(
                           format,
                           message,
                           encoding,
                           messageWriterSettings,
                           writingResponse,
                           model,
                           urlResolver));
            }

            throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataOutputContext_CreateOutputContext_UnrecognizedFormat));
        }