Ejemplo n.º 1
0
        /// <summary>Converts string values to given collection.</summary>
        /// <param name="converterProvider">The converter provider.</param>
        /// <param name="values">The values.</param>
        /// <param name="collectionType">The collection type.</param>
        /// <param name="request">The request.</param>
        /// <returns>Instance of the <paramref name="collectionType" />.</returns>
        public static object ConvertToCollection(this IConverterProvider converterProvider, IEnumerable<string> values, Type collectionType, IRequestInfo request = null)
        {
            if (values == null)
            {
                return null;
            }

            if (collectionType == null)
            {
                throw new ArgumentNullException("collectionType");
            }

            var itemType = collectionType.GetItemType();
            bool success;
            var result = ConvertUsingTypeConverters(values, itemType, out success);
            if ((success) || (request == null))
            {
                return result.MakeInstance(collectionType, itemType);
            }

            if (converterProvider == null)
            {
                throw new ArgumentNullException("converterProvider");
            }

            return ConvertUsingCustomConverters(converterProvider, request, values, itemType).MakeInstance(collectionType, itemType);
        }
Ejemplo n.º 2
0
 public ApiRequest(IRequestInfo requestinfo, CollectionSettings currentCollectionSettings, Book.Book currentBook)
 {
     _requestInfo = requestinfo;
     CurrentCollectionSettings = currentCollectionSettings;
     CurrentBook = currentBook;
     Parameters = requestinfo.GetQueryParameters();
 }
Ejemplo n.º 3
0
        /// <summary>Converts string to given type.</summary>
        /// <param name="converterProvider">The converter provider.</param>
        /// <param name="value">The value.</param>
        /// <param name="type">The target type.</param>
        /// <param name="request">The request.</param>
        /// <returns>Instance of the <paramref name="type" />.</returns>
        public static object ConvertTo(this IConverterProvider converterProvider, string value, Type type, IRequestInfo request = null)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            if (value == null)
            {
                return (type.IsValueType ? Activator.CreateInstance(type) : null);
            }

            bool success;
            object result = ConvertUsingTypeConverters(value, type, out success);
            if ((success) || (request == null))
            {
                return result;
            }

            if (converterProvider == null)
            {
                throw new ArgumentNullException("converterProvider");
            }

            return ConvertUsingCustomConverters(converterProvider, request, value, type);
        }
Ejemplo n.º 4
0
 public static bool Handle(EndpointRegistration endpointRegistration, IRequestInfo info, CollectionSettings collectionSettings, Book.Book currentBook)
 {
     var request = new ApiRequest(info, collectionSettings, currentBook);
     try
     {
         if(Program.RunningUnitTests)
         {
             endpointRegistration.Handler(request);
         }
         else
         {
             var formForSynchronizing = Application.OpenForms.Cast<Form>().Last();
             if (endpointRegistration.HandleOnUIThread && formForSynchronizing.InvokeRequired)
             {
                 formForSynchronizing.Invoke(endpointRegistration.Handler, request);
             }
             else
             {
                 endpointRegistration.Handler(request);
             }
         }
         if(!info.HaveOutput)
         {
             throw new ApplicationException(string.Format("The EndpointHandler for {0} never called a Succeeded(), Failed(), or ReplyWith() Function.", info.RawUrl.ToString()));
         }
     }
     catch (Exception e)
     {
         SIL.Reporting.ErrorReport.ReportNonFatalExceptionWithMessage(e, info.RawUrl);
         return false;
     }
     return true;
 }
 public static string GetResponseString(IRequestInfo requestInfo)
 {
     using (var dataStream = GetResponseStream(requestInfo))
       using (var reader = new StreamReader(dataStream, Encoding))
       {
     return reader.ReadToEnd();
       }
 }
Ejemplo n.º 6
0
 public void Reset(IRequestInfo requestInfo) {
     _requestInfo = requestInfo;
     _carriageReturn = false;
     _statusBuffer.Length = 0;
     _bufferPosition = 0;
     _bufferDataLength = 0;
     _responseDataPosition = 0;
     _currentResponse = new Response(new[] { "ERROR", "INCOMPLETE" });
 }
Ejemplo n.º 7
0
        public static Stream GetResponseStream(IRequestInfo requestInfo)
        {
            if (requestInfo == null)
                throw new ArgumentNullException("requestInfo");

            var webRequest = (HttpWebRequest)WebRequest.Create(requestInfo.UriString);
            webRequest.UserAgent = UserAgent;
            webRequest.Accept = Accept;

            if (requestInfo.PostContent != null)
                webRequest.Method = WebRequestMethods.Http.Post;
            else
                webRequest.Method = WebRequestMethods.Http.Get;

            if (requestInfo.PostContent != null)
            {
                byte[] byteArray = requestInfo.PostContent;

                // Set the ContentType property of the WebRequest.
                webRequest.ContentType = requestInfo.ContentType;
                webRequest.ContentLength = byteArray.Length;

                // Get the request stream.
                using (Stream dataStream = webRequest.GetRequestStream())
                {
                    // Write the data to the request stream.
                    dataStream.Write(byteArray, 0, byteArray.Length);
                    dataStream.Close();
                }
            }

            Stream memoryStream = new MemoryStream();

            try
            {
                using (WebResponse response = webRequest.GetResponse())
                using (Stream dataStream = response.GetResponseStream())
                {
                    if (dataStream != null)
                    {
                        CopyStream(dataStream, memoryStream);
                        dataStream.Close();
                    }
                    response.Close();
                }
            }
            catch (WebException ex)
            {
                //TODO: Добавить протоколирование
                Debug.WriteLine(ex.Message);
            }

            return memoryStream;
        }
        public static Stream GetResponseStream(IRequestInfo requestInfo)
        {
            if (requestInfo == null)
            throw new ArgumentNullException("requestInfo");

              var webRequest = WebRequest.Create(requestInfo.UriString) as HttpWebRequest;
              webRequest.UserAgent  = USERAGENT;
              webRequest.Accept     = ACCEPT;

              if (requestInfo.PostContent != null)
            webRequest.Method = WebRequestMethods.Http.Post;
              else
            webRequest.Method = WebRequestMethods.Http.Get;

              if (requestInfo.PostContent != null)
              {
            byte[] byteArray = requestInfo.PostContent;

            webRequest.ContentType = requestInfo.ContentType;
            webRequest.ContentLength = byteArray.Length;

            using (Stream dataStream = webRequest.GetRequestStream())
            {
              dataStream.Write(byteArray, 0, byteArray.Length);
              dataStream.Close();
            }
              }

              Stream memoryStream = new MemoryStream();

              try
              {
            using (WebResponse response = webRequest.GetResponse())
            using (Stream dataStream = response.GetResponseStream())
            {
              if (dataStream != null)
              {
            CopyStream(dataStream, memoryStream);
            dataStream.Close();
              }
              response.Close();
            }
              }
              catch (WebException ex)
              {
            Debug.WriteLine(ex.Message);
              }

              return memoryStream;
        }
