コード例 #1
0
ファイル: AS2Converter.cs プロジェクト: ciolt/Kroeg-old
            public async Task Render(HttpRequest request, HttpResponse response, APEntity toRender)
            {
                response.ContentType = ConverterHelpers.GetBestMatch(_factory.MimeTypes, request.Headers["Accept"]);
                if (toRender.Type.Contains("Tombstone"))
                {
                    response.StatusCode = 410;
                }

                if (request.Method == "POST")
                {
                    response.StatusCode = 201;
                    response.Headers.Add("Location", toRender.Id);
                }

                var depth       = Math.Min(int.Parse(request.Query["depth"].FirstOrDefault() ?? "3"), 5);
                var unflattened = await _flattener.Unflatten(_entityStore, toRender, depth, isOwner : toRender.IsOwner);

                await response.WriteAsync(unflattened.Serialize(true).ToString());
            }
コード例 #2
0
        public async Task Invoke(HttpContext context, IServiceProvider serviceProvider, EntityData entityData, IEntityStore store)
        {
            var handler = ActivatorUtilities.CreateInstance <GetEntityHandler>(serviceProvider, context.User);

            if (entityData.RewriteRequestScheme)
            {
                context.Request.Scheme = "https";
            }

            var fullpath = $"{context.Request.Scheme}://{context.Request.Host}{context.Request.Path}";

            foreach (var converterFactory in _converters)
            {
                if (converterFactory.FileExtension != null && fullpath.EndsWith("." + converterFactory.FileExtension))
                {
                    fullpath = fullpath.Substring(0, fullpath.Length - 1 - converterFactory.FileExtension.Length);
                    context.Request.Headers.Remove("Accept");
                    context.Request.Headers.Add("Accept", converterFactory.RenderMimeType);
                    break;
                }
            }

            /* && ConverterHelpers.GetBestMatch(_converters[0].MimeTypes, context.Request.Headers["Accept"]) != null */
            if (context.Request.Method == "OPTIONS")
            {
                context.Response.StatusCode = 200;
                context.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
                context.Response.Headers.Add("Access-Control-Allow-Headers", "Authorization");
                context.Response.Headers.Add("Access-Control-Allow-Methods", "GET, POST");
                context.Response.Headers.Add("Access-Control-Allow-Origin", context.Request.Headers["Origin"]);
                context.Response.Headers.Add("Vary", "Origin");
                return;
            }

            Console.WriteLine(fullpath);
            foreach (var line in context.Request.Headers["Accept"])
            {
                Console.WriteLine($"---- {line}");
            }

            if (context.Request.Headers["Accept"].Contains("text/event-stream"))
            {
                await handler.EventStream(context, fullpath);

                return;
            }


            if (context.WebSockets.IsWebSocketRequest)
            {
                await handler.WebSocket(context, fullpath);

                return;
            }

            if (context.Request.Method == "POST" && context.Request.ContentType.StartsWith("multipart/form-data"))
            {
                context.Items.Add("fullPath", fullpath);
                context.Request.Path = "/settings/uploadMedia";
                await _next(context);

                return;
            }

            if (context.Request.QueryString.Value == "?hub")
            {
                context.Items.Add("fullPath", fullpath);
                context.Request.Path        = "/.well-known/hub";
                context.Request.QueryString = QueryString.Empty;
                await _next(context);

                return;
            }

            IConverter readConverter  = null;
            IConverter writeConverter = null;
            bool       needRead       = context.Request.Method == "POST";
            var        target         = fullpath;
            APEntity   targetEntity   = null;

            targetEntity = await store.GetEntity(target, false);

            if (needRead)
            {
                if (targetEntity?.Type == "_inbox")
                {
                    target = (string)targetEntity.Data["attributedTo"].Single().Primitive;
                }
            }

            if (targetEntity == null)
            {
                await _next(context);

                return;
            }


            foreach (var converterFactory in _converters)
            {
                bool worksForWrite = converterFactory.CanRender && ConverterHelpers.GetBestMatch(converterFactory.MimeTypes, context.Request.Headers["Accept"]) != null;
                bool worksForRead  = needRead && converterFactory.CanParse && ConverterHelpers.GetBestMatch(converterFactory.MimeTypes, context.Request.ContentType) != null;

                if (worksForRead && worksForWrite && readConverter == null && writeConverter == null)
                {
                    readConverter = writeConverter = converterFactory.Build(serviceProvider, target);
                    break;
                }

                if (worksForRead && readConverter == null)
                {
                    readConverter = converterFactory.Build(serviceProvider, target);
                }

                if (worksForWrite && writeConverter == null)
                {
                    writeConverter = converterFactory.Build(serviceProvider, target);
                }
            }

            ASObject data = null;

            if (readConverter != null)
            {
                data = await readConverter.Parse(context.Request.Body);
            }

            if (needRead && readConverter != null && writeConverter == null)
            {
                writeConverter = readConverter;
            }

            if (data == null && needRead && targetEntity != null)
            {
                context.Response.StatusCode = 415;
                await context.Response.WriteAsync("Unknown mime type " + context.Request.ContentType);

                return;
            }

            var arguments = context.Request.Query;

            try
            {
                if (context.Request.Method == "GET" || context.Request.Method == "HEAD" || context.Request.Method == "OPTIONS")
                {
                    data = await handler.Get(fullpath, arguments, context);
                }
                else if (context.Request.Method == "POST" && data != null)
                {
                    data = await handler.Post(context, fullpath, data);
                }
            }
            catch (UnauthorizedAccessException e)
            {
                context.Response.StatusCode = 403;
                await context.Response.WriteAsync(e.Message);
            }
            catch (InvalidOperationException e)
            {
                context.Response.StatusCode = 401;
                await context.Response.WriteAsync(e.Message);
            }

            if (context.Response.HasStarted)
            {
                return;
            }

            if (data != null)
            {
                if (context.Request.Method == "HEAD")
                {
                    context.Response.StatusCode = 200;
                    return;
                }

                if (writeConverter != null)
                {
                    await writeConverter.Render(context.Request, context.Response, data);
                }
                else if (context.Request.ContentType == "application/magic-envelope+xml")
                {
                    context.Response.StatusCode = 202;
                    await context.Response.WriteAsync("accepted");
                }
                else
                {
                    context.Request.Method  = "GET";
                    context.Request.Path    = "/render";
                    context.Items["object"] = APEntity.From(data);
                    await _next(context);
                }
                return;
            }

            if (!context.Response.HasStarted)
            {
                await _next(context);
            }
        }
