summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeroen Walter <jeroen@enormkansloos.nl>2012-08-25 17:34:26 +0200
committerJeroen Walter <jeroen@enormkansloos.nl>2012-08-25 17:34:26 +0200
commit02ceefe2ea914b202c7ad6819940d94690b0cd6c (patch)
tree5142cefddace419486bc42870c5f7f25900d9b83
parent5b7ff96e229af25255fdf600069dedd408dbe45c (diff)
downloadComicRackWeb-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.cs8
-rw-r--r--ComicRackWebViewer/BCRSettings.cs168
-rw-r--r--ComicRackWebViewer/Bootstrapper.cs74
-rw-r--r--ComicRackWebViewer/ComicRackWebViewer.csproj4
-rw-r--r--ComicRackWebViewer/Entities.cs2
-rw-r--r--ComicRackWebViewer/Modules/BCRModule.cs377
-rw-r--r--ComicRackWebViewer/Plugin.cs44
-rw-r--r--ComicRackWebViewer/Program.py3
-rw-r--r--ComicRackWebViewer/Settings.cs72
-rw-r--r--ComicRackWebViewer/WebServicePanel.xaml.cs11
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();
}