Ejemplo n.º 9
0
        /// <inheritdoc />
        public async Task Process(IRequestInfo request)
        {
            if (request == null)
            {
                throw new ArgumentNullException("request");
            }

            var httpRequest = request as RequestInfo;
            if (httpRequest == null)
            {
                throw new ArgumentOutOfRangeException("request");
            }

            await AuthenticateInternal(httpRequest);
        }
Ejemplo n.º 10
0
        protected override bool ProcessRequest(IRequestInfo info)
        {
            if (base.ProcessRequest(info))
                return true;

            if (!_useCache)
                return false;

            var imageFile = GetLocalPathWithoutQuery(info);

            // only process images
            var isSvg = imageFile.EndsWith(".svg", StringComparison.OrdinalIgnoreCase);
            if (!IsImageTypeThatCanBeDegraded(imageFile) && !isSvg)
                return false;

            imageFile = imageFile.Replace("thumbnail", "");

            var processImage = !isSvg;

            // This happens with the new way we are serving css files
            if (!RobustFile.Exists(imageFile))
            {
                var fileName = Path.GetFileName(imageFile);
                var sourceDir = FileLocator.GetDirectoryDistributedWithApplication(BloomFileLocator.BrowserRoot);
                imageFile = Directory.EnumerateFiles(sourceDir, fileName, SearchOption.AllDirectories).FirstOrDefault();

                // image file not found
                if (string.IsNullOrEmpty(imageFile)) return false;

                // BL-2368: Do not process files from the BloomBrowserUI directory. These files are already in the state we
                //          want them. Running them through _cache.GetPathToResizedImage() is not necessary, and in PNG files
                //          it converts all white areas to transparent. This is resulting in icons which only contain white
                //          (because they are rendered on a dark background) becoming completely invisible.
                processImage = false;
            }

            if (processImage)
            {
                // thumbnail requests have the thumbnail parameter set in the query string
                var thumb = info.GetQueryParameters()["thumbnail"] != null;
                imageFile = _cache.GetPathToResizedImage(imageFile, thumb);

                if (string.IsNullOrEmpty(imageFile)) return false;
            }

            info.ReplyWithImage(imageFile);
            return true;
        }
Ejemplo n.º 11
0
        /// <inheritdoc />
        public Task<object> Transform(IRequestMapping requestMapping, IRequestInfo request, object result, object[] arguments)
        {
            RequestInfo requestInfo;
            MethodInfo underlyingMethod;
            if (!CanOutputHypermedia((underlyingMethod = requestMapping.Operation.UnderlyingMethod).ReturnType, requestInfo = request as RequestInfo))
            {
                return Task.FromResult(result);
            }

            int totalItems = ((IEnumerable)result).Cast<object>().Count();
            int skip = 0;
            int take = 0;
            bool canOutputHypermedia = false;
            KeyValuePair<Verb, MethodInfo> method;
            if ((requestMapping.Target.GetType().GetImplementationOfAny(typeof(IController<>), typeof(IAsyncController<>)) != null) &&
                (!Equals(method = requestMapping.Target.GetType().DiscoverCrudMethods().FirstOrDefault(entry => entry.Value == underlyingMethod), default(KeyValuePair<Verb, MethodInfo>))))
            {
                switch (method.Key.ToString())
                {
                    case "":
                        var parameters = underlyingMethod.GetParameters();
                        var resultingValues = arguments.Where((item, index) => parameters[index].IsOut).ToList();
                        totalItems = (resultingValues.Count > 0 ? (int)resultingValues[0] : -1);
                        if ((arguments[1] != null) && (arguments[2] != null))
                        {
                            skip = (int)arguments[1];
                            take = ((take = (int)arguments[2]) == 0 ? 0 : Math.Min(take, totalItems));
                            canOutputHypermedia = (requestMapping.ArgumentSources[1] == ArgumentValueSources.Bound) && (requestMapping.ArgumentSources[2] == ArgumentValueSources.Bound);
                        }

                        break;
                }
            }

            if (!canOutputHypermedia)
            {
                return Task.FromResult(result);
            }

            var namedGraphSelector = _namedGraphSelectorFactory.NamedGraphSelector;
            ILocallyControlledNamedGraphSelector locallyControlledNamedGraphSelector = namedGraphSelector as ILocallyControlledNamedGraphSelector;
            result = (locallyControlledNamedGraphSelector == null ? TransformCollection(result, requestInfo.Url, totalItems, skip, take) :
                TransformColectionWithLock(locallyControlledNamedGraphSelector, result, requestInfo, totalItems, skip, take));
            return Task.FromResult(result);
        }
Ejemplo n.º 12
0
 public new string SubstitutePathParameters(string path, IRequestInfo requestInfo)
 {
     return(base.SubstitutePathParameters(path, requestInfo));
 }
 /// <summary>
 /// Initialises a new instance of the <see cref="RequestBodySerializerInfo"/> structure
 /// </summary>
 /// <param name="requestInfo">Information about the request</param>
 /// <param name="formatProvider">Format provider to use</param>
 public RequestBodySerializerInfo(IRequestInfo requestInfo, IFormatProvider formatProvider)
 {
     this.RequestInfo    = requestInfo;
     this.FormatProvider = formatProvider;
 }
Ejemplo n.º 14
0
 public override string ToString(IRequestInfo request)
 {
     return("do nothing");
 }
Ejemplo n.º 15
0
 public CommonService(IUnitOfWork unitOfWork, IRequestInfo requestInfo)
     : base(unitOfWork)
 {
     this.requestInfo = requestInfo;
 }
Ejemplo n.º 16
0
 /// <summary>
 /// 通讯干扰时调用此函数
 /// </summary>
 /// <param name="info"></param>
 public abstract void CommunicateError(IRequestInfo info);