コード例 #3
0
        public async Task <APEntity> GetEntity(string id, bool doRemote)
        {
            if (id == "https://www.w3.org/ns/activitystreams#Public")
            {
                var aso = new ASObject();
                aso.Type.Add("https://www.w3.org/ns/activitystreams#Collection");
                aso.Id = "https://www.w3.org/ns/activitystreams#Public";

                var ent = APEntity.From(aso);
                return(ent);
            }
            try {
                if ((new Uri(id)).Host == "localhost")
                {
                    return(await Bypass.GetEntity(id, doRemote));
                }
            } catch (UriFormatException) { /* nom */ }

            APEntity entity = null;

            if (Bypass != null)
            {
                entity = await Bypass.GetEntity(id, doRemote);
            }
            if (entity != null && !entity.IsOwner && entity.Data.Type.Any(_collections.Contains) && doRemote)
            {
                entity = null;
            }

            if (entity?.Type == "_:LazyLoad" && !doRemote)
            {
                return(null);
            }
            if ((entity != null && entity.Type != "_:LazyLoad") || !doRemote)
            {
                return(entity);
            }

            var loadUrl = id;

            if (entity?.Type == "_:LazyLoad")
            {
                loadUrl = (string)entity.Data["href"].First().Primitive;
            }

            if (loadUrl.StartsWith("tag:"))
            {
                return(null);
            }

            var htc = new HttpClient();

            htc.DefaultRequestHeaders.TryAddWithoutValidation("Accept", "application/activity+json; application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\", application/json, application/atom+xml, text/html");

            if (_context != null)
            {
                var signatureVerifier = _serviceProvider.GetRequiredService <SignatureVerifier>();
                var user = await Bypass.GetEntity(_context.User.FindFirstValue(JwtTokenSettings.ActorClaim), false);

                if (user != null)
                {
                    var jwt = await signatureVerifier.BuildJWS(user, id);

                    if (jwt != null)
                    {
                        htc.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", jwt);
                    }
                }
            }

            HttpResponseMessage response = null;

            try
            {
                response = await htc.GetAsync(loadUrl);

                if (!response.IsSuccessStatusCode)
                {
                    response = await htc.GetAsync(loadUrl + ".atom"); // hack!

                    if (!response.IsSuccessStatusCode)
                    {
                        return(null);
                    }
                }
            }
            catch (TaskCanceledException)
            {
                return(null); // timeout
            }
            catch (HttpRequestException)
            {
                return(null);
            }

            var converters = new List <IConverterFactory> {
                new AS2ConverterFactory(), new AtomConverterFactory(false)
            };

tryAgain:
            ASObject data = null;

            foreach (var converter in converters)
            {
                if (converter.CanParse && ConverterHelpers.GetBestMatch(converter.MimeTypes, response.Content.Headers.ContentType.ToString()) != null)
                {
                    data = await converter.Build(_serviceProvider, null).Parse(await response.Content.ReadAsStreamAsync());

                    break;
                }
            }

            if (data == null)
            {
                if (response.Headers.Contains("Link"))
                {
                    var split = string.Join(", ", response.Headers.GetValues("Link")).Split(new[] { ", " }, StringSplitOptions.RemoveEmptyEntries);
                    foreach (var spl in split)
                    {
                        var args = spl.Split(';').Select(a => a.Trim()).ToArray();
                        if (args.Contains("rel=\"alternate\"") && args.Contains("type=\"application/atom+xml\""))
                        {
                            response = await htc.GetAsync(args[0].Substring(1, args[0].Length - 2));

                            goto tryAgain;
                        }
                    }
                }

                try
                {
                    var links = (await response.Content.ReadAsStringAsync()).Split('\n');
                    var alt   = links.FirstOrDefault(a => a.Contains("application/atom+xml") && a.Contains("alternate"));
                    if (alt == null)
                    {
                        return(null);
                    }
                    var l = XDocument.Parse(alt + "</link>").Root;
                    if (l.Attribute(XNamespace.None + "type")?.Value == "application/atom+xml")
                    {
                        response = await htc.GetAsync(l.Attribute(XNamespace.None + "href")?.Value);

                        goto tryAgain;
                    }
                }
                catch (Exception) { }

                return(null);
            }

            // forces out the old lazy load, if used
            await _entityFlattener.FlattenAndStore(Bypass, data, false);

            return(await Bypass.GetEntity(id, true));
        }
