public static async Task Test_CopyStream()
        {
            //Prepare
            MemoryStream msSource = new MemoryStream();
            StreamWriter swSource = new StreamWriter(msSource);

            swSource.Write(dummyPath);
            swSource.Flush();
            msSource.Seek(0, SeekOrigin.Begin);
            MemoryStream msDest = new MemoryStream();
            StreamReader reader = new StreamReader(msDest);

            CopyStream   copyStream = new CopyStream();
            ParameterDic pd         = new ParameterDic()
            {
                { copyStream.SourceKey, msSource },
                { copyStream.DestinationKey, msDest }
            };

            //Action
            IScriptCommand retCmd = await copyStream.ExecuteAsync(pd);

            msDest.Seek(0, SeekOrigin.Begin);
            string read = reader.ReadToEnd();

            //Assert
            Assert.AreEqual(dummyPath, read);
        }
        /// <summary>
        ///  This is called when the request is PUT/POST/PATCH to read the body
        /// </summary>
        /// <returns></returns>
        internal async Task CopyRequestBodyAsync(HttpWriter writer, TransformationMode transformation, CancellationToken cancellationToken)
        {
            var request = WebSession.Request;

            long contentLength = request.ContentLength;

            // send the request body bytes to server
            if (contentLength > 0 && hasMulipartEventSubscribers && request.IsMultipartFormData)
            {
                var    reader   = getStreamReader(true);
                string boundary = HttpHelper.GetBoundaryFromContentType(request.ContentType);

                using (var copyStream = new CopyStream(reader, writer, bufferPool, bufferSize))
                {
                    while (contentLength > copyStream.ReadBytes)
                    {
                        long read = await readUntilBoundaryAsync(copyStream, contentLength, boundary, cancellationToken);

                        if (read == 0)
                        {
                            break;
                        }

                        if (contentLength > copyStream.ReadBytes)
                        {
                            var headers = new HeaderCollection();
                            await HeaderParser.ReadHeaders(copyStream, headers, cancellationToken);

                            OnMultipartRequestPartSent(boundary, headers);
                        }
                    }

                    await copyStream.FlushAsync(cancellationToken);
                }
            }
            else
            {
                await copyBodyAsync(true, false, writer, transformation, OnDataSent, cancellationToken);
            }
        }
            protected FileInfo CopyFolder(string parentId, FileInfo fileInfo)
            {
                try
                {
                  FileInfo folder = CreateFolder(parentId, fileInfo);

                  FilesProcessed++;

                  foreach (FileInfo childInfo in fileInfo.Files)
                  {
                if (IsCancellationRequested)
                {
                  throw new Exception("Process cancelled by user.");
                }

                if (childInfo.IsFolder)
                {
                  CopyFolder(folder.Id, childInfo);
                }
                else
                {
                  var copyStream = new CopyStream();

                  copyStream.Init(folder.Id, childInfo);

                  copyStream.Visible = false;

                  _DriveService.CopyFile(copyStream);

                  while (!copyStream.Processed)
                  {
                if (IsCancellationRequested)
                {
                  copyStream.Cancel();
                }

                System.Threading.Thread.Sleep(250);
                  }

                  if (IsCancellationRequested)
                  {
                throw new Exception("Process cancelled by user.");
                  }

                  if (!copyStream.Completed)
                  {
                throw new Exception("Could not create new folder");
                  }

                  FilesProcessed++;
                }
                  }

                  return folder;
                }
                catch (Exception exception)
                {
                  Log.Error(exception);

                  return null;
                }
            }