Ejemplo n.º 17
0
        /// <summary>
        /// Given a set of headers, apply them to the given HttpRequestMessage. Headers will override any of that type already present
        /// </summary>
        /// <param name="requestInfo">RequestInfo for this request</param>
        /// <param name="requestMessage">HttpRequestMessage to add the headers to</param>
        /// <param name="headers">Headers to add</param>
        /// <param name="areMethodHeaders">True if these headers came from the method, false if they came from the class</param>
        protected virtual void ApplyHeadersSet(
            IRequestInfo requestInfo,
            HttpRequestMessage requestMessage,
            IEnumerable <KeyValuePair <string, string?> > headers,
            bool areMethodHeaders)
        {
            HttpContent?dummyContent  = null;
            var         headersGroups = headers.GroupBy(x => x.Key);

            foreach (var headersGroup in headersGroups)
            {
                // Can't use .Contains, as it will throw if the header isn't a valid type
                if (requestMessage.Headers.Any(x => x.Key == headersGroup.Key))
                {
                    requestMessage.Headers.Remove(headersGroup.Key);
                }

                // Null values are used to remove instances of a header, but should not be added
                string[] headersToAdd = headersGroup.Select(x => x.Value).Where(x => x != null).ToArray() !;
                if (!headersToAdd.Any())
                {
                    continue;
                }

                bool added = requestMessage.Headers.TryAddWithoutValidation(headersGroup.Key, headersToAdd);

                // If we failed, it's probably a content header. Try again there
                if (!added)
                {
                    // If it's a method header, then add a dummy body if necessary
                    // If it's a class header, then add a dummy body if there isn't one but there is a [Body]
                    // parameter, otherwise ignore it.
                    // If it's a class header, then throw only if it isn't a content header (but don't add a dummy body containing it)
                    if (requestMessage.Content != null)
                    {
                        if (requestMessage.Content.Headers.Any(x => x.Key == headersGroup.Key))
                        {
                            requestMessage.Content.Headers.Remove(headersGroup.Key);
                        }
                        added = requestMessage.Content.Headers.TryAddWithoutValidation(headersGroup.Key, headersToAdd);
                    }
                    else
                    {
                        // If they've added a content header, my reading of the RFC is that we are actually sending a body (even if they haven't
                        // said what should be in it), and therefore we need to send Content-Length
                        if (dummyContent == null)
                        {
                            dummyContent = new ByteArrayContent(ArrayUtil.Empty <byte>());
                        }

                        added = dummyContent.Headers.TryAddWithoutValidation(headersGroup.Key, headersToAdd);
                        if (added && (areMethodHeaders || requestInfo.BodyParameterInfo != null))
                        {
                            requestMessage.Content = dummyContent;
                        }
                    }
                }

                // Technically this can be triggered, but I can't come up with any inputs which will
                if (!added)
                {
                    throw new ArgumentException($"Header {headersGroup.Key} could not be added. Maybe it's associated with HTTP responses, or it's malformed?");
                }
            }
        }
Ejemplo n.º 18
0
        /// <summary>
        /// Given an IRequestInfo and pre-substituted relative path, constructs a URI with the right query parameters
        /// </summary>
        /// <param name="baseAddress">Base address to start with, with placeholders already substituted</param>
        /// <param name="basePath">Base path to start with, with placeholders already substituted</param>
        /// <param name="path">Path to start with, with placeholders already substituted</param>
        /// <param name="requestInfo">IRequestInfo to retrieve the query parameters from</param>
        /// <returns>Constructed URI; relative if 'path' was relative, otherwise absolute</returns>
        protected virtual Uri ConstructUri(string baseAddress, string basePath, string path, IRequestInfo requestInfo)
        {
            UriBuilder uriBuilder;

            try
            {
                // For the base address, we choose HttpClient.BaseAddress, unless it's null where we choose baseAdress
                // If path is absolute, then baseAddress and basePath are both ignored.
                // If path starts with /, then basePath is ignored but baseAddress is not.
                // If basePath is absolute, then baseAddress is ignored.

                string trimmedPath = (path ?? string.Empty).TrimStart('/');
                // Here, a leading slash will strip the path from baseAddress
                var uri = new Uri(trimmedPath, UriKind.RelativeOrAbsolute);
                if (!uri.IsAbsoluteUri && path?.StartsWith("/") != true && !string.IsNullOrEmpty(basePath))
                {
                    uri = Prepend(uri, basePath.TrimStart('/'));
                }

                if (!uri.IsAbsoluteUri)
                {
                    string?resolvedBaseAddress = this.httpClient.BaseAddress?.ToString() ?? baseAddress?.TrimStart('/');
                    if (!string.IsNullOrEmpty(resolvedBaseAddress))
                    {
                        uri = Prepend(uri, resolvedBaseAddress !);
                    }
                }

                // If it's still relative, 'new UriBuilder(Uri)' won't accept it, but 'new UriBuilder(string)' will
                // (by prepending 'http://').
                uriBuilder = uri.IsAbsoluteUri ? new UriBuilder(uri) : new UriBuilder(uri.ToString());

                Uri Prepend(Uri uri, string path)
                {
                    // Need to make sure it ends with a trailing slash, or appending our relative path will strip
                    // the last path component (assuming there is one)
                    if (!path.EndsWith("/") && !string.IsNullOrEmpty(uri.OriginalString))
                    {
                        path += '/';
                    }
                    return(new Uri(path + uri.OriginalString, UriKind.RelativeOrAbsolute));
                }
            }
            catch (FormatException e)
            {
                // The original exception doesn't actually include the path - which is not helpful to the user
                throw new FormatException(string.Format("Path '{0}' is not valid: {1}", path, e.Message));
            }

            string?query = this.BuildQueryParam(uriBuilder.Query, requestInfo.RawQueryParameters, requestInfo.QueryParams, requestInfo.QueryProperties, requestInfo);

            // Mono's UriBuilder.Query setter will always add a '?', so we can end up with a double '??'.
            uriBuilder.Query = query.TrimStart('?');

            return(uriBuilder.Uri);
        }
Ejemplo n.º 19
0
        protected override bool ProcessRequest(IRequestInfo info)
        {
            if (base.ProcessRequest(info))
            {
                return(true);
            }

            var r = info.LocalPathWithoutQuery.Replace("/bloom/", "");

            r = r.Replace("library/", "");
            if (r.Contains("libraryContents"))
            {
                GetLibraryBooks(info);
            }
            else if (r == "libraryName")
            {
                info.WriteCompleteOutput(_collectionSettings.CollectionName + " Library");
            }
            else if (r.Contains("SourceCollectionsList"))
            {
                GetStoreBooks(info);
            }
            else if (r.StartsWith("thumbnails/"))
            {
                r = r.Replace("thumbnails/", "");
                r = r.Replace("%5C", "/");
                r = r.Replace("%20", " ");
                if (File.Exists(r))
                {
                    info.ReplyWithImage(r);
                }
            }
            else if (r.EndsWith(".png") && r.Contains("thumbnail"))
            {
                info.ContentType = "image/png";

                r = r.Replace("thumbnail", "");
                //if (r.Contains("thumb"))
                {
                    if (File.Exists(r))
                    {
                        info.ReplyWithImage(r);
                    }
                    else
                    {
                        var imgPath = FileLocator.GetFileDistributedWithApplication("BloomBrowserUI", "book.png");
                        info.ReplyWithImage(imgPath);
                        //book.GetThumbNailOfBookCoverAsync(book.Type != Book.Book.BookType.Publication,image => RefreshOneThumbnail(book, image));
                    }
                }
//				else
//				{
//					var imgPath = FileLocator.GetFileDistributedWithApplication("root", "ui", "book.png");
//					info.ReplyWithImage(imgPath);
//				}
            }
            else
            {
                info.ContentType = GetContentType(Path.GetExtension(r));
                string path = FileLocator.GetFileDistributedWithApplication("BloomBrowserUI", r);


                //request.QueryString.GetValues()
                info.ReplyWithFileContent(path);
            }
            return(true);
        }
Ejemplo n.º 20
0
 public new void ApplyHeaders(IRequestInfo requestInfo, HttpRequestMessage requestMessage)
 {
     base.ApplyHeaders(requestInfo, requestMessage);
 }
