Пример #1
0
        public override async Task <int> ReadAsync(byte[] buffer, int _offset, int count, CancellationToken cancellationToken)
        {
            if (length == 0)
            {
                return(0);
            }

            var pos = Position;
            await _readSem.WaitAsync().ConfigureAwait(false);

            try
            {
                var seg = cachedMeta ?? await engine.DownloadMetaForPath(path).ConfigureAwait(false);

                if (seg == null)
                {
                    throw new FileNotFoundException();
                }
                cachedMeta = seg;

                Int64 len    = Length;
                long  size   = count;
                long  offset = _offset + pos;

                Console.WriteLine("offset: {0}, count: {1}, path: {2}", offset, count, path);

                if (offset < len)
                {
                    if (offset + size > len)
                    {
                        size = len - offset;
                    }

                    var read = (long)0;

                    int extraBlockCounter = 4;

                    // MAYBE: make concurrent and cap concurrency? or look ahead
                    foreach (var c in seg.Commands
                             .Where(c => c.CMD == MetaSegment.Command.CMDV.ADD)
                             .Where(c => c.TYPE == MetaSegment.Command.TYPEV.BLOCK)
                             .Select(c => c.FILE_ORIGIN)
                             .SkipWhile(c => c.Start + c.Size <= offset)
                             )
                    {
                        if (read >= size || c.Start >= offset + size)
                        {
                            if (extraBlockCounter == 0)
                            {
                                break;
                            }

                            extraBlockCounter--;
                            _ = engine.DownloadChunk(engine.Generator.GenerateRawOrParityID(c.Hash));
                            continue;
                        }
                        var mspos1  = read;
                        var offset1 = (int)Math.Max(0, (offset + read) - c.Start);
                        var size1   = (int)Math.Min(c.Size - offset1, size - read);

                        if (size1 < 0)
                        {
                            throw new Exception("size1 < 0");
                        }
                        read += size1;

                        var data = await engine.DownloadChunk(engine.Generator.GenerateRawOrParityID(c.Hash)).ConfigureAwait(false);

                        Array.Copy(data, offset1, buffer, mspos1, size1);
                    }

                    Position += read;
                    return((int)read);
                }
                else
                {
                    return(0);
                }
            }
            finally
            {
                _readSem.Release();
            }
        }
Пример #2
0
        public async Task <IActionResult> Index()
        {
            var engine = Program.BinsyncEngine;

            var route = getNormalizedRoute();
            var path  = getBinsyncPathFromNormalizedRoute(route);

            var m = await engine.DownloadMetaForPath(path);

            if (m == null)
            {
                // handle empty dir & file
                var prev = path.Split('/').SkipLast(1).Aggregate("", (a, b) => a + "/" + b).Trim('/');
                var cur  = path.Split('/').Last().Trim('/');
                if (cur == "" && prev == "")
                {
                    m = new Engine.Meta {
                        IsFile = false, Path = "", Commands = new List <MetaSegment.Command>()
                    };
                }
                else
                {
                    var p = await engine.DownloadMetaForPath(prev);

                    if (p == null)
                    {
                        return(NotFound());
                    }
                    MetaSegment.Command cmd;
                    if ((cmd = p.Commands?.Where(c => c.FOLDER_ORIGIN?.Name == cur).Take(1).FirstOrDefault()) != null)
                    {
                        m = new Engine.Meta {
                            IsFile = cmd.TYPE == MetaSegment.Command.TYPEV.FILE, Path = path, Commands = new List <MetaSegment.Command>()
                        }
                    }
                    ;
                    else
                    {
                        return(NotFound());
                    }
                }
            }
            if (m.IsFile)
            {
                return(Redirect(escape($"/_dav/{m.Path}")));
            }

            var entries = new List <entry>();

            if (path != "")
            {
                entries.Add(new entry
                {
                    href   = escape(route.Split('/').SkipLast(1).Aggregate("", (a, b) => a + "/" + b).Substring(1)),
                    label  = "..",
                    @class = "back",
                    title  = "Back",
                });
            }

            entries.AddRange(m.Commands.Select(c => new { c, f = c.TYPE == MetaSegment.Command.TYPEV.FILE }).Select(x => new entry
            {
                href = escape(x.f
                                           ? $"/_dav/{m.Path}/{x.c.FOLDER_ORIGIN?.Name}".Replace("//", "/")
                                           : $"{route}/{x.c.FOLDER_ORIGIN?.Name}"),
                label  = x.c.FOLDER_ORIGIN?.Name,
                @class = x.f ? "file" : "folder",
                title  = x.f ? $"File: {x.c.FOLDER_ORIGIN?.FileSize} B" : "Folder",
            }));


            var pubHash = engine.PublicHash.Substring(0, 8);
            var text    = $"<font color=\"gray\">[{HttpUtility.HtmlEncode(pubHash)}]</font> /" + HttpUtility.HtmlEncode(m.Path);

            var elems = entries
                        .Select(e => $"<a href=\"{e.href}\"><li class=\"{e.@class}\" title=\"{e.@title}\">{HttpUtility.HtmlEncode(e.label)}</li></a>")
                        .ToList();

            if (path == "" && entries.Count == 0 || elems.Count == 1)
            {
                elems.Add("<li class=\"empty\">This folder is empty.</li>");
            }

            var webDavUrl = $"{Request.Scheme}://{Request.Host}" + escape($"/_dav/{m.Path}".TrimEnd('/'));
            var title     = HttpUtility.HtmlEncode($"binsync [{pubHash}]");

            Response.ContentType = "text/html; charset=UTF-8";
            return(Content($@"
<!DOCTYPE html>
<html>
	<head>
		<meta charset=""UTF-8"">
		<title>{title}</title>
		<style>
			a:link {{
				text-decoration: none;
			}}
			a:hover {{
				text-decoration: underline;
			}}
			li {{
				list-style: none;
			}}
			.empty {{
				color: gray;
			}}
			li::before {{
				display:inline-block;
			}}
			.empty::before {{ content: ""ℹ️ ""; }}
			.back::before {{ content: ""⬅️ ""; }}
			.folder::before {{ content: ""📁 ""; }}
			.file::before {{ content: ""📄 ""; }}
		</style>
	</head>
	<body>
		<a title=""Home"" href=""/"">
			<img height=""32px"" alt=""binsync logo"" src=""/images/header_logo.png"">
		</a>
		<hr>
		<h3>{text}</h3>
		<ul>
			{elems.Aggregate("", (a, b) => $"{a}\n\t\t\t{b}").Trim('\n').TrimStart('\t')}
		</ul>
		<hr>
		WebDAV: {webDavUrl}
	</body>
</html>
			"            ));

            // todo: learn some asp net
        }