Beispiel #4
0
            protected FileInfo CopyFolder(string parentId, FileInfo fileInfo)
            {
                try
                {
                    FileInfo folder = CreateFolder(parentId, fileInfo);

                    FilesProcessed++;

                    foreach (FileInfo childInfo in fileInfo.Files)
                    {
                        if (IsCancellationRequested)
                        {
                            throw new Exception("Process cancelled by user.");
                        }

                        if (childInfo.IsFolder)
                        {
                            CopyFolder(folder.Id, childInfo);
                        }
                        else
                        {
                            var copyStream = new CopyStream();

                            copyStream.Init(folder.Id, childInfo);

                            copyStream.Visible = false;

                            _DriveService.CopyFile(copyStream);

                            while (!copyStream.Processed)
                            {
                                if (IsCancellationRequested)
                                {
                                    copyStream.Cancel();
                                }

                                System.Threading.Thread.Sleep(250);
                            }

                            if (IsCancellationRequested)
                            {
                                throw new Exception("Process cancelled by user.");
                            }

                            if (!copyStream.Completed)
                            {
                                throw new Exception("Could not create new folder");
                            }

                            FilesProcessed++;
                        }
                    }

                    return(folder);
                }
                catch (Exception exception)
                {
                    Log.Error(exception);

                    return(null);
                }
            }
        public static async ValueTask ProcessClient(HttpClientHolder holder, HttpInitialRequest request)
        {
            var handler = HttpHandleStore.Check(request.Path);

            if (handler == null)
            {
                request.Path = Path.Combine(Directory.GetCurrentDirectory(), HttpConstant.RootDirectory, request.Path);
                if (!File.Exists(request.Path))
                {
                    await holder.SafeWriteAsync(HttpErrorResponses.Instance.NotFoundResponse);

                    return;
                }
            }
            else
            {
                handler.Invoked?.Invoke(holder);
                return;
            }

            var mime = MimeProcessor.Interpret(request.Path);

            if (mime == null)
            {
                await holder.SafeWriteAsync(HttpErrorResponses.Instance.NotImplementedResponse);

                return;
            }

            var fileInfo = new FileInfo(request.Path);

            holder.Client.SendBufferSize = HttpConstant.FileBufferSize;
            var    asyncFs = fileInfo.Length > 1024 * 1024;
            Stream fs;

            if (Cfg.EnableHttpCache && !Cfg.HttpCacheExclude.Contains(request.Path))
            {
                var(stat, array, length) = HttpServerFileCache.TryGet(request.Path);
                if (stat)
                {
                    Trace.Assert(array != null, "Http cache null L58/Client.Processor!");
                    fs      = new MemoryStream(array, 0, length.Value);
                    asyncFs = false;
                }
                else
                {
                    var(success, bytes, stream) = await HttpServerFileCache.TryCache(request.Path, asyncFs);

                    if (success)
                    {
                        fs      = new MemoryStream(bytes, 0, (int)fileInfo.Length);
                        asyncFs = false;
                    }
                    else
                    {
                        fs = stream;
                    }
                }
            }
            else
            {
                fs = new FileStream(request.Path, FileMode.Open, FileAccess.Read, FileShare.Read, 4096,
                                    useAsync: asyncFs);
            }

            await using (fs)
            {
                if (request.Ranges == null || request.Ranges.Count == 0)
                {
                    using var header = new HttpResponseHeaders(fileInfo.Length, ResponseStatusCode.Ok200,
                                                               new IResponseField[]
                    {
                        new FieldServer(HttpConstant.ServerName),
                        new FieldContentType(mime),
                        new FieldAcceptRanges(HttpConstant.AcceptRanges),
                    }, request.HttpVersion);

                    var headerData = header.Compile();

                    if (!await holder.SafeWriteAsync(headerData.Item1, headerData.Item2))
                    {
                        return;
                    }
                    if (request.Method == HttpInitialRequestMethod.HEAD)
                    {
                        return;
                    }

                    await CopyStream(fileInfo, fs, holder, fileInfo.Length, asyncFs);

                    return;
                }

                foreach (var range in request.Ranges)
                {
                    switch (range.Method)
                    {
                    case HttpRangeRequestMethod.SliceFromToEnd:
                    {
                        // implemented, tested
                        if (fs.Length < range.Range.From)
                        {
                            return;
                        }

                        using var header = new HttpResponseHeaders(fileInfo.Length,
                                                                   ResponseStatusCode.PartialContent206, new IResponseField[]
                            {
                                new FieldContentRange(true, range.Range.From, fileInfo.Length - 1, fileInfo.Length),
                                new FieldServer(HttpConstant.ServerName),
                                new FieldContentType(mime),
                                new FieldAcceptRanges(HttpConstant.AcceptRanges),
                            }, request.HttpVersion);

                        var headerData = header.Compile();
                        if (!await holder.SafeWriteAsync(headerData.Item1, headerData.Item2))
                        {
                            return;
                        }
                        if (request.Method == HttpInitialRequestMethod.HEAD)
                        {
                            return;
                        }
                        fs.Seek((long)range.Range.From !, SeekOrigin.Begin);
                        await CopyStream(fileInfo, fs, holder, (int)(fs.Length - range.Range.From), asyncFs);

                        return;
                    }

                    case HttpRangeRequestMethod.SendAll:
                    {
                        // implemented, tested
                        using var header = new HttpResponseHeaders(fileInfo.Length,
                                                                   ResponseStatusCode.PartialContent206, new IResponseField[]
                            {
                                new FieldContentRange(true, 0, fileInfo.Length - 1, fileInfo.Length),
                                new FieldServer(HttpConstant.ServerName),
                                new FieldContentType(mime),
                                new FieldAcceptRanges(HttpConstant.AcceptRanges),
                            }, request.HttpVersion);

                        var headerData = header.Compile();
                        if (!await holder.SafeWriteAsync(headerData.Item1, headerData.Item2))
                        {
                            return;
                        }
                        if (request.Method == HttpInitialRequestMethod.HEAD)
                        {
                            return;
                        }
                        await CopyStream(fileInfo, fs, holder, (int)fs.Length, asyncFs);

                        return;
                    }

                    case HttpRangeRequestMethod.SliceFromTo:
                    {
                        if (fs.Length < range.Range.From || fs.Length < range.Range.To)
                        {
                            // attacker.
                            return;
                        }

                        using var header = new HttpResponseHeaders(fileInfo.Length,
                                                                   ResponseStatusCode.PartialContent206, new IResponseField[]
                            {
                                new FieldContentRange(true, range.Range.From, range.Range.To, fileInfo.Length),
                                new FieldServer(HttpConstant.ServerName),
                                new FieldContentType(mime),
                                new FieldAcceptRanges(HttpConstant.AcceptRanges),
                            }, request.HttpVersion);

                        var headerData = header.Compile();

                        if (!await holder.SafeWriteAsync(headerData.Item1, headerData.Item2))
                        {
                            return;
                        }
                        if (request.Method == HttpInitialRequestMethod.HEAD)
                        {
                            return;
                        }
                        fs.Seek((int)range.Range.From, SeekOrigin.Begin);
                        await CopyStream(fileInfo, fs, holder, (long)(range.Range.To - range.Range.From) !,
                                         asyncFs);

                        return;
                    }

                    case HttpRangeRequestMethod.SliceFromStartTo:
                    {
                        if (fs.Length < range.Range.To)
                        {
                            // attacker.
                            return;
                        }

                        using var header = new HttpResponseHeaders(fileInfo.Length,
                                                                   ResponseStatusCode.PartialContent206, new IResponseField[]
                            {
                                new FieldContentRange(true, 0, range.Range.To, fileInfo.Length),
                                new FieldServer(HttpConstant.ServerName),
                                new FieldContentType(mime),
                                new FieldAcceptRanges(HttpConstant.AcceptRanges),
                            }, request.HttpVersion);

                        var headerData = header.Compile();
                        if (!await holder.SafeWriteAsync(headerData.Item1, headerData.Item2) ||
                            range.Range.To == null)
                        {
                            return;
                        }
                        if (request.Method == HttpInitialRequestMethod.HEAD)
                        {
                            return;
                        }
                        await CopyStream(fileInfo, fs, holder, (long)range.Range.To, asyncFs);

                        return;
                    }

                    default:
                        return;     // ??
                    }
                }
            }
        }