Ejemplo n.º 21
0
        public async Task <Boolean> SignInUserAsync(String loginProvider, String providerKey, String token, IRequestInfo request)
        {
            AppUser user = await UserManager.FindAsync(new UserLoginInfo(loginProvider, providerKey));

            if (user == null)
            {
                return(false);
            }
            // TODO: generate token
            //Boolean result = await UserManager.VerifyUserTokenAsync(user.Id, loginProvider, token);
            //if (result)
            //{
            await SignInManager.SignInAsync(user, false, false);

            if (request != null)
            {
                user.LastLoginDate = DateTime.Now;
                user.LastLoginHost = request.HostText;
                await _userManager.UpdateAsync(user);
            }
            return(true);
            //}
            //return result;
        }
Ejemplo n.º 22
0
 protected override Task<HttpResponseMessage> SendRequestAsync(IRequestInfo requestInfo)
 {
     this.RequestInfo = requestInfo;
     return this.ResponseMessage;
 }
Ejemplo n.º 23
0
 public override string ToString(IRequestInfo request)
 {
     return(ToString());
 }
Ejemplo n.º 24
0
        // Every path should return false or send a response.
        // Otherwise we can get a timeout error as the browser waits for a response.
        //
        // NOTE: this method gets called on different threads!
        protected override bool ProcessRequest(IRequestInfo info)
        {
            var localPath = GetLocalPathWithoutQuery(info);

            //enhance: something feeds back these branding logos with a weird URL, that shouldn't be.
            if(localPath.IndexOf("api/branding") > 20) // this 20 is just arbitrary... the point is, if it doesn't start with api/branding, it is bogus
            {
                return false;
            }

            if (localPath.ToLower().StartsWith("api/"))
            {
                var endpoint = localPath.Substring(3).ToLowerInvariant().Trim(new char[] {'/'});
                foreach (var pair in _endpointRegistrations.Where(pair =>
                        Regex.Match(endpoint,
                            "^" + //must match the beginning
                            pair.Key.ToLower()
                        ).Success))
                {
                    lock(SyncObj)
                    {
                        return ApiRequest.Handle(pair.Value, info, CurrentCollectionSettings, _bookSelection.CurrentSelection);
                    }
                }
            }

            //OK, no more obvious simple API requests, dive into the rat's nest of other possibilities
            if (base.ProcessRequest(info))
                return true;

            if(localPath.Contains("CURRENTPAGE")) //useful when debugging. E.g. http://localhost:8091/bloom/CURRENTPAGE.htm will always show the page we're on.
            {
                localPath = _keyToCurrentPage;
            }

            string content;
            bool gotSimulatedPage;
            lock (_urlToSimulatedPageContent)
            {
                gotSimulatedPage = _urlToSimulatedPageContent.TryGetValue(localPath, out content);
            }
            if (gotSimulatedPage)
            {
                info.ContentType = "text/html";
                info.WriteCompleteOutput(content ?? "");
                return true;
            }

            if (localPath.StartsWith(OriginalImageMarker) && IsImageTypeThatCanBeDegraded(localPath))
            {
                // Path relative to simulated page file, and we want the file contents without modification.
                // (Note that the simulated page file's own URL starts with this, so it's important to check
                // for that BEFORE we do this check.)
                localPath = localPath.Substring(OriginalImageMarker.Length + 1);
                return ProcessAnyFileContent(info, localPath);
            }

            if (localPath.StartsWith("error", StringComparison.InvariantCulture))
            {
                ProcessError(info);
                return true;
            }
            else if (localPath.StartsWith("i18n/", StringComparison.InvariantCulture))
            {
                if (ProcessI18N(localPath, info))
                    return true;
            }
            else if (localPath.StartsWith("directoryWatcher/", StringComparison.InvariantCulture))
                return ProcessDirectoryWatcher(info);
            else if (localPath.StartsWith("localhost/", StringComparison.InvariantCulture))
            {
                var temp = LocalHostPathToFilePath(localPath);
                if (RobustFile.Exists(temp))
                    localPath = temp;
            }
            // this is used only by the readium viewer
            else if (localPath.StartsWith("node_modules/jquery/dist/jquery.js"))
            {
                localPath = BloomFileLocator.GetBrowserFile("jquery.min.js");
                // Avoid having "output/browser/" removed on Linux developer machines.
                // GetBrowserFile adds output to the path on developer machines, but not user installs.
                return ProcessContent(info, localPath);
            }
            //Firefox debugger, looking for a source map, was prefixing in this unexpected
            //way.
            localPath = localPath.Replace("output/browser/", "");

            return ProcessContent(info, localPath);
        }
Ejemplo n.º 25
0
        /// <summary>
        /// Serializes the value of a path parameter, using an appropriate method
        /// </summary>
        /// <param name="pathParameter">Path parameter to serialize</param>
        /// <param name="requestInfo">RequestInfo representing the request</param>
        /// <returns>Serialized value</returns>
        protected virtual KeyValuePair <string, string?> SerializePathParameter(PathParameterInfo pathParameter, IRequestInfo requestInfo)
        {
            switch (pathParameter.SerializationMethod)
            {
            case PathSerializationMethod.ToString:
                return(pathParameter.SerializeToString(this.FormatProvider));

            case PathSerializationMethod.Serialized:
                if (this.RequestPathParamSerializer == null)
                {
                    throw new InvalidOperationException("Cannot serialize path parameter when RequestPathParamSerializer is null. Please set RequestPathParamSerializer");
                }
                var result = pathParameter.SerializeValue(this.RequestPathParamSerializer, requestInfo, this.FormatProvider);
                return(result);

            default:
                throw new InvalidOperationException("Should never get here");
            }
        }
Ejemplo n.º 26
0
        private static bool GetTopicList(IRequestInfo info)
        {
            var keyToLocalizedTopicDictionary = new Dictionary<string, string>();
            foreach (var topic in BookInfo.TopicsKeys)
            {
                var localized = LocalizationManager.GetDynamicString("Bloom", "Topics." + topic, topic,
                    @"shows in the topics chooser in the edit tab");
                keyToLocalizedTopicDictionary.Add(topic, localized);
            }
            string localizedNoTopic = LocalizationManager.GetDynamicString("Bloom", "Topics.NoTopic", "No Topic",
                @"shows in the topics chooser in the edit tab");
            var arrayOfKeyValuePairs = from key in keyToLocalizedTopicDictionary.Keys
                orderby keyToLocalizedTopicDictionary[key]
                select string.Format("\"{0}\": \"{1}\"",key,keyToLocalizedTopicDictionary[key]);
            var pairs = arrayOfKeyValuePairs.Concat(",");
            info.ContentType = "application/json";
            var data = string.Format("{{\"NoTopic\": \"{0}\", {1} }}", localizedNoTopic, pairs);

            info.WriteCompleteOutput(data);
            /*			var data = new {NoTopic = localizedNoTopic, pairs = arrayOfKeyValuePairs};
             * var serializeObject = JsonConvert.SerializeObject(data, new JsonSerializerSettings
                        {
                            TypeNameHandling = TypeNameHandling.None,
                            TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple,
                        });
                        */
            //info.WriteCompleteOutput(serializeObject);

            return true;
        }
