public virtual async Task <StorageResponseHolder> Read(string key
                                                               , string directory         = null
                                                               , CancellationToken?cancel = null
                                                               , bool useEncryption       = true)
        {
            var request = new StorageRequestHolder(key, cancel, directory);

            return(await CallCloudBlockBlob(request,
                                            async (rq, rs, exists) =>
            {
                if (exists)
                {
                    var sData = new MemoryStream();

                    await rq.Blob.DownloadToStreamAsync(sData, rq.CancelSet);

                    rs.Data = new byte[sData.Length];
                    sData.Position = 0;
                    sData.Read(rs.Data, 0, rs.Data.Length);

                    // If encryption provided decrypt the blob
                    if (useEncryption && mEncryption != null)
                    {
                        rs.Data = mEncryption.Decrypt(rs.Data);
                    }

                    MetadataGet(rq.Blob, rs);
                }
                else
                {
                    rq.CopyTo(rs);
                }

                rs.IsSuccess = exists;
                rs.StatusCode = exists ? 200 : 404;
            }));
        }
Beispiel #2
0
        public bool MoveNext()
        {
            if (isDisposed)
            {
                throw new ObjectDisposedException(nameof(PdfTokenScanner));
            }

            // Read until we find object-number generation obj, e.g. "69 420 obj".
            int tokensRead = 0;

            while (coreTokenScanner.MoveNext() && !Equals(coreTokenScanner.CurrentToken, OperatorToken.StartObject))
            {
                if (coreTokenScanner.CurrentToken is CommentToken)
                {
                    continue;
                }

                tokensRead++;

                previousTokens[0]         = previousTokens[1];
                previousTokenPositions[0] = previousTokenPositions[1];

                previousTokens[1]         = previousTokens[2];
                previousTokenPositions[1] = previousTokenPositions[2];

                previousTokens[2]         = coreTokenScanner.CurrentToken;
                previousTokenPositions[2] = coreTokenScanner.CurrentTokenStart;
            }

            // We only read partial tokens.
            if (tokensRead < 2)
            {
                return(false);
            }

            var startPosition = previousTokenPositions[1];
            var objectNumber  = previousTokens[1] as NumericToken;
            var generation    = previousTokens[2] as NumericToken;

            if (objectNumber == null || generation == null)
            {
                // Handle case where the scanner correctly reads most of an object token but includes too much of the first token
                // specifically %%EOF1 0 obj where scanning starts from 'F'.
                if (generation != null && previousTokens[1] is OperatorToken op)
                {
                    var match = EndsWithNumberRegex.Match(op.Data);

                    if (match.Success && int.TryParse(match.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out var number))
                    {
                        startPosition = previousTokenPositions[1] + match.Index;
                        objectNumber  = new NumericToken(number);
                    }
                    else
                    {
                        return(false);
                    }
                }
                else
                {
                    return(false);
                }
            }

            var readStream = false;

            // Read all tokens between obj and endobj.
            while (coreTokenScanner.MoveNext() && !Equals(coreTokenScanner.CurrentToken, OperatorToken.EndObject))
            {
                if (coreTokenScanner.CurrentToken is CommentToken)
                {
                    continue;
                }

                if (ReferenceEquals(coreTokenScanner.CurrentToken, OperatorToken.StartObject))
                {
                    if (readStream && readTokens[0] is StreamToken streamRead)
                    {
                        readTokens.Clear();
                        readTokens.Add(streamRead);
                        coreTokenScanner.Seek(previousTokenPositions[0]);
                        break;
                    }

                    if (readTokens.Count == 3 && readTokens[1] is NumericToken extraObjNum && readTokens[2] is NumericToken extraGenNum)
                    {
                        // An obj was encountered after reading the actual token and the object and generation number of the following token.
                        var actualReference = new IndirectReference(objectNumber.Int, generation.Int);
                        var actualToken     = encryptionHandler.Decrypt(actualReference, readTokens[0]);

                        CurrentToken = new ObjectToken(startPosition, actualReference, actualToken);

                        readTokens.Clear();
                        coreTokenScanner.Seek(previousTokenPositions[0]);

                        return(true);
                    }

                    // This should never happen.
                    Debug.Assert(false, "Encountered a start object 'obj' operator before the end of the previous object.");
                    return(false);
                }

                if (ReferenceEquals(coreTokenScanner.CurrentToken, OperatorToken.StartStream))
                {
                    var streamIdentifier = new IndirectReference(objectNumber.Long, generation.Int);

                    // Prevent an infinite loop where a stream's length references the stream or the stream's offset.
                    var getLengthFromFile = !isBruteForcing && !(callingObject.HasValue && callingObject.Value.Equals(streamIdentifier));

                    var outerCallingObject = callingObject;

                    try
                    {
                        callingObject = streamIdentifier;

                        // Read stream: special case.
                        if (TryReadStream(coreTokenScanner.CurrentTokenStart, getLengthFromFile, out var stream))
                        {
                            readTokens.Clear();
                            readTokens.Add(stream);
                            readStream = true;
                        }
                    }
                    finally
                    {
                        callingObject = outerCallingObject;
                    }
                }
                else
                {
                    readTokens.Add(coreTokenScanner.CurrentToken);
                }

                previousTokens[0]         = previousTokens[1];
                previousTokenPositions[0] = previousTokenPositions[1];

                previousTokens[1]         = previousTokens[2];
                previousTokenPositions[1] = previousTokenPositions[2];

                previousTokens[2]         = coreTokenScanner.CurrentToken;
                previousTokenPositions[2] = coreTokenScanner.CurrentTokenStart;
            }

            if (!readStream && !ReferenceEquals(coreTokenScanner.CurrentToken, OperatorToken.EndObject))
            {
                readTokens.Clear();
                return(false);
            }

            var reference = new IndirectReference(objectNumber.Long, generation.Int);

            IToken token;

            if (readTokens.Count == 3 && readTokens[0] is NumericToken objNum &&
                readTokens[1] is NumericToken genNum &&
                ReferenceEquals(readTokens[2], OperatorToken.R))
            {
                // I have no idea if this can ever happen.
                token = new IndirectReferenceToken(new IndirectReference(objNum.Long, genNum.Int));
            }