コード例 #4
0
        public async Task <APEntity> GetEntity(string id, bool doRemote)
        {
            if (id == "https://www.w3.org/ns/activitystreams#Public")
            {
                var aso = new ASObject();
                aso.Type.Add("https://www.w3.org/ns/activitystreams#Collection");
                aso.Id = "https://www.w3.org/ns/activitystreams#Public";

                var ent = APEntity.From(aso);
                return(ent);
            }
            string origin = id;

            try {
                var uri = new Uri(id);
                if (uri.Host == "localhost")
                {
                    return(await Bypass.GetEntity(id, doRemote));
                }
                origin = uri.GetLeftPart(UriPartial.Authority);
            } catch (UriFormatException) { /* nom */ }

            APEntity entity = null;

            if (Bypass != null)
            {
                entity = await Bypass.GetEntity(id, doRemote);
            }

/*            if (entity == null)
 *          {
 *              var possibilities = (await _getRE().Query(new RelevantEntitiesService.ContainsAnyStatement("https://www.w3.org/ns/activitystreams#url") { id })).Where(a => Uri.IsWellFormedUriString(a.Id, UriKind.Absolute) && (new Uri(a.Id)).GetLeftPart(UriPartial.Authority) == origin).ToList();
 *              if (possibilities.Count == 1) entity = possibilities.First();
 *          }*/
            if (entity != null && !entity.IsOwner && entity.Data.Type.Any(_collections.Contains) && doRemote)
            {
                entity = null;
            }
            if (entity != null || !doRemote)
            {
                return(entity);
            }

            var htc     = new HttpClient();
            var request = new HttpRequestMessage(HttpMethod.Get, id);

            request.Headers.TryAddWithoutValidation("Accept", "application/activity+json; application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\", application/json, text/html");

            if (_context != null)
            {
                var signatureVerifier = _serviceProvider.GetRequiredService <SignatureVerifier>();
                var user = await Bypass.GetEntity(_context.User.FindFirstValue("actor"), false);

                if (user != null)
                {
                    var jwt = await signatureVerifier.BuildJWS(user, id);

                    if (jwt != null)
                    {
                        request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", jwt);
                    }
                    request.Headers.TryAddWithoutValidation("Signature", await _keyService.BuildHTTPSignature(user.Id, request));
                }
            }

            HttpResponseMessage response = null;

            try
            {
                response = await htc.SendAsync(request);
            }
            catch (TaskCanceledException)
            {
                return(null); // timeout
            }
            catch (HttpRequestException)
            {
                return(null);
            }

            ASObject data = null;
            await response.Content.LoadIntoBufferAsync();

            foreach (var converter in ServerConfig.Converters)
            {
                if (converter.CanParse && ConverterHelpers.GetBestMatch(converter.MimeTypes, response.Content.Headers.ContentType.ToString()) != null)
                {
                    try {
                        data = await converter.Build(_serviceProvider, null).Parse(await response.Content.ReadAsStreamAsync());

                        break;
                    } catch (NullReferenceException e) { Console.WriteLine(e); /* nom */ }
                }
            }

            if (data == null)
            {
                return(null);
            }

            // forces out the old lazy load, if used
            await _entityFlattener.FlattenAndStore(Bypass, data, false);

            return(await Bypass.GetEntity(id, true));
        }