Ejemplo n.º 27
0
        /// <summary>
        /// Called from interface methods which return a Task{HttpResponseMessage}
        /// </summary>
        /// <param name="requestInfo">IRequestInfo to construct the request from</param>
        /// <returns>Task containing the result of the request</returns>
        public virtual async Task <HttpResponseMessage> RequestWithResponseMessageAsync(IRequestInfo requestInfo)
        {
            // It's the user's responsibility to dispose this
            var response = await this.SendRequestAsync(requestInfo, readBody : false).ConfigureAwait(false);

            return(response);
        }
Ejemplo n.º 28
0
        private static void ProcessError(IRequestInfo info)
        {
            // pop-up the error messages if a debugger is attached or an environment variable is set
            var popUpErrors = Debugger.IsAttached || !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("DEBUG_BLOOM"));

            var post = info.GetPostDataWhenFormEncoded();

            // log the error message
            var errorMsg = post["message"] + Environment.NewLine + "File: " + post["url"].FromLocalhost()
                + Environment.NewLine + "Line: " + post["line"] + " Column: " + post["column"] + Environment.NewLine;

            Logger.WriteMinorEvent(errorMsg);
            Console.Out.WriteLine(errorMsg);

            if (popUpErrors)
                Shell.DisplayProblemToUser(errorMsg);
        }
Ejemplo n.º 29
0
        private void GetStoreBooks(IRequestInfo info)
        {
            //enhance: it will eventually work better to do sorting client-side, according to user's current prefs
            var reply = new StringBuilder();
            var list = new List<BookCollection>();
            list.AddRange(_sourceCollectionsesList.GetSourceCollections());

            list.Sort(CompareBookCollections);

            foreach (BookCollection collection in list)
            {
                reply.AppendFormat("<li class='collectionGroup'><h2>{0}</h2><ul class='collection'>", collection.Name);
                reply.Append(GetBookListItems(collection.GetBookInfos()));
                reply.AppendFormat(@"</ul></li>");
            }
            info.WriteCompleteOutput(reply.ToString());
        }
Ejemplo n.º 30
0
 private static void ReplyWithFileContentAndType(IRequestInfo info, string path)
 {
     info.ContentType = GetContentType(Path.GetExtension(path));
     info.ReplyWithFileContent(path);
 }
Ejemplo n.º 31
0
 public Repository(IRequestInfo <TDbContext> requestInfo) => this.RequestInfo = requestInfo;
Ejemplo n.º 32
0
        private bool CheckForSampleTextChanges(IRequestInfo info)
        {
            lock (SyncObj)
            {
                if (_sampleTextsWatcher == null)
                {
                    var path = Path.Combine(Path.GetDirectoryName(CurrentCollectionSettings.SettingsFilePath), "Sample Texts");
                    if (!Directory.Exists(path))
                        Directory.CreateDirectory(path);

                    _sampleTextsWatcher = new FileSystemWatcher { Path = path };
                    _sampleTextsWatcher.Created += SampleTextsOnChange;
                    _sampleTextsWatcher.Changed += SampleTextsOnChange;
                    _sampleTextsWatcher.Renamed += SampleTextsOnChange;
                    _sampleTextsWatcher.Deleted += SampleTextsOnChange;
                    _sampleTextsWatcher.EnableRaisingEvents = true;
                }
            }

            lock (_sampleTextsWatcher)
            {
                var hasChanged = _sampleTextsChanged;

                // Reset the changed flag.
                // NOTE: we are only resetting the flag if it was "true" when we checked in case the FileSystemWatcher detects a change
                // after we check the flag but we reset it to false before we check again.
                if (hasChanged)
                    _sampleTextsChanged = false;

                info.ContentType = "text/plain";
                info.WriteCompleteOutput(hasChanged ? "yes" : "no");

                return true;
            }
        }
Ejemplo n.º 33
0
 private Task Callback(IServiceBusMessage message, IRequestInfo requestInfo) => Task.CompletedTask;
Ejemplo n.º 34
0
        private bool ProcessAnyFileContent(IRequestInfo info, string localPath)
        {
            string modPath = localPath;
            string path = null;
            // When JavaScript inserts our path into the html it replaces the three magic html characters with these substitutes.
            // We need to convert back in order to match our key. Then, reverse the change we made to deal with quotation marks.
            string tempPath = UnescapeUrlQuotes(modPath.Replace("&lt;", "<").Replace("&gt;", ">").Replace("&amp;", "&"));
            if (RobustFile.Exists(tempPath))
                modPath = tempPath;
            try
            {
                if (localPath.Contains("favicon.ico")) //need something to pacify Chrome
                    path = FileLocator.GetFileDistributedWithApplication("BloomPack.ico");

                // Is this request the full path to an image file? For most images, we just have the filename. However, in at
                // least one use case, the image we want isn't in the folder of the PDF we're looking at. That case is when
                // we are looking at a "folio", a book that gathers up other books into one big PDF. In that case, we want
                // to find the image in the correct book folder.  See AddChildBookContentsToFolio();
                var possibleFullImagePath = localPath;
                // "OriginalImages/" at the beginning means we're generating a pdf and want full images,
                // but it has nothing to do with the actual file location.
                if (localPath.StartsWith("OriginalImages/"))
                    possibleFullImagePath = localPath.Substring(15);
                if(RobustFile.Exists(possibleFullImagePath) && Path.IsPathRooted(possibleFullImagePath))
                {
                    path = possibleFullImagePath;
                }
                else
                {
                    // Surprisingly, this method will return localPath unmodified if it is a fully rooted path
                    // (like C:\... or \\localhost\C$\...) to a file that exists. So this execution path
                    // can return contents of any file that exists if the URL gives its full path...even ones that
                    // are generated temp files most certainly NOT distributed with the application.
                    path = FileLocator.GetFileDistributedWithApplication(BloomFileLocator.BrowserRoot, modPath);
                }
            }
            catch (ApplicationException)
            {
                // ignore. Assume this means that this class/method cannot serve that request, but something else may.
            }

            //There's probably a eventual way to make this problem go away,
            // but at the moment FF, looking for source maps to go with css, is
            // looking for those maps where we said the css was, which is in the actual
            // book folders. So instead redirect to our browser file folder.
            if (string.IsNullOrEmpty(path) || !RobustFile.Exists(path))
            {
                var startOfBookLayout = localPath.IndexOf("bookLayout");
                if (startOfBookLayout > 0)
                    path = BloomFileLocator.GetBrowserFile(localPath.Substring(startOfBookLayout));
                var startOfBookEdit = localPath.IndexOf("bookEdit");
                if (startOfBookEdit > 0)
                    path = BloomFileLocator.GetBrowserFile(localPath.Substring(startOfBookEdit));
            }

            if (!RobustFile.Exists(path) && localPath.StartsWith("pageChooser/") && IsImageTypeThatCanBeReturned(localPath))
            {
                // if we're in the page chooser dialog and looking for a thumbnail representing an image in a
                // template page, look for that thumbnail in the book that is the template source,
                // rather than in the folder that stores the page choose dialog HTML and code.
                var templatePath = Path.Combine(_bookSelection.CurrentSelection.FindTemplateBook().FolderPath,
                    localPath.Substring("pageChooser/".Length));
                if (RobustFile.Exists(templatePath))
                {
                    info.ReplyWithImage(templatePath);
                    return true;
                }
            }
            // Use '%25' to detect that the % in a Url encoded character (for example space encoded as %20) was encoded as %25.
            // In this example we would have %2520 in info.RawUrl and %20 in localPath instead of a space.  Note that if an
            // image has a % in the filename, like 'The other 50%', and it isn't doubly encoded, then this shouldn't be a
            // problem because we're triggering here only if the file isn't found.
            if (!RobustFile.Exists(localPath) && info.RawUrl.Contains("%25"))
            {
                // possibly doubly encoded?  decode one more time and try.  See https://silbloom.myjetbrains.com/youtrack/issue/BL-3835.
                // Some existing books have somehow acquired Url encoded coverImage data like the following:
                // <div data-book="coverImage" lang="*">
                //     The%20Moon%20and%20The%20Cap_Cover.png
                // </div>
                // This leads to data being stored doubly encoded in the program's run-time data.  The coverImage data is supposed to be
                // Html/Xml encoded (using &), not Url encoded (using %).
                path = System.Web.HttpUtility.UrlDecode(localPath);
            }
            if (!RobustFile.Exists(path) && IsImageTypeThatCanBeReturned(localPath))
            {
                // last resort...maybe we are in the process of renaming a book (BL-3345) and something mysteriously is still using
                // the old path. For example, I can't figure out what hangs on to the old path when an image is changed after
                // altering the main book title.
                var currentFolderPath = Path.Combine(_bookSelection.CurrentSelection.FolderPath, Path.GetFileName(localPath));
                if (RobustFile.Exists(currentFolderPath))
                {
                    info.ReplyWithImage(currentFolderPath);
                    return true;
                }
            }

            if (!RobustFile.Exists(path))
            {
                // On developer machines, we can lose part of path earlier.  Try one more thing.
                path = info.LocalPathWithoutQuery.Substring(7); // skip leading "/bloom/");
            }
            if (!File.Exists(path))
            {
                ReportMissingFile(localPath,path);
                return false;
            }
            info.ContentType = GetContentType(Path.GetExtension(modPath));
            info.ReplyWithFileContent(path);
            return true;
        }
