diff options
author | Jeroen Walter <jeroen@enormkansloos.nl> | 2012-08-25 17:34:26 +0200 |
---|---|---|
committer | Jeroen Walter <jeroen@enormkansloos.nl> | 2012-08-25 17:34:26 +0200 |
commit | 02ceefe2ea914b202c7ad6819940d94690b0cd6c (patch) | |
tree | 5142cefddace419486bc42870c5f7f25900d9b83 | |
parent | 5b7ff96e229af25255fdf600069dedd408dbe45c (diff) | |
download | ComicRackWeb-02ceefe2ea914b202c7ad6819940d94690b0cd6c.zip ComicRackWeb-02ceefe2ea914b202c7ad6819940d94690b0cd6c.tar.gz ComicRackWeb-02ceefe2ea914b202c7ad6819940d94690b0cd6c.tar.bz2 |
- moved original Web Viewer settings to BCR settings.xml
- BCRSettings is now a singleton
- improved error handling
-rw-r--r-- | ComicRackWebViewer/API.cs | 8 | ||||
-rw-r--r-- | ComicRackWebViewer/BCRSettings.cs | 168 | ||||
-rw-r--r-- | ComicRackWebViewer/Bootstrapper.cs | 74 | ||||
-rw-r--r-- | ComicRackWebViewer/ComicRackWebViewer.csproj | 4 | ||||
-rw-r--r-- | ComicRackWebViewer/Entities.cs | 2 | ||||
-rw-r--r-- | ComicRackWebViewer/Modules/BCRModule.cs | 377 | ||||
-rw-r--r-- | ComicRackWebViewer/Plugin.cs | 44 | ||||
-rw-r--r-- | ComicRackWebViewer/Program.py | 3 | ||||
-rw-r--r-- | ComicRackWebViewer/Settings.cs | 72 | ||||
-rw-r--r-- | ComicRackWebViewer/WebServicePanel.xaml.cs | 11 |
10 files changed, 473 insertions, 290 deletions
diff --git a/ComicRackWebViewer/API.cs b/ComicRackWebViewer/API.cs index ec31013..ff37117 100644 --- a/ComicRackWebViewer/API.cs +++ b/ComicRackWebViewer/API.cs @@ -150,12 +150,12 @@ namespace ComicRackWebViewer return (Image)bmp; } - public static Response GetPageImage(Guid id, int page, int width, int height, BCRSettings settings, IResponseFormatter response) + public static Response GetPageImage(Guid id, int page, int width, int height, IResponseFormatter response) { string filename = string.Format("{0}-p{1}-w{2}-h{3}.jpg", id, page, width, height); try { - MemoryStream stream = settings.LoadFromCache(filename, !(width == -1 && height == -1)); + MemoryStream stream = BCRSettingsStore.Instance.LoadFromCache(filename, !(width == -1 && height == -1)); if (stream == null) return response.FromStream(stream, MimeTypes.GetMimeType(".jpg")); } @@ -174,7 +174,7 @@ namespace ComicRackWebViewer { // Return original image. MemoryStream mem = new MemoryStream(bytes); - settings.SaveToCache(filename, mem, false); + BCRSettingsStore.Instance.SaveToCache(filename, mem, false); return response.FromStream(mem, MimeTypes.GetMimeType(".jpg")); } @@ -199,7 +199,7 @@ namespace ComicRackWebViewer MemoryStream stream = GetBytesFromImage(thumbnail); thumbnail.Dispose(); - settings.SaveToCache(filename, stream, true); + BCRSettingsStore.Instance.SaveToCache(filename, stream, true); return response.FromStream(stream, MimeTypes.GetMimeType(".jpg")); } diff --git a/ComicRackWebViewer/BCRSettings.cs b/ComicRackWebViewer/BCRSettings.cs index 047070b..02cb7c6 100644 --- a/ComicRackWebViewer/BCRSettings.cs +++ b/ComicRackWebViewer/BCRSettings.cs @@ -10,9 +10,6 @@ namespace ComicRackWebViewer { public class BCRSettings { - private const string DIRECTORY = "ComicRack BCR"; - private const string SETTINGS_FILE = "settings.xml"; - public bool open_current_comic_at_launch { get; set; } public bool open_next_comic { get; set; } public int page_fit_mode { get; set; } // 1: Fit width, 2: Full page @@ -25,20 +22,11 @@ namespace ComicRackWebViewer public int cache_size { get; set; } public bool nancy_request_tracing { get; set; } public string nancy_diagnostics_password { get; set; } + public int webserver_port { get; set; } + public string webserver_externalip { get; set; } - - private static string folder; - private static string cache_folder; - private static string thumbnail_folder; - private static string filepath; - private static bool initialized = false; - - private static int max_image_dimension = 3072; // max ipad image size is 4096x3072 ? - public BCRSettings() - { - Init(); - + { open_current_comic_at_launch = true; open_next_comic = true; page_fit_mode = 1; @@ -52,59 +40,134 @@ namespace ComicRackWebViewer nancy_request_tracing = true; nancy_diagnostics_password = "diagnostics"; + + webserver_port = 8080; + webserver_externalip = ""; } + } + + public sealed class BCRSettingsStore : BCRSettings + { + private const string DIRECTORY = "ComicRack BCR"; + private const string SETTINGS_FILE = "settings.xml"; + + private static string folder; + private static string cache_folder; + private static string thumbnail_folder; + private static string filepath; + + //private static int max_image_dimension = 3072; // max ipad image size is 4096x3072 ? - private static void Init() + private static BCRSettingsStore instance = new BCRSettingsStore(); + + public static BCRSettingsStore Instance { - if (!initialized) + get { return instance; } + } + + private BCRSettingsStore() + { + folder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), DIRECTORY); + if (!Directory.Exists(folder)) { - initialized = true; - folder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), DIRECTORY); - if (!Directory.Exists(folder)) - { - Directory.CreateDirectory(folder); - } - - cache_folder = folder + "\\cache\\"; - if (!Directory.Exists(cache_folder)) - { - Directory.CreateDirectory(cache_folder); - } - - thumbnail_folder = folder + "\\cache\\thumbnails\\"; - if (!Directory.Exists(thumbnail_folder)) - { - Directory.CreateDirectory(thumbnail_folder); - } - - - filepath = folder + "\\" + SETTINGS_FILE; - - if (!File.Exists(filepath)) - { - BCRSettings settings = new BCRSettings(); - settings.Save(); - } + Directory.CreateDirectory(folder); } + + cache_folder = folder + "\\cache\\"; + if (!Directory.Exists(cache_folder)) + { + Directory.CreateDirectory(cache_folder); + } + + thumbnail_folder = folder + "\\cache\\thumbnails\\"; + if (!Directory.Exists(thumbnail_folder)) + { + Directory.CreateDirectory(thumbnail_folder); + } + + + filepath = folder + "\\" + SETTINGS_FILE; + + if (File.Exists(filepath)) + { + Load(); + } + + // save current settings once, so new entries will be saved in the xml file. + Save(); + } + + + // this can undoubtely be done simpler, but I don't enough C#.... + public void UpdateFrom(BCRSettings data) + { + open_current_comic_at_launch = data.open_current_comic_at_launch; + open_next_comic = data.open_next_comic; + page_fit_mode = data.page_fit_mode; + zoom_on_tap = data.zoom_on_tap; + toggle_paging_bar = data.toggle_paging_bar; + use_page_turn_drag = data.use_page_turn_drag; + page_turn_drag_threshold = data.page_turn_drag_threshold; + use_page_change_area = data.use_page_change_area; + page_change_area_width = data.page_change_area_width; + cache_size = data.cache_size; + + nancy_request_tracing = data.nancy_request_tracing; + nancy_diagnostics_password = data.nancy_diagnostics_password; + + webserver_port = data.webserver_port; + webserver_externalip = data.webserver_externalip; + Save(); } - public static BCRSettings Load() + + public BCRSettings GetData() { - Init(); + BCRSettings data = new BCRSettings(); + data.open_current_comic_at_launch = open_current_comic_at_launch; + data.open_next_comic = open_next_comic; + data.page_fit_mode = page_fit_mode; + data.zoom_on_tap = zoom_on_tap; + data.toggle_paging_bar = toggle_paging_bar; + data.use_page_turn_drag = use_page_turn_drag; + data.page_turn_drag_threshold = page_turn_drag_threshold; + data.use_page_change_area = use_page_change_area; + data.page_change_area_width = page_change_area_width; + data.cache_size = cache_size; + data.nancy_request_tracing = nancy_request_tracing; + data.nancy_diagnostics_password = nancy_diagnostics_password; + + data.webserver_port = webserver_port; + data.webserver_externalip = webserver_externalip; + + return data; + } + + + public void Load() + { XmlSerializer deserializer = new XmlSerializer(typeof(BCRSettings)); TextReader textReader = new StreamReader(filepath); - BCRSettings settings = (BCRSettings)deserializer.Deserialize(textReader); + try + { + BCRSettings settings = (BCRSettings)deserializer.Deserialize(textReader); + UpdateFrom(settings); + } + catch(Exception e) + { + // ignore, use default values. + } + textReader.Close(); - return settings; } public void Save() { - XmlSerializer serializer = new XmlSerializer(this.GetType()); + XmlSerializer serializer = new XmlSerializer(typeof(BCRSettings)); StreamWriter writer = new StreamWriter(filepath); - serializer.Serialize(writer.BaseStream, this); + serializer.Serialize(writer.BaseStream, GetData()); writer.Close(); } @@ -181,10 +244,5 @@ namespace ComicRackWebViewer } } } - - - } - - } diff --git a/ComicRackWebViewer/Bootstrapper.cs b/ComicRackWebViewer/Bootstrapper.cs index fb11990..582d916 100644 --- a/ComicRackWebViewer/Bootstrapper.cs +++ b/ComicRackWebViewer/Bootstrapper.cs @@ -9,32 +9,44 @@ using Nancy.ViewEngines.Razor; using Nancy.Conventions;
using Nancy.Diagnostics;
using TinyIoC;
-
+using Nancy.ErrorHandling;
+using Nancy.Extensions;
namespace ComicRackWebViewer
{
- public class Bootstrapper : DefaultNancyBootstrapper
- {
- private static BCRSettings settings = null;
+ /*
+ public class LoggingErrorHandler : IErrorHandler
+ {
+ public bool HandlesStatusCode(HttpStatusCode statusCode, NancyContext context)
+ {
+ return true;//statusCode == HttpStatusCode.InternalServerError;
+ }
+
+ public void Handle(HttpStatusCode statusCode, NancyContext context)
+ {
- private BCRSettings getSettings()
- {
- if (settings == null)
- {
- settings = BCRSettings.Load();
- // save current settings once, so new entries will be saved in the xml file.
- settings.Save();
- }
+ object errorObject;
+ context.Items.TryGetValue(NancyEngine.ERROR_EXCEPTION, out errorObject);
+ var error = errorObject as Exception;
- return settings;
- }
+
+
+ }
+ }
+ */
+
+ public class Bootstrapper : DefaultNancyBootstrapper
+ {
protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines)
{
base.ApplicationStartup(container, pipelines);
- // Increase size of JSON responses as 100K is way too small for a large comic collection.
+ // Increase size of JSON responses as 100K is way too small for a large comic collection. Make it 10M.
+ // Also, for some reason I don't get InvalidOperationException ("Nancy.Json.JsonSettings.MaxJsonLength exceeded")
+ // Instead Nancy generates a response with status OK and content length 0.
Nancy.Json.JsonSettings.MaxJsonLength = 10000000;
+ // Case sensitivity is buggy in Nancy, so disable it. Or maybe I should generate/parse GUIDs correctly......
StaticConfiguration.CaseSensitive = false;
#if DEBUG
@@ -53,34 +65,12 @@ namespace ComicRackWebViewer return string.Concat("original/Views/", viewName);
});
- StaticConfiguration.EnableRequestTracing = getSettings().nancy_request_tracing;
+ StaticConfiguration.EnableRequestTracing = BCRSettingsStore.Instance.nancy_request_tracing;
- if (getSettings().nancy_diagnostics_password == "")
+ if (BCRSettingsStore.Instance.nancy_diagnostics_password == "")
DiagnosticsHook.Disable(pipelines);
-
- //pipelines.OnError += ExceptionHandler;
- }
-
-/*
- private Response ExceptionHandler(NancyContext ctx, Exception ex)
- {
- MessageBox.Show(ex.ToString());
- return HttpStatusCode.InternalServerError;
- }
-*/
-
- protected override IEnumerable<ModuleRegistration> Modules
- {
- get
- {
- yield return CreateRegistration<IndexModule>();
- yield return CreateRegistration<PublishersModule>();
- yield return CreateRegistration<SeriesModule>();
- yield return CreateRegistration<ComicsModule>();
- yield return CreateRegistration<ListModule>();
- yield return CreateRegistration<BCRModule>();
- }
}
+
protected override void ConfigureApplicationContainer(TinyIoCContainer container)
{
@@ -89,11 +79,13 @@ namespace ComicRackWebViewer container.AutoRegister(new List<Assembly>() { typeof(Bootstrapper).Assembly, typeof(RazorViewEngine).Assembly });
}
+ /*
private ModuleRegistration CreateRegistration<Tmodule>()
{
Type t = typeof(Tmodule);
return new ModuleRegistration(t, this.GetModuleKeyGenerator().GetKeyForModuleType(t));
}
+ */
protected override void ConfigureConventions(NancyConventions conventions)
{
@@ -109,7 +101,7 @@ namespace ComicRackWebViewer protected override DiagnosticsConfiguration DiagnosticsConfiguration
{
- get { return new DiagnosticsConfiguration { Password = getSettings().nancy_diagnostics_password }; }
+ get { return new DiagnosticsConfiguration { Password = BCRSettingsStore.Instance.nancy_diagnostics_password }; }
}
}
diff --git a/ComicRackWebViewer/ComicRackWebViewer.csproj b/ComicRackWebViewer/ComicRackWebViewer.csproj index 2253d23..7b1b95d 100644 --- a/ComicRackWebViewer/ComicRackWebViewer.csproj +++ b/ComicRackWebViewer/ComicRackWebViewer.csproj @@ -76,6 +76,9 @@ <Reference Include="ICSharpCode.SharpZipLib">
<HintPath>C:\Program Files\ComicRack\ICSharpCode.SharpZipLib.dll</HintPath>
</Reference>
+ <Reference Include="Linq2Rest">
+ <HintPath>..\packages\Linq2Rest.2.4.1.0\lib\Net40\Linq2Rest.dll</HintPath>
+ </Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Nancy, Version=0.11.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
@@ -128,7 +131,6 @@ <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Modules\PublishersModule.cs" />
<Compile Include="Modules\SeriesModule.cs" />
- <Compile Include="Settings.cs" />
<Compile Include="WebServicePanel.xaml.cs">
<DependentUpon>WebServicePanel.xaml</DependentUpon>
</Compile>
diff --git a/ComicRackWebViewer/Entities.cs b/ComicRackWebViewer/Entities.cs index b5bbf75..28d448b 100644 --- a/ComicRackWebViewer/Entities.cs +++ b/ComicRackWebViewer/Entities.cs @@ -8,7 +8,7 @@ using cYo.Projects.ComicRack.Engine.Database; namespace ComicRackWebViewer
{
/*
- public class BCRSettings {
+ public class BCRSettingsStore {
public bool open_current_comic_at_launch { get; set; }
public bool open_next_comic { get; set; }
public int page_fit_mode { get; set; }
diff --git a/ComicRackWebViewer/Modules/BCRModule.cs b/ComicRackWebViewer/Modules/BCRModule.cs index 695d00b..4caa771 100644 --- a/ComicRackWebViewer/Modules/BCRModule.cs +++ b/ComicRackWebViewer/Modules/BCRModule.cs @@ -17,17 +17,88 @@ using Nancy.OData; using Nancy.ModelBinding; using Nancy.Responses; +/* +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Linq; +using Linq2Rest.Parser; + +namespace Nancy.OData +{ + public static class ODataExtensions + { + private const string ODATA_URI_KEY = "OData_Uri"; + + private static NameValueCollection MyParseUriOptions(NancyContext context) + { + object item; + if (context.Items.TryGetValue(ODATA_URI_KEY, out item)) + { + return item as NameValueCollection; + } + NameValueCollection nv = new NameValueCollection(); + context.Items.Add(ODATA_URI_KEY, nv); + var queryString = context.Request.Url.Query; + if (string.IsNullOrWhiteSpace(queryString)) + { + return nv; + } + if (!queryString.StartsWith("?")) + { + throw new InvalidOperationException("Invalid OData query string " + queryString); + } + var parameters = queryString.Substring(1).Split('&', '='); + if (parameters.Length % 2 != 0) + { + throw new InvalidOperationException("Invalid OData query string " + queryString); + } + for (int i = 0; i < parameters.Length; i += 2) + { + nv.Add(parameters[i], Uri.UnescapeDataString(parameters[i + 1])); + } + return nv; + } + public static IEnumerable<object> MyApplyODataUriFilter<T>(this NancyContext context, IEnumerable<T> modelItems) + { + var nv = MyParseUriOptions(context); + + var parser = new ParameterParser<T>(); + var filter = parser.Parse(nv); + return filter.Filter(modelItems); + } + + public static Response MyAsOData<T>(this IResponseFormatter formatter, IEnumerable<T> modelItems, HttpStatusCode code = HttpStatusCode.OK) + { + bool isJson = formatter.Context.Request.Headers.Accept.Select(x => x.Item1).Where(x => x.StartsWith("application/json", StringComparison.InvariantCultureIgnoreCase)).Any(); + + var nv = MyParseUriOptions(formatter.Context); + string value = nv.Get("$format"); + if (string.Compare(value, "json", true) == 0) + { + isJson = true; + } + + if (isJson) + { + return formatter.AsJson(formatter.Context.MyApplyODataUriFilter(modelItems), code); + } + throw new NotImplementedException("Atom feeds not implemented"); + } + } +} +*/ + namespace ComicRackWebViewer { public static class BCRExtensions { - public static Response AsError(this IResponseFormatter formatter, HttpStatusCode statusCode, string message) + public static Response AsError(this IResponseFormatter formatter, HttpStatusCode statusCode, string message, Request request) { return new Response { StatusCode = statusCode, ContentType = "text/plain", - Contents = stream => (new StreamWriter(stream) { AutoFlush = true }).Write(message) + Contents = stream => (new StreamWriter(stream) { AutoFlush = true }).Write("Request: " + request.Url + "\nError: " + message) }; } } @@ -38,160 +109,258 @@ namespace ComicRackWebViewer public class BCRModule : NancyModule { - private BCRSettings settings = null; - - - public BCRModule() : base("/BCR") { - settings = BCRSettings.Load(); - + // Undoubtedly Nancy has a better way to do error handling, but the documentation is severely lacking. + // For now, rewrite the response with a JSON object. + /* After hook isn't called if there is an unhandled exception.... + After += (ctx) => { + + NancyContext c = ctx as NancyContext;// Modify ctx.Response + + // Error handling + // If this is an error response then we need to alter it, because the default error handling intends to show a page, but + // the error page will never be visible to the user. + // Instead we will send a JSON error object with the error details. + + if (c.Response.StatusCode != HttpStatusCode.OK) + { + string message = ""; + string details = ""; + + if (c.Response.StatusCode == HttpStatusCode.InternalServerError) + { + object errorObject; + + c.Items.TryGetValue(NancyEngine.ERROR_EXCEPTION, out errorObject); + + var error = errorObject as Exception; + + //string trace = context.Trace.TraceLog;.ToString(); + if (error != null) + { + message = "EXCEPTION"; + details = error.ToString(); + } + else + { + message = "INTERNAL SERVER ERROR"; + details = error.ToString(); + } + } + else + if (c.Response.StatusCode == HttpStatusCode.NotFound) + { + message = "NOT FOUND"; + } + else + { + message = "UNKNOWN"; + } + + c.Response.ContentType = "application/json"; + c.Response = Response.AsJson(new { message = message, details = details }, c.Response.StatusCode); + } + }; + */ + Get["/"] = x => { return Response.AsRedirect("/tablet/index.html", RedirectResponse.RedirectType.Permanent); }; Get["/Lists"] = x => { - - int depth = Request.Query.depth.HasValue ? int.Parse(Request.Query.depth) : -1; - return Response.AsOData(Program.Database.ComicLists.Select(c => c.ToComicList(depth))); + try + { + int depth = Request.Query.depth.HasValue ? int.Parse(Request.Query.depth) : -1; + return Response.AsOData(Program.Database.ComicLists.Select(c => c.ToComicList(depth))); + } + catch(Exception e) + { + return Response.AsError(HttpStatusCode.InternalServerError, e.ToString(), Request); + } }; Get["/Lists/{id}"] = x => { - int depth = Request.Query.depth.HasValue ? int.Parse(Request.Query.depth) : -1; - IEnumerable<ComicList> list = Program.Database.ComicLists.Where(c => c.Id == new Guid(x.id)).Select(c => c.ToComicList(depth)); - if (list.Count() == 0) - { - return Response.AsError(HttpStatusCode.NotFound, "List not found"); - } - - try - { - return Response.AsOData(list); + try + { + int depth = Request.Query.depth.HasValue ? int.Parse(Request.Query.depth) : -1; + IEnumerable<ComicList> list = Program.Database.ComicLists.Where(c => c.Id == new Guid(x.id)).Select(c => c.ToComicList(depth)); + if (list.Count() == 0) + { + return Response.AsError(HttpStatusCode.NotFound, "List not found", Request); + } + + return Response.AsOData(list); } catch(Exception e) { - return Response.AsError(HttpStatusCode.InsufficientStorage, e.ToString()); + return Response.AsError(HttpStatusCode.InternalServerError, e.ToString(), Request); } }; // For OData compatibility, count should be $count, but I don't know how to parse the $ with Nancy.... - Get["/Lists/{id}/Comics/count"] = x => { - return Response.AsText(Context.ApplyODataUriFilter(API.GetIssuesOfListFromId(new Guid(x.id), Context).Comics).Count().ToString()); + Get["/Lists/{id}/Comics/count"] = x => { + try + { + return Response.AsText(Context.ApplyODataUriFilter(API.GetIssuesOfListFromId(new Guid(x.id), Context).Comics).Count().ToString()); + } + catch(Exception e) + { + return Response.AsError(HttpStatusCode.InternalServerError, e.ToString(), Request); + } }; // Return the comics of the specified list using OData to filter the comic properties and the list paging. Get["/Lists/{id}/Comics"] = x => { - - bool wantsCount = Request.Query["$inlinecount"].HasValue; - try { - IEnumerable<Comic> comics = API.GetIssuesOfListFromId(new Guid(x.id), Context).Comics; - return Response.AsOData(comics); + bool wantsCount = Request.Query["$inlinecount"].HasValue; + var rawcomics = API.GetIssuesOfListFromId(new Guid(x.id), Context).Comics; + var comics = Context.ApplyODataUriFilter(rawcomics); + return Response.AsJson(comics, HttpStatusCode.OK); + //IEnumerable<Comic> comics = API.GetIssuesOfListFromId(new Guid(x.id), Context).Comics; + //return Response.AsOData(comics); } catch(Exception e) { - return Response.AsError(HttpStatusCode.InsufficientStorage, e.ToString()); + return Response.AsError(HttpStatusCode.InternalServerError, e.ToString(), Request); } - }; Get["/Comics"] = x => { - return Response.AsOData(API.GetComics().Select(c => c.ToComic())); + try + { + return Response.AsOData(API.GetComics().Select(c => c.ToComic())); + } + catch(Exception e) + { + return Response.AsError(HttpStatusCode.InternalServerError, e.ToString(), Request); + } }; // Return the comicbook info as an OData filtered bag of properties. Get["/Comics/{id}"] = x => { - Comic comic = API.GetComic(new Guid(x.id)); - if (comic == null) - { - return Response.AsError(HttpStatusCode.NotFound, "Comic not found"); - } - - return Response.AsOData(new List<Comic> { comic }); + try + { + Comic comic = API.GetComic(new Guid(x.id)); + if (comic == null) + { + return Response.AsError(HttpStatusCode.NotFound, "Comic not found", Request); + } + + return Response.AsOData(new List<Comic> { comic }); + } + catch(Exception e) + { + return Response.AsError(HttpStatusCode.InternalServerError, e.ToString(), Request); + } }; // Retrieve the specified page as a jpg file with the specified dimensions. Get["/Comics/{id}/Pages/{page}"] = x => { - - int width = Request.Query.width.HasValue ? int.Parse(Request.Query.width) : -1; - int height = Request.Query.height.HasValue ? int.Parse(Request.Query.height) : -1; - - int maxWidth = Request.Query.maxWidth.HasValue ? int.Parse(Request.Query.maxWidth) : -1; - int maxHeight = Request.Query.maxHeight.HasValue ? int.Parse(Request.Query.maxHeight) : -1; - - return API.GetPageImage(new Guid(x.id), int.Parse(x.page), width, height, settings, Response); + try + { + int width = Request.Query.width.HasValue ? int.Parse(Request.Query.width) : -1; + int height = Request.Query.height.HasValue ? int.Parse(Request.Query.height) : -1; + + int maxWidth = Request.Query.maxWidth.HasValue ? int.Parse(Request.Query.maxWidth) : -1; + int maxHeight = Request.Query.maxHeight.HasValue ? int.Parse(Request.Query.maxHeight) : -1; + + return API.GetPageImage(new Guid(x.id), int.Parse(x.page), width, height, Response); + } + catch(Exception e) + { + return Response.AsError(HttpStatusCode.InternalServerError, e.ToString(), Request); + } }; // Get one property. Get["/Comics/{id}/{property}"] = x => { - Comic comic = API.GetComic(new Guid(x.id)); - if (comic == null) - { - return Response.AsError(HttpStatusCode.NotFound, "Comic not found"); - } + try + { + Comic comic = API.GetComic(new Guid(x.id)); + if (comic == null) + { + return Response.AsError(HttpStatusCode.NotFound, "Comic not found", Request); + } - try - { PropertyInfo property = comic.GetType().GetProperty(x.property); object value = property.GetValue(comic, null); return Response.AsJson(value); } catch(Exception e) - { - return Response.AsError(HttpStatusCode.NotFound, "Comic property not found"); - } + { + return Response.AsError(HttpStatusCode.InternalServerError, e.ToString(), Request); + } }; // Update properties of the specified comicbook. Put["/Comics/{id}"] = x => { - - // Get the ComicBook entry from the library, so we can change it. - ComicBook book = API.GetComicBook(new Guid(x.id)); - if (book == null) + try { - return Response.AsError(HttpStatusCode.NotFound, "Comic not found"); + // Get the ComicBook entry from the library, so we can change it. + ComicBook book = API.GetComicBook(new Guid(x.id)); + if (book == null) + { + return Response.AsError(HttpStatusCode.NotFound, "Comic not found", Request); + } + + // Convert form values to temporary ComicBook object. + ComicBook info = this.Bind<ComicBook>(); + + IEnumerable<string> keys = Request.Form.GetDynamicMemberNames(); + + // This also triggers the update of the ComicRack application. + book.CopyDataFrom(info, keys); + + return HttpStatusCode.OK; + } + catch(Exception e) + { + return Response.AsError(HttpStatusCode.InternalServerError, e.ToString(), Request); } - - // Convert form values to temporary ComicBook object. - ComicBook info = this.Bind<ComicBook>(); - - IEnumerable<string> keys = Request.Form.GetDynamicMemberNames(); - - // This also triggers the update of the ComicRack application. - book.CopyDataFrom(info, keys); - - return HttpStatusCode.OK; }; // Update one property Put["/Comics/{id}/{property}"] = x => { - - // Convert form values to temporary Comic object. - string info = this.Bind<string>(); - - - // Now get the ComicBook entry from the library, so we can change it. - ComicBook book = API.GetComicBook(x.id); - if (book == null) + try + { + // Convert form values to temporary Comic object. + string info = this.Bind<string>(); + + + // Now get the ComicBook entry from the library, so we can change it. + ComicBook book = API.GetComicBook(x.id); + if (book == null) + { + return Response.AsError(HttpStatusCode.NotFound, "Comic not found", Request); + } + + // Setting one of these values also triggers the update of the ComicRack application. + book.SetValue(x.property, info); + + + return HttpStatusCode.OK; + } + catch(Exception e) { - return Response.AsError(HttpStatusCode.NotFound, "Comic not found"); + return Response.AsError(HttpStatusCode.InternalServerError, e.ToString(), Request); } - - // Setting one of these values also triggers the update of the ComicRack application. - book.SetValue(x.property, info); - - - return HttpStatusCode.OK; }; // Get the BCR settings. Get["/Settings"] = x => { - - return Response.AsJson(settings, HttpStatusCode.OK); + try + { + return Response.AsJson(BCRSettingsStore.Instance, HttpStatusCode.OK); + } + catch(Exception e) + { + return Response.AsError(HttpStatusCode.InternalServerError, e.ToString(), Request); + } }; // Update the BCR settings. @@ -200,13 +369,13 @@ namespace ComicRackWebViewer // TODO: only overwrite settings that were specified. try { - settings = this.Bind<BCRSettings>(); - settings.Save(); + BCRSettings settings = this.Bind<BCRSettings>(); + BCRSettingsStore.Instance.UpdateFrom(settings); return HttpStatusCode.OK; } catch(Exception e) { - return Response.AsError(HttpStatusCode.InternalServerError, e.ToString()); + return Response.AsError(HttpStatusCode.InternalServerError, e.ToString(), Request); } }; @@ -217,7 +386,7 @@ namespace ComicRackWebViewer } catch(Exception e) { - return Response.AsError(HttpStatusCode.BadRequest, e.ToString()); + return Response.AsError(HttpStatusCode.InternalServerError, e.ToString(), Request); } }; @@ -229,7 +398,7 @@ namespace ComicRackWebViewer } catch(Exception e) { - return Response.AsError(HttpStatusCode.BadRequest, e.ToString()); + return Response.AsError(HttpStatusCode.InternalServerError, e.ToString(), Request); } }; @@ -240,7 +409,7 @@ namespace ComicRackWebViewer } catch(Exception e) { - return Response.AsError(HttpStatusCode.BadRequest, e.ToString()); + return Response.AsError(HttpStatusCode.InternalServerError, e.ToString(), Request); } }; @@ -252,14 +421,24 @@ namespace ComicRackWebViewer } catch(Exception e) { - return Response.AsError(HttpStatusCode.BadRequest, e.ToString()); + return Response.AsError(HttpStatusCode.InternalServerError, e.ToString(), Request); } }; Get["/Log"] = x => { - string severity = Request.Query.sev.HasValue ? Request.Query.sev : ""; - string message = Request.Query.msg.HasValue ? Request.Query.msg : ""; - return Response.AsRedirect("/tablet/resources/images/empty_1x1.png", RedirectResponse.RedirectType.Permanent); + try + { + string severity = Request.Query.sev.HasValue ? Request.Query.sev : ""; + string message = Request.Query.msg.HasValue ? Request.Query.msg : ""; + + // TODO: write log entry to a file. + + return Response.AsRedirect("/tablet/resources/images/empty_1x1.png", RedirectResponse.RedirectType.Permanent); + } + catch(Exception e) + { + return Response.AsError(HttpStatusCode.InternalServerError, e.ToString(), Request); + } }; } diff --git a/ComicRackWebViewer/Plugin.cs b/ComicRackWebViewer/Plugin.cs index 782de93..47eac8f 100644 --- a/ComicRackWebViewer/Plugin.cs +++ b/ComicRackWebViewer/Plugin.cs @@ -8,22 +8,41 @@ namespace ComicRackWebViewer {
internal static IApplication Application;
private static WebServicePanel panel;
- private static Version requiredVersion = new Version(0, 9, 153);
-
+ private static Version requiredVersion = new Version(0, 9, 155);
+
+ public static void Initialize(IApplication app)
+ {
+ try
+ {
+ Application = app;
+ var comicVersion = new Version(app.ProductVersion);
+ if (comicVersion < requiredVersion)
+ {
+ MessageBox.Show("Version check failed!\n\nThe ComicRack Web Viewer Plugin requires an updated version of ComicRack\nComicRack version required: " + requiredVersion + "\n\nThe Web Viewer is now disabled.", "ComicRack Web Viewer Plugin", MessageBoxButton.OK, MessageBoxImage.Error);
+ return;
+ }
+
+ BCRInstaller.Instance.Install();
+ }
+ catch (Exception e)
+ {
+ MessageBox.Show(e.ToString());
+ }
+ }
+
public static void Run(IApplication app)
{
+ Initialize(app);
try
{
- Application = app;
+ /*
var comicVersion = new Version(app.ProductVersion);
if (comicVersion < requiredVersion)
{
- MessageBox.Show("ComicRack version required: " + requiredVersion);
- return;
+ MessageBox.Show("Version check failed!\n\nThe ComicRack Web Viewer Plugin requires an updated version of ComicRack\nComicRack version required: " + requiredVersion + "\n\nThe Web Viewer is now disabled.", "ComicRack Web Viewer Plugin", MessageBoxButton.OK, MessageBoxImage.Error);
+ return;
}
-
- BCRInstaller.Instance.Install();
-
+ */
if (panel == null)
{
panel = new WebServicePanel();
@@ -40,17 +59,16 @@ namespace ComicRackWebViewer public static void RunAtStartup(IApplication app)
{
+ Initialize(app);
try
{
- Application = app;
+ /*
var comicVersion = new Version(app.ProductVersion);
if (comicVersion < requiredVersion)
{
- MessageBox.Show("ComicRack version required: " + requiredVersion);
- return;
+ return;
}
-
- BCRInstaller.Instance.Install();
+ */
if (panel == null)
{
diff --git a/ComicRackWebViewer/Program.py b/ComicRackWebViewer/Program.py index 05fa984..c98903d 100644 --- a/ComicRackWebViewer/Program.py +++ b/ComicRackWebViewer/Program.py @@ -6,6 +6,9 @@ clr.AddReferenceByPartialName("ComicRackWebViewer") from ComicRackWebViewer import Plugin
+#Version check + additional install operations:
+#Plugin.RunWhenComicRackStarts(ComicRack.App)
+
#@Name ComicRack Web
#@Key ComicRackWebViewer
#@Hook Books, Editor
diff --git a/ComicRackWebViewer/Settings.cs b/ComicRackWebViewer/Settings.cs deleted file mode 100644 index 73b7b37..0000000 --- a/ComicRackWebViewer/Settings.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System.Collections.Generic;
-using System.IO;
-using System.IO.IsolatedStorage;
-
-namespace ComicRackWebViewer
-{
- public static class Settings
- {
- private const string DIRECTORY = "ComicRackWebViewer";
- private const string SETTINGS_FILE = "ComicRackWebViewer\\settings.txt";
-
- private static Dictionary<string, string> settings = new Dictionary<string, string>();
-
- static Settings()
- {
- var file = GetIsoFile();
- if (file.FileExists(SETTINGS_FILE))
- {
- using (var reader = new StreamReader(file.OpenFile(SETTINGS_FILE, FileMode.Open)))
- {
- string line;
- while (!string.IsNullOrEmpty(line = reader.ReadLine()))
- {
- var setting = line.Split(',');
- if (setting.Length == 2)
- {
- settings.Add(setting[0], setting[1]);
- }
- }
- }
- }
- }
-
- public static string GetSetting(string key)
- {
- string value;
- if (settings.TryGetValue(key, out value))
- {
- return value;
- }
- return null;
- }
-
- public static void SaveSetting(string key, string value)
- {
- settings[key] = value;
- SaveAll();
- }
-
- private static IsolatedStorageFile GetIsoFile()
- {
- var file = IsolatedStorageFile.GetUserStoreForDomain();
- if (!file.DirectoryExists(DIRECTORY))
- {
- file.CreateDirectory(DIRECTORY);
- }
- return file;
- }
-
- private static void SaveAll()
- {
- var file = GetIsoFile();
- using (var writer = new StreamWriter(file.OpenFile(SETTINGS_FILE, FileMode.OpenOrCreate)))
- {
- foreach (var kvp in settings)
- {
- writer.WriteLine(kvp.Key + "," + kvp.Value);
- }
- }
- }
- }
-}
diff --git a/ComicRackWebViewer/WebServicePanel.xaml.cs b/ComicRackWebViewer/WebServicePanel.xaml.cs index 828b7ac..280cfe4 100644 --- a/ComicRackWebViewer/WebServicePanel.xaml.cs +++ b/ComicRackWebViewer/WebServicePanel.xaml.cs @@ -27,8 +27,9 @@ namespace ComicRackWebViewer public WebServicePanel()
{
InitializeComponent();
- addressTextBox.Text = Settings.GetSetting("externalip") ?? "localhost";
- portTextBox.Text = Settings.GetSetting("port") ?? "8080";
+ addressTextBox.Text = BCRSettingsStore.Instance.webserver_externalip;
+ portTextBox.Text = BCRSettingsStore.Instance.webserver_port.ToString();
+ actualPort = BCRSettingsStore.Instance.webserver_port;
//bindAll.IsChecked = bool.Parse(Settings.GetSetting("bindAll") ?? "false");
SetEnabledState();
}
@@ -193,8 +194,10 @@ namespace ComicRackWebViewer {
if (IsCurrentlyRunningAsAdmin())
{
- Settings.SaveSetting("externalip", addressTextBox.Text);
- Settings.SaveSetting("port", portTextBox.Text);
+ BCRSettingsStore.Instance.webserver_externalip = addressTextBox.Text.Trim();
+ BCRSettingsStore.Instance.webserver_port = actualPort.HasValue ? actualPort.Value : 8080;
+ BCRSettingsStore.Instance.Save();
+
//Settings.SaveSetting("bindAll", (bindAll.IsChecked ?? false).ToString());
StartService();
}
|