Ejemplo n.º 35
0
 /// <summary>
 /// Serialize the (typed) value using the given serializer
 /// </summary>
 /// <param name="serializer">Serializer to use</param>
 /// <param name="requestInfo">RequestInfo representing the request</param>
 /// <param name="formatProvider"><see cref="IFormatProvider"/> to use if the value implements <see cref="IFormattable"/></param>
 /// <returns>Serialized value</returns>
 public abstract HttpContent SerializeValue(RequestBodySerializer serializer, IRequestInfo requestInfo, IFormatProvider formatProvider);
Ejemplo n.º 36
0
        private bool ProcessContent(IRequestInfo info, string localPath)
        {
            if (localPath.EndsWith(".css"))
            {
                return ProcessCssFile(info, localPath);
            }

            switch (localPath)
            {
                case "currentPageContent":
                    info.ContentType = "text/html";
                    info.WriteCompleteOutput(CurrentPageContent ?? "");
                    return true;
                case "toolboxContent":
                    info.ContentType = "text/html";
                    info.WriteCompleteOutput(ToolboxContent ?? "");
                    return true;
                case "availableFontNames":
                    info.ContentType = "application/json";
                    var list = new List<string>(Browser.NamesOfFontsThatBrowserCanRender());
                    list.Sort();
                    info.WriteCompleteOutput(JsonConvert.SerializeObject(new{fonts = list}));
                    return true;
                case "authorMode":
                    info.ContentType = "text/plain";
                    info.WriteCompleteOutput(AuthorMode ? "true" : "false");
                    return true;
                case "topics":
                    return GetTopicList(info);
            }
            return ProcessAnyFileContent(info, localPath);
        }
Ejemplo n.º 37
0
 public new Uri ConstructUri(string basePath, string relativePath, IRequestInfo requestInfo)
 {
     return(base.ConstructUri(basePath, relativePath, requestInfo));
 }
Ejemplo n.º 38
0
        private bool ProcessCssFile(IRequestInfo info, string localPath)
        {
            // BL-2219: "OriginalImages" means we're generating a pdf and want full images,
            // but it has nothing to do with css files and defeats the following 'if'
            localPath = localPath.Replace("OriginalImages/", "");
            // is this request the full path to a real file?
            if (RobustFile.Exists(localPath) && Path.IsPathRooted(localPath))
            {
                // Typically this will be files in the book or collection directory, since the browser
                // is supplying the path.

                // currently this only applies to settingsCollectionStyles.css, and customCollectionStyles.css
                var cssFile = Path.GetFileName(localPath);
                if ((cssFile == "settingsCollectionStyles.css") || (cssFile == "customCollectionStyles.css"))
                {
                    info.ContentType = "text/css";
                    info.ReplyWithFileContent(localPath);
                    return true;
                }
            }

            // if not a full path, try to find the correct file
            var fileName = Path.GetFileName(localPath);

            // try to find the css file in the xmatter and templates
            if (_fileLocator == null)
            {
                _fileLocator = Program.OptimizedFileLocator;
            }
            var path = _fileLocator.LocateFile(fileName);

            // if still not found, and localPath is an actual file path, use it
            if (string.IsNullOrEmpty(path) && RobustFile.Exists(localPath)) path = localPath;

            if (string.IsNullOrEmpty(path))
            {
                // it's just possible we need to add BloomBrowserUI to the path (in the case of the AddPage dialog)
                var lastTry = FileLocator.GetFileDistributedWithApplication(true, BloomFileLocator.BrowserRoot, localPath);
                if(RobustFile.Exists(lastTry)) path = lastTry;
            }

            // return false if the file was not found
            if (string.IsNullOrEmpty(path)) return false;

            info.ContentType = "text/css";
            info.ReplyWithFileContent(path);
            return true;
        }
Ejemplo n.º 39
0
 public new HttpContent ConstructContent(IRequestInfo requestInfo)
 {
     return(base.ConstructContent(requestInfo));
 }
Ejemplo n.º 40
0
 private bool ProcessDirectoryWatcher(IRequestInfo info)
 {
     // thread synchronization is done in CheckForSampleTextChanges.
     var dirName = info.GetPostDataWhenFormEncoded()["dir"];
     if (dirName == "Sample Texts")
     {
         if (CheckForSampleTextChanges(info))
             return true;
     }
     return false;
 }
Ejemplo n.º 41
0
 public new Task <HttpResponseMessage> SendRequestAsync(IRequestInfo requestInfo, bool readBody)
 {
     return(base.SendRequestAsync(requestInfo, readBody));
 }
Ejemplo n.º 42
0
 private bool ProcessI18N(string localPath, IRequestInfo info)
 {
     lock (I18NLock)
     {
         return I18NHandler.HandleRequest(localPath, info, CurrentCollectionSettings);
     }
 }
Ejemplo n.º 43
0
        private void GetLibraryBooks(IRequestInfo info)
        {
            var books = _booksInProjectLibrary.GetBookInfos();

            info.WriteCompleteOutput(GetBookListItems(books));
        }
Ejemplo n.º 44
0
 public UnitOfWork(IRequestInfo requestInfo)
 {
     this._requestInfo = requestInfo;
 }
 public AuditableRepository(IRequestInfo <TDbContext> requestInfo)
     : base(requestInfo)
 {
 }
Ejemplo n.º 46
0
 public new Uri ConstructUri(string relativePath, IRequestInfo requestInfo)
 {
     return base.ConstructUri(relativePath, requestInfo);
 }
Ejemplo n.º 47
0
 /// <summary>
 /// Initialises a new instance of the <see cref="RequestQueryParamSerializerInfo"/> structure
 /// </summary>
 /// <param name="requestInfo">Information about the request</param>
 /// <param name="format">Format string specified using <see cref="QueryAttribute.Format"/></param>
 public RequestQueryParamSerializerInfo(IRequestInfo requestInfo, string format)
 {
     this.RequestInfo = requestInfo;
     this.Format      = format;
 }
Ejemplo n.º 48
0
 public new string SubstitutePathParameters(IRequestInfo requestInfo)
 {
     return base.SubstitutePathParameters(requestInfo);
 }
Ejemplo n.º 49
0
        /// <summary>
        /// Build up a query string from the initial query string, raw query parameter, and any query params (which need to be combined)
        /// </summary>
        /// <param name="initialQueryString">Initial query string, present from the URI the user specified in the Get/etc parameter</param>
        /// <param name="rawQueryParameters">The raw query parameters, if any</param>
        /// <param name="queryParams">The query parameters which need serializing (or an empty collection)</param>
        /// <param name="queryProperties">The query parameters from properties which need serialializing (or an empty collection)</param>
        /// <param name="requestInfo">RequestInfo representing the request</param>
        /// <returns>Query params combined into a query string</returns>
        protected virtual string BuildQueryParam(
            string initialQueryString,
            IEnumerable <RawQueryParameterInfo> rawQueryParameters,
            IEnumerable <QueryParameterInfo> queryParams,
            IEnumerable <QueryParameterInfo> queryProperties,
            IRequestInfo requestInfo)
        {
            var serializedQueryParams        = queryParams.SelectMany(x => this.SerializeQueryParameter(x, requestInfo));
            var serializedQueryProperties    = queryProperties.SelectMany(x => this.SerializeQueryParameter(x, requestInfo));
            var serializedRawQueryParameters = rawQueryParameters.Select(x => x.SerializeToString(this.FormatProvider));

            if (this.QueryStringBuilder != null)
            {
                var info = new QueryStringBuilderInfo(initialQueryString, serializedRawQueryParameters, serializedQueryParams, serializedQueryProperties, requestInfo, this.FormatProvider);
                return(this.QueryStringBuilder.Build(info));
            }

            // Implementation copied from FormUrlEncodedContent

            var sb = new StringBuilder();

            void AppendQueryString(string query)
            {
                if (sb.Length > 0)
                {
                    sb.Append('&');
                }
                sb.Append(query);
            }

            string Encode(string?data)
            {
                if (string.IsNullOrEmpty(data))
                {
                    return(string.Empty);
                }
                return(Uri.EscapeDataString(data).Replace("%20", "+"));
            }

            if (!string.IsNullOrEmpty(initialQueryString))
            {
                AppendQueryString(initialQueryString.Replace("%20", "+"));
            }

            foreach (string?serializedRawQueryParameter in serializedRawQueryParameters)
            {
                AppendQueryString(serializedRawQueryParameter);
            }

            foreach (var kvp in serializedQueryParams.Concat(serializedQueryProperties))
            {
                if (kvp.Key == null)
                {
                    AppendQueryString(Encode(kvp.Value));
                }
                else
                {
                    AppendQueryString(Encode(this.ToStringHelper(kvp.Key)));
                    sb.Append('=');
                    sb.Append(Encode(kvp.Value));
                }
            }

            return(sb.ToString());
        }
Ejemplo n.º 50
0
 public new HttpContent ConstructContent(IRequestInfo requestInfo)
 {
     return base.ConstructContent(requestInfo);
 }
Ejemplo n.º 51
0
        /// <summary>
        /// Serializes the value of a query parameter, using an appropriate method
        /// </summary>
        /// <param name="queryParameter">Query parameter to serialize</param>
        /// <param name="requestInfo">RequestInfo representing the request</param>
        /// <returns>Serialized value</returns>
        protected virtual IEnumerable <KeyValuePair <string, string?> > SerializeQueryParameter(QueryParameterInfo queryParameter, IRequestInfo requestInfo)
        {
            switch (queryParameter.SerializationMethod)
            {
            case QuerySerializationMethod.ToString:
                return(queryParameter.SerializeToString(this.FormatProvider));

            case QuerySerializationMethod.Serialized:
                if (this.RequestQueryParamSerializer == null)
                {
                    throw new InvalidOperationException("Cannot serialize query parameter when RequestQueryParamSerializer is null. Please set RequestQueryParamSerializer");
                }
                var result = queryParameter.SerializeValue(this.RequestQueryParamSerializer, requestInfo, this.FormatProvider);
                return(result ?? Enumerable.Empty <KeyValuePair <string, string?> >());

            default:
                throw new InvalidOperationException("Should never get here");
            }
        }
Ejemplo n.º 52
0
 public new void ApplyHeaders(IRequestInfo requestInfo, HttpRequestMessage requestMessage)
 {
     base.ApplyHeaders(requestInfo, requestMessage);
 }
Ejemplo n.º 53
0
 /// <summary>
 /// Calls this.ResponseDeserializer.ReadAndDeserializeAsync, after checking it's not null
 /// </summary>
 /// <typeparam name="T">Type of object to deserialize into</typeparam>
 /// <param name="content">String content read from the response</param>
 /// <param name="response">Response to deserialize from</param>
 /// <param name="requestInfo">RequestInfo representing the request</param>
 /// <returns>A task containing the deserialized response</returns>
 protected virtual T Deserialize <T>(string?content, HttpResponseMessage response, IRequestInfo requestInfo)
 {
     if (this.ResponseDeserializer == null)
     {
         throw new InvalidOperationException("Cannot deserialize a response when ResponseDeserializer is null. Please set ResponseDeserializer");
     }
     return(this.ResponseDeserializer.Deserialize <T>(content, response, new ResponseDeserializerInfo(requestInfo)));
 }
Ejemplo n.º 54
0
 public new Task<HttpResponseMessage> SendRequestAsync(IRequestInfo requestInfo)
 {
     return base.SendRequestAsync(requestInfo);
 }
Ejemplo n.º 55
0
 /// <summary>
 /// 通讯中断时调用此函数
 /// </summary>
 /// <param name="info"></param>
 public abstract void CommunicateInterrupt(IRequestInfo info);
Ejemplo n.º 56
0
 public Task DispatchCommand <TCommand>(TCommand message, IRequestInfo requestInfo) where TCommand : ICommand
 {
     _serviceBusMessagePublisher.PublishCommand(message, requestInfo);
     _logger.LogInformation($"{message.GetType().Name} dispatched for user: " + requestInfo.UserId);
     return(Task.CompletedTask);
 }
Ejemplo n.º 57
0
 private void GetLibraryBooks(IRequestInfo info)
 {
     var books = _booksInProjectLibrary.GetBookInfos();
     info.WriteCompleteOutput(GetBookListItems(books));
 }
Ejemplo n.º 58
0
        // Every path should return false or send a response.
        // Otherwise we can get a timeout error as the browser waits for a response.
        //
        // NOTE: this method gets called on different threads!
        public bool ProcessRequest(IRequestInfo info, string localPath)
        {
            var localPathLc = localPath.ToLowerInvariant();

            if (localPathLc.StartsWith("api/", StringComparison.InvariantCulture))
            {
                var endpointPath = localPath.Substring(3).ToLowerInvariant().Trim(new char[] { '/' });
                foreach (var pair in _endpointRegistrations.Where(pair =>
                                                                  Regex.Match(endpointPath,
                                                                              "^" + //must match the beginning
                                                                              pair.Key.ToLower()
                                                                              ).Success))
                {
                    var endpointRegistration = pair.Value;
                    if (endpointRegistration.RequiresSync)
                    {
                        // A single synchronization object won't do, because when processing a request to create a thumbnail or update a preview,
                        // we have to load the HTML page the thumbnail is based on, or other HTML pages (like one used to figure what's
                        // visible in a preview). If the page content somehow includes
                        // an api request (api/branding/image is one example), that request will deadlock if the
                        // api/pageTemplateThumbnail request already has the main lock.
                        // Another case is the Bloom Reader preview, where the whole UI is rebuilt at the same time as the preview.
                        // This leads to multiple api requests racing with the preview one, and it was possible for all
                        // the server threads to be processing these and waiting for SyncObject while the updatePreview
                        // request held the lock...and the request for the page that would free the lock was sitting in
                        // the queue, waiting for a thread.
                        // To the best of my knowledge, there's no shared data between the thumbnailing and preview processes and any
                        // other api requests, so it seems safe to have one lock that prevents working on multiple
                        // thumbnails/previews at the same time, and one that prevents working on other api requests at the same time.
                        var syncOn = SyncObj;
                        if (localPathLc.StartsWith("api/pagetemplatethumbnail", StringComparison.InvariantCulture) ||
                            localPathLc == "api/publish/android/thumbnail" ||
                            localPathLc == "api/publish/android/updatepreview")
                        {
                            syncOn = ThumbnailsAndPreviewsSyncObj;
                        }
                        else if (localPathLc.StartsWith("api/i18n/"))
                        {
                            syncOn = I18NLock;
                        }

                        // Basically what lock(syncObj) {} is syntactic sugar for (see its documentation),
                        // but we wrap RegisterThreadBlocking/Unblocked around acquiring the lock.
                        // We need the more complicated structure because we would like RegisterThreadUnblocked
                        // to be called immediately after acquiring the lock (notably, before Handle() is called),
                        // but we also want to handle the case where Monitor.Enter throws an exception.
                        bool lockAcquired = false;
                        try
                        {
                            // Try to acquire lock
                            BloomServer._theOneInstance.RegisterThreadBlocking();
                            try
                            {
                                // Blocks until it either succeeds (lockAcquired will then always be true) or throws (lockAcquired will stay false)
                                Monitor.Enter(syncOn, ref lockAcquired);
                            }
                            finally
                            {
                                BloomServer._theOneInstance.RegisterThreadUnblocked();
                            }

                            // Lock has been acquired.
                            ApiRequest.Handle(endpointRegistration, info, CurrentCollectionSettings,
                                              _bookSelection.CurrentSelection);

                            // Even if ApiRequest.Handle() fails, return true to indicate that the request was processed and there
                            // is no further need for the caller to continue trying to process the request as a filename.
                            // See https://issues.bloomlibrary.org/youtrack/issue/BL-6763.
                            return(true);
                        }
                        finally
                        {
                            if (lockAcquired)
                            {
                                Monitor.Exit(syncOn);
                            }
                        }
                    }
                    else
                    {
                        // Up to api's that request no sync to do things right!
                        ApiRequest.Handle(endpointRegistration, info, CurrentCollectionSettings, _bookSelection.CurrentSelection);
                        // Even if ApiRequest.Handle() fails, return true to indicate that the request was processed and there
                        // is no further need for the caller to continue trying to process the request as a filename.
                        // See https://issues.bloomlibrary.org/youtrack/issue/BL-6763.
                        return(true);
                    }
                }
            }
            return(false);
        }
Ejemplo n.º 59
0
        /// <summary>
        /// This is designed to be easily unit testable by not taking actual HttpContext, but doing everything through this IRequestInfo object
        /// </summary>
        /// <param name="info"></param>
        public void MakeReply(IRequestInfo info)
        {
            var r = info.LocalPathWithoutQuery.Replace("/bloom/", "");
            r = r.Replace("library/", "");
            if (r.Contains("libraryContents"))
            {
                GetLibraryBooks(info);
            }
            else if (r == "libraryName")
            {
                info.WriteCompleteOutput(_collectionSettings.CollectionName + " Library");
            }
            else if (r.Contains("SourceCollectionsList"))
            {
                GetStoreBooks(info);
            }
            else if(r.StartsWith("thumbnails/"))
            {
                r = r.Replace("thumbnails/", "");
                r = r.Replace("%5C", "/");
                r = r.Replace("%20", " ");
                if (File.Exists(r))
                {
                    info.ReplyWithImage(r);
                }
            }
            else if (r.EndsWith(".png"))
            {
                info.ContentType = "image/png";

                r = r.Replace("thumbnail", "");
                //if (r.Contains("thumb"))
                {
                    if (File.Exists(r))
                    {
                        info.ReplyWithImage(r);
                    }
                    else
                    {
                        var imgPath = FileLocator.GetFileDistributedWithApplication("BloomBrowserUI", "book.png");
                        info.ReplyWithImage(imgPath);
                        //book.GetThumbNailOfBookCoverAsync(book.Type != Book.Book.BookType.Publication,image => RefreshOneThumbnail(book, image));
                    }
                }
            //				else
            //				{
            //					var imgPath = FileLocator.GetFileDistributedWithApplication("root", "ui", "book.png");
            //					info.ReplyWithImage(imgPath);
            //				}
            }
            else
            {
                string path = FileLocator.GetFileDistributedWithApplication("BloomBrowserUI", r);

                //request.QueryString.GetValues()
                info.WriteCompleteOutput(File.ReadAllText(path));
            }
        }
Ejemplo n.º 60
0
 protected override Task <HttpResponseMessage> SendRequestAsync(IRequestInfo requestInfo, bool readBody)
 {
     this.RequestInfo = requestInfo;
     return(this.ResponseMessage);
 }