From 4536c5cf2d7b8e68768f90d281b3e4974cd26ae9 Mon Sep 17 00:00:00 2001 From: Niki Roo Date: Thu, 14 May 2020 12:09:51 +0200 Subject: [PATCH] Merge from master --- data/JsonIO.java | 31 ++++ library/BasicLibrary.java | 4 +- library/CacheLibrary.java | 2 +- library/LocalLibrary.java | 8 +- library/RemoteLibrary.java | 2 +- library/RemoteLibraryServer.java | 15 +- library/WebLibrary.java | 146 +++++++++++++---- library/WebLibraryServer.java | 254 ++++++++++++++++++++++++++++-- library/WebLibraryServerHtml.java | 39 ++++- library/WebLibraryUrls.java | 76 ++++++++- 10 files changed, 518 insertions(+), 59 deletions(-) diff --git a/data/JsonIO.java b/data/JsonIO.java index 5157dca3..beff342b 100644 --- a/data/JsonIO.java +++ b/data/JsonIO.java @@ -8,6 +8,7 @@ import org.json.JSONException; import org.json.JSONObject; import be.nikiroo.fanfix.data.Paragraph.ParagraphType; +import be.nikiroo.utils.Progress; public class JsonIO { static public JSONObject toJson(MetaData meta) { @@ -200,6 +201,36 @@ public class JsonIO { return para; } + // no children included + static public JSONObject toJson(Progress pg) { + if (pg == null) { + return null; + } + + JSONObject json = new JSONObject(); + + put(json, "", Progress.class.getName()); + put(json, "name", pg.getName()); + put(json, "min", pg.getMin()); + put(json, "max", pg.getMax()); + put(json, "progress", pg.getProgress()); + + return json; + } + + // no children included + static public Progress toProgress(JSONObject json) { + if (json == null) { + return null; + } + + Progress pg = new Progress(getString(json, "name"), + getInt(json, "min", 0), getInt(json, "max", 100)); + pg.setProgress(getInt(json, "progress", 0)); + + return pg; + } + static public List toListString(JSONArray array) { if (array != null) { List values = new ArrayList(); diff --git a/library/BasicLibrary.java b/library/BasicLibrary.java index af7920bf..f6024eef 100644 --- a/library/BasicLibrary.java +++ b/library/BasicLibrary.java @@ -311,7 +311,7 @@ abstract public class BasicLibrary { * * @return the next luid */ - protected abstract int getNextId(); + protected abstract String getNextId(); /** * Delete the target {@link Story}. @@ -741,7 +741,7 @@ abstract public class BasicLibrary { pg.setName("Saving story"); if (luid == null || luid.isEmpty()) { - meta.setLuid(String.format("%03d", getNextId())); + meta.setLuid(getNextId()); } else { meta.setLuid(luid); } diff --git a/library/CacheLibrary.java b/library/CacheLibrary.java index a3c3b5e3..e184c1bd 100644 --- a/library/CacheLibrary.java +++ b/library/CacheLibrary.java @@ -419,7 +419,7 @@ public class CacheLibrary extends BasicLibrary { // BasicLibrary: @Override - protected int getNextId() { + protected String getNextId() { throw new java.lang.InternalError("Should not have been called"); } diff --git a/library/LocalLibrary.java b/library/LocalLibrary.java index 67209726..7220a395 100644 --- a/library/LocalLibrary.java +++ b/library/LocalLibrary.java @@ -20,10 +20,10 @@ import be.nikiroo.fanfix.output.BasicOutput; import be.nikiroo.fanfix.output.BasicOutput.OutputType; import be.nikiroo.fanfix.output.InfoCover; import be.nikiroo.fanfix.supported.InfoReader; +import be.nikiroo.utils.HashUtils; import be.nikiroo.utils.IOUtils; import be.nikiroo.utils.Image; import be.nikiroo.utils.Progress; -import be.nikiroo.utils.StringUtils; /** * This {@link BasicLibrary} will store the stories locally on disk. @@ -168,11 +168,11 @@ public class LocalLibrary extends BasicLibrary { } @Override - protected int getNextId() { + protected String getNextId() { getStories(null); // make sure lastId is set synchronized (lock) { - return ++lastId; + return String.format("%03d", ++lastId); } } @@ -553,7 +553,7 @@ public class LocalLibrary extends BasicLibrary { */ private File getAuthorCoverFile(String author) { File aDir = new File(baseDir, "_AUTHORS"); - String hash = StringUtils.getMd5Hash(author); + String hash = HashUtils.md5(author); String ext = Instance.getInstance().getConfig() .getString(Config.FILE_FORMAT_IMAGE_FORMAT_COVER); return new File(aDir, hash + "." + ext.toLowerCase()); diff --git a/library/RemoteLibrary.java b/library/RemoteLibrary.java index 3a60e02c..ad928008 100644 --- a/library/RemoteLibrary.java +++ b/library/RemoteLibrary.java @@ -485,7 +485,7 @@ public class RemoteLibrary extends BasicLibrary { // The following methods are only used by Save and Delete in BasicLibrary: @Override - protected int getNextId() { + protected String getNextId() { throw new java.lang.InternalError("Should not have been called"); } diff --git a/library/RemoteLibraryServer.java b/library/RemoteLibraryServer.java index e54f105d..59819bb9 100644 --- a/library/RemoteLibraryServer.java +++ b/library/RemoteLibraryServer.java @@ -3,6 +3,7 @@ package be.nikiroo.fanfix.library; import java.io.IOException; import java.net.URL; import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.List; @@ -578,12 +579,16 @@ public class RemoteLibraryServer extends ServerObject { private boolean isAllowed(MetaData meta, List whitelist, List blacklist) { - if (!whitelist.isEmpty() && !whitelist.contains(meta.getSource())) { - return false; + MetaResultList one = new MetaResultList(Arrays.asList(meta)); + if (!whitelist.isEmpty()) { + if (one.filter(whitelist, null, null).isEmpty()) { + return false; + } } - - if (blacklist.contains(meta.getSource())) { - return false; + if (!blacklist.isEmpty()) { + if (!one.filter(blacklist, null, null).isEmpty()) { + return false; + } } return true; diff --git a/library/WebLibrary.java b/library/WebLibrary.java index 8c71ff59..9d1c773a 100644 --- a/library/WebLibrary.java +++ b/library/WebLibrary.java @@ -103,14 +103,18 @@ public class WebLibrary extends BasicLibrary { this.host = host; this.port = port; - - // TODO: not supported yet - this.rw = false; } + /** + * Return the version of the program running server-side. + *

+ * Never returns NULL. + * + * @return the version or an empty {@link Version} if not known + */ public Version getVersion() { try { - InputStream in = download(WebLibraryUrls.VERSION_URL); + InputStream in = post(WebLibraryUrls.VERSION_URL); try { return new Version(IOUtils.readSmallStream(in)); } finally { @@ -125,10 +129,10 @@ public class WebLibrary extends BasicLibrary { @Override public Status getStatus() { try { - download(WebLibraryUrls.INDEX_URL).close(); + post(WebLibraryUrls.INDEX_URL).close(); } catch (IOException e) { try { - download(WebLibraryUrls.VERSION_URL).close(); + post("/style.css").close(); return Status.UNAUTHORIZED; } catch (IOException ioe) { return Status.UNAVAILABLE; @@ -146,7 +150,7 @@ public class WebLibrary extends BasicLibrary { @Override public Image getCover(String luid) throws IOException { - InputStream in = download(WebLibraryUrls.getStoryUrlCover(luid)); + InputStream in = post(WebLibraryUrls.getStoryUrlCover(luid)); try { return new Image(in); } finally { @@ -155,37 +159,48 @@ public class WebLibrary extends BasicLibrary { } @Override - public Image getCustomSourceCover(final String source) throws IOException { - // TODO maybe global system in BasicLib ? - return null; + public Image getCustomSourceCover(String source) throws IOException { + InputStream in = post(WebLibraryUrls.getCoverUrlSource(source)); + try { + return new Image(in); + } finally { + in.close(); + } } @Override - public Image getCustomAuthorCover(final String author) throws IOException { - // TODO maybe global system in BasicLib ? - return null; + public Image getCustomAuthorCover(String author) throws IOException { + InputStream in = post(WebLibraryUrls.getCoverUrlAuthor(author)); + try { + return new Image(in); + } finally { + in.close(); + } } @Override public void setSourceCover(String source, String luid) throws IOException { - // TODO Auto-generated method stub - throw new IOException("Not implemented yet"); + Map post = new HashMap(); + post.put("luid", luid); + post(WebLibraryUrls.getCoverUrlSource(source), post).close(); } @Override public void setAuthorCover(String author, String luid) throws IOException { - // TODO Auto-generated method stub - throw new IOException("Not implemented yet"); + Map post = new HashMap(); + post.put("luid", luid); + post(WebLibraryUrls.getCoverUrlAuthor(author), post).close(); } @Override public synchronized Story getStory(final String luid, Progress pg) throws IOException { - - // TODO: pg + if (pg == null) { + pg = new Progress(); + } Story story; - InputStream in = download(WebLibraryUrls.getStoryUrlJson(luid)); + InputStream in = post(WebLibraryUrls.getStoryUrlJson(luid)); try { JSONObject json = new JSONObject(IOUtils.readSmallStream(in)); story = JsonIO.toStory(json); @@ -193,13 +208,19 @@ public class WebLibrary extends BasicLibrary { in.close(); } + int max = 0; + for (Chapter chap : story) { + max += chap.getParagraphs().size(); + } + pg.setMinMax(0, max); + story.getMeta().setCover(getCover(luid)); int chapNum = 1; for (Chapter chap : story) { int number = 1; for (Paragraph para : chap) { if (para.getType() == ParagraphType.IMAGE) { - InputStream subin = download( + InputStream subin = post( WebLibraryUrls.getStoryUrl(luid, chapNum, number)); try { para.setContentImage(new Image(subin)); @@ -208,19 +229,21 @@ public class WebLibrary extends BasicLibrary { } } + pg.add(1); number++; } chapNum++; } + pg.done(); return story; } @Override protected List getMetas(Progress pg) throws IOException { List metas = new ArrayList(); - InputStream in = download(WebLibraryUrls.LIST_URL_METADATA); + InputStream in = post(WebLibraryUrls.LIST_URL_METADATA); JSONArray jsonArr = new JSONArray(IOUtils.readSmallStream(in)); for (int i = 0; i < jsonArr.length(); i++) { JSONObject json = jsonArr.getJSONObject(i); @@ -233,8 +256,9 @@ public class WebLibrary extends BasicLibrary { @Override // Could work (more slowly) without it public MetaData imprt(final URL url, Progress pg) throws IOException { - if (true) - throw new IOException("Not implemented yet"); + if (pg == null) { + pg = new Progress(); + } // Import the file locally if it is actually a file @@ -244,8 +268,44 @@ public class WebLibrary extends BasicLibrary { // Import it remotely if it is an URL - // TODO - return super.imprt(url, pg); + try { + String luid = null; + + Map post = new HashMap(); + post.put("url", url.toString()); + InputStream in = post(WebLibraryUrls.IMPRT_URL_IMPORT, post); + try { + luid = IOUtils.readSmallStream(in); + } finally { + in.close(); + } + + Progress subPg = null; + do { + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + } + + in = post(WebLibraryUrls.getImprtProgressUrl(luid)); + try { + subPg = JsonIO.toProgress( + new JSONObject(IOUtils.readSmallStream(in))); + } finally { + in.close(); + } + } while (subPg != null); + + in = post(WebLibraryUrls.getStoryUrlMetadata(luid)); + try { + return JsonIO.toMetaData( + new JSONObject(IOUtils.readSmallStream(in))); + } finally { + in.close(); + } + } finally { + pg.done(); + } } @Override @@ -253,8 +313,24 @@ public class WebLibrary extends BasicLibrary { protected synchronized void changeSTA(final String luid, final String newSource, final String newTitle, final String newAuthor, Progress pg) throws IOException { - // TODO - super.changeSTA(luid, newSource, newTitle, newAuthor, pg); + MetaData meta = getInfo(luid); + if (meta != null) { + if (!meta.getSource().equals(newSource)) { + Map post = new HashMap(); + post.put("value", newSource); + post(WebLibraryUrls.getStoryUrlSource(luid), post).close(); + } + if (!meta.getTitle().equals(newTitle)) { + Map post = new HashMap(); + post.put("value", newTitle); + post(WebLibraryUrls.getStoryUrlTitle(luid), post).close(); + } + if (!meta.getAuthor().equals(newAuthor)) { + Map post = new HashMap(); + post.put("value", newAuthor); + post(WebLibraryUrls.getStoryUrlAuthor(luid), post).close(); + } + } } @Override @@ -270,7 +346,7 @@ public class WebLibrary extends BasicLibrary { // The following methods are only used by Save and Delete in BasicLibrary: @Override - protected int getNextId() { + protected String getNextId() { throw new java.lang.InternalError("Should not have been called"); } @@ -293,10 +369,18 @@ public class WebLibrary extends BasicLibrary { } // starts with "/", never NULL - private InputStream download(String path) throws IOException { + private InputStream post(String path) throws IOException { + return post(path, null); + } + + // starts with "/", never NULL + private InputStream post(String path, Map post) + throws IOException { URL url = new URL(host + ":" + port + path); - Map post = new HashMap(); + if (post == null) { + post = new HashMap(); + } post.put("login", subkey); post.put("password", key); diff --git a/library/WebLibraryServer.java b/library/WebLibraryServer.java index 97f2f0e8..5cda3b5d 100644 --- a/library/WebLibraryServer.java +++ b/library/WebLibraryServer.java @@ -3,7 +3,9 @@ package be.nikiroo.fanfix.library; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; +import java.net.URL; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -25,6 +27,7 @@ import be.nikiroo.utils.LoginResult; import be.nikiroo.utils.NanoHTTPD; import be.nikiroo.utils.NanoHTTPD.Response; import be.nikiroo.utils.NanoHTTPD.Response.Status; +import be.nikiroo.utils.Progress; public class WebLibraryServer extends WebLibraryServerHtml { class WLoginResult extends LoginResult { @@ -72,6 +75,8 @@ public class WebLibraryServer extends WebLibraryServerHtml { private List whitelist; private List blacklist; + private Map imprts = new HashMap(); + public WebLibraryServer(boolean secure) throws IOException { super(secure); @@ -182,17 +187,17 @@ public class WebLibraryServer extends WebLibraryServerHtml { // /story/luid/json <-- json, whole chapter (no images) @Override protected Response getStoryPart(String uri, WLoginResult login) { - String[] cover = uri.split("/"); + String[] uriParts = uri.split("/"); int off = 2; - if (cover.length < off + 2) { + if (uriParts.length < off + 2) { return NanoHTTPD.newFixedLengthResponse(Status.BAD_REQUEST, NanoHTTPD.MIME_PLAINTEXT, null); } - String luid = cover[off + 0]; - String chapterStr = cover[off + 1]; - String imageStr = cover.length < off + 3 ? null : cover[off + 2]; + String luid = uriParts[off + 0]; + String chapterStr = uriParts[off + 1]; + String imageStr = uriParts.length < off + 3 ? null : uriParts[off + 2]; // 1-based (0 = desc) int chapter = 0; @@ -228,7 +233,7 @@ public class WebLibraryServer extends WebLibraryServerHtml { InputStream in = null; try { if ("cover".equals(chapterStr)) { - Image img = cover(luid, login); + Image img = storyCover(luid, login); if (img != null) { in = img.newInputStream(); } @@ -287,6 +292,169 @@ public class WebLibraryServer extends WebLibraryServerHtml { return newInputStreamResponse(mimeType, in); } + // /story/luid/source + // /story/luid/title + // /story/luid/author + @Override + protected Response setStoryPart(String uri, String value, + WLoginResult login) throws IOException { + String[] uriParts = uri.split("/"); + int off = 2; // "" and "story" + + if (uriParts.length < off + 2) { + return NanoHTTPD.newFixedLengthResponse(Status.BAD_REQUEST, + NanoHTTPD.MIME_PLAINTEXT, "Invalid story part request"); + } + + String luid = uriParts[off + 0]; + String type = uriParts[off + 1]; + + if (!Arrays.asList("source", "title", "author").contains(type)) { + return NanoHTTPD.newFixedLengthResponse(Status.BAD_REQUEST, + NanoHTTPD.MIME_PLAINTEXT, + "Invalid SET story part: " + type); + } + + if (meta(luid, login) != null) { + BasicLibrary lib = Instance.getInstance().getLibrary(); + if ("source".equals(type)) { + lib.changeSource(luid, value, null); + } else if ("title".equals(type)) { + lib.changeTitle(luid, value, null); + } else if ("author".equals(type)) { + lib.changeAuthor(luid, value, null); + } + } + + return newInputStreamResponse(NanoHTTPD.MIME_PLAINTEXT, null); + } + + @Override + protected Response getCover(String uri, WLoginResult login) + throws IOException { + String[] uriParts = uri.split("/"); + int off = 2; // "" and "cover" + + if (uriParts.length < off + 2) { + return NanoHTTPD.newFixedLengthResponse(Status.BAD_REQUEST, + NanoHTTPD.MIME_PLAINTEXT, "Invalid cover request"); + } + + String type = uriParts[off + 0]; + String id = uriParts[off + 1]; + + InputStream in = null; + + if ("story".equals(type)) { + Image img = storyCover(id, login); + if (img != null) { + in = img.newInputStream(); + } + } else if ("source".equals(type)) { + Image img = sourceCover(id, login); + if (img != null) { + in = img.newInputStream(); + } + } else if ("author".equals(type)) { + Image img = authorCover(id, login); + if (img != null) { + in = img.newInputStream(); + } + } else { + return NanoHTTPD.newFixedLengthResponse(Status.BAD_REQUEST, + NanoHTTPD.MIME_PLAINTEXT, + "Invalid GET cover type: " + type); + } + + // TODO: get correct image type + return newInputStreamResponse("image/png", in); + } + + @Override + protected Response setCover(String uri, String luid, WLoginResult login) + throws IOException { + String[] uriParts = uri.split("/"); + int off = 2; // "" and "cover" + + if (uriParts.length < off + 2) { + return NanoHTTPD.newFixedLengthResponse(Status.BAD_REQUEST, + NanoHTTPD.MIME_PLAINTEXT, "Invalid cover request"); + } + + String type = uriParts[off + 0]; + String id = uriParts[off + 1]; + + if ("source".equals(type)) { + sourceCover(id, login, luid); + } else if ("author".equals(type)) { + authorCover(id, login, luid); + } else { + return NanoHTTPD.newFixedLengthResponse(Status.BAD_REQUEST, + NanoHTTPD.MIME_PLAINTEXT, + "Invalid SET cover type: " + type); + } + + return newInputStreamResponse(NanoHTTPD.MIME_PLAINTEXT, null); + } + + @Override + protected Response imprt(String uri, String urlStr, WLoginResult login) + throws IOException { + final BasicLibrary lib = Instance.getInstance().getLibrary(); + + final URL url = new URL(urlStr); + final Progress pg = new Progress(); + final String luid = lib.getNextId(); + + synchronized (imprts) { + imprts.put(luid, pg); + } + + new Thread(new Runnable() { + @Override + public void run() { + try { + lib.imprt(url, pg); + } catch (IOException e) { + Instance.getInstance().getTraceHandler().error(e); + } finally { + synchronized (imprts) { + imprts.remove(luid); + } + } + } + }, "Import story: " + urlStr).start(); + + lib.imprt(url, pg); + + return NanoHTTPD.newFixedLengthResponse(Status.OK, + NanoHTTPD.MIME_PLAINTEXT, luid); + } + + @Override + protected Response imprtProgress(String uri, WLoginResult login) { + String[] uriParts = uri.split("/"); + int off = 2; // "" and "import" + + if (uriParts.length < off + 1) { + return NanoHTTPD.newFixedLengthResponse(Status.BAD_REQUEST, + NanoHTTPD.MIME_PLAINTEXT, "Invalid cover request"); + } + + String luid = uriParts[off + 0]; + + Progress pg = null; + synchronized (imprts) { + pg = imprts.get(luid); + } + if (pg != null) { + return NanoHTTPD.newFixedLengthResponse(Status.OK, + "application/json", JsonIO.toJson(pg).toString()); + } + + return newInputStreamResponse(NanoHTTPD.MIME_PLAINTEXT, null); + } + @Override protected List metas(WLoginResult login) throws IOException { BasicLibrary lib = Instance.getInstance().getLibrary(); @@ -348,7 +516,8 @@ public class WebLibraryServer extends WebLibraryServerHtml { return meta; } - private Image cover(String luid, WLoginResult login) throws IOException { + private Image storyCover(String luid, WLoginResult login) + throws IOException { MetaData meta = meta(luid, login); if (meta != null) { BasicLibrary lib = Instance.getInstance().getLibrary(); @@ -358,13 +527,74 @@ public class WebLibraryServer extends WebLibraryServerHtml { return null; } + private Image authorCover(String author, WLoginResult login) + throws IOException { + Image img = null; + + List metas = new MetaResultList(metas(login)).filter(null, + author, null); + if (metas.size() > 0) { + BasicLibrary lib = Instance.getInstance().getLibrary(); + img = lib.getCustomAuthorCover(author); + if (img == null) + img = lib.getCover(metas.get(0).getLuid()); + } + + return img; + + } + + private void authorCover(String author, WLoginResult login, String luid) + throws IOException { + if (meta(luid, login) != null) { + List metas = new MetaResultList(metas(login)).filter(null, + author, null); + if (metas.size() > 0) { + BasicLibrary lib = Instance.getInstance().getLibrary(); + lib.setAuthorCover(author, luid); + } + } + } + + private Image sourceCover(String source, WLoginResult login) + throws IOException { + Image img = null; + + List metas = new MetaResultList(metas(login)).filter(source, + null, null); + if (metas.size() > 0) { + BasicLibrary lib = Instance.getInstance().getLibrary(); + img = lib.getCustomSourceCover(source); + if (img == null) + img = lib.getCover(metas.get(0).getLuid()); + } + + return img; + } + + private void sourceCover(String source, WLoginResult login, String luid) + throws IOException { + if (meta(luid, login) != null) { + List metas = new MetaResultList(metas(login)) + .filter(source, null, null); + if (metas.size() > 0) { + BasicLibrary lib = Instance.getInstance().getLibrary(); + lib.setSourceCover(source, luid); + } + } + } + private boolean isAllowed(MetaData meta, WLoginResult login) { - if (login.isWl() && !whitelist.isEmpty() - && !whitelist.contains(meta.getSource())) { - return false; + MetaResultList one = new MetaResultList(Arrays.asList(meta)); + if (login.isWl() && !whitelist.isEmpty()) { + if (one.filter(whitelist, null, null).isEmpty()) { + return false; + } } - if (login.isBl() && blacklist.contains(meta.getSource())) { - return false; + if (login.isBl() && !blacklist.isEmpty()) { + if (!one.filter(blacklist, null, null).isEmpty()) { + return false; + } } return true; diff --git a/library/WebLibraryServerHtml.java b/library/WebLibraryServerHtml.java index c28188cd..a534b4cd 100644 --- a/library/WebLibraryServerHtml.java +++ b/library/WebLibraryServerHtml.java @@ -47,12 +47,26 @@ abstract class WebLibraryServerHtml implements Runnable { abstract protected Response getStoryPart(String uri, WLoginResult login); + abstract protected Response setStoryPart(String uri, String value, + WLoginResult login) throws IOException; + + abstract protected Response getCover(String uri, WLoginResult login) + throws IOException; + + abstract protected Response setCover(String uri, String luid, + WLoginResult login) throws IOException; + abstract protected List metas(WLoginResult login) throws IOException; abstract protected Story story(String luid, WLoginResult login) throws IOException; + protected abstract Response imprt(String uri, String url, + WLoginResult login) throws IOException; + + protected abstract Response imprtProgress(String uri, WLoginResult login); + public WebLibraryServerHtml(boolean secure) throws IOException { Integer port = Instance.getInstance().getConfig() .getInteger(Config.SERVER_PORT); @@ -162,16 +176,35 @@ abstract class WebLibraryServerHtml implements Runnable { rep = newFixedLengthResponse(Status.OK, MIME_PLAINTEXT, Version.getCurrentVersion().toString()); + } else if (WebLibraryUrls.isCoverUrl(uri)) { + String luid = params.get("luid"); + if (luid != null) { + rep = setCover(uri, luid, login); + } else { + rep = getCover(uri, login); + } } else if (WebLibraryUrls.isListUrl(uri)) { rep = getList(uri, login); } else if (WebLibraryUrls.isStoryUrl(uri)) { - rep = getStoryPart(uri, login); + String value = params.get("value"); + if (value != null) { + rep = setStoryPart(uri, value, login); + } else { + rep = getStoryPart(uri, login); + } } else if (WebLibraryUrls.isViewUrl(uri)) { rep = getViewer(cookies, uri, login); } else if (WebLibraryUrls.LOGOUT_URL.equals(uri)) { session.getCookies().delete("cookie"); cookies.remove("cookie"); rep = loginPage(login(false, false), uri); + } else if (WebLibraryUrls.isImprtUrl(uri)) { + String url = params.get("url"); + if (url != null) { + rep = imprt(uri, url, login); + } else { + rep = imprtProgress(uri, login); + } } else { getTraceHandler().error( "Supported URL was not processed: " @@ -218,7 +251,9 @@ abstract class WebLibraryServerHtml implements Runnable { } }; - if (ssf != null) { + if (ssf != null) + + { getTraceHandler().trace("Install SSL on the web server..."); server.makeSecure(ssf, null); getTraceHandler().trace("Done."); diff --git a/library/WebLibraryUrls.java b/library/WebLibraryUrls.java index be4cf256..41f1c82f 100644 --- a/library/WebLibraryUrls.java +++ b/library/WebLibraryUrls.java @@ -17,11 +17,37 @@ class WebLibraryUrls { static private final String STORY_URL_COVER = STORY_URL_BASE + "{luid}/cover"; static private final String STORY_URL_JSON = STORY_URL_BASE + "{luid}/json"; + static private final String STORY_URL_METADATA = STORY_URL_BASE + + "{luid}/metadata"; + + // GET/SET ("value" param -> set STA to this value) + static private final String STORY_URL_SOURCE = STORY_URL_BASE + + "{luid}/source"; + static private final String STORY_URL_TITLE = STORY_URL_BASE + + "{luid}/title"; + static private final String STORY_URL_AUTHOR = STORY_URL_BASE + + "{luid}/author"; static private final String LIST_URL_BASE = "/list/"; static public final String LIST_URL_METADATA = LIST_URL_BASE + "metadata"; + // "import" requires param "url" and return an luid, "/{luid}" return + // progress status as a JSON Progress or 404 if none (done or failed) + static private final String IMPRT_URL_BASE = "/import/"; + static private final String IMPRT_URL_PROGRESS = IMPRT_URL_BASE + "{luid}"; + static public final String IMPRT_URL_IMPORT = IMPRT_URL_BASE + "import"; + + // GET/SET ("luid" param -> set cover to the cover of this story -- not ok + // for /cover/story/) + static private final String COVER_URL_BASE = "/cover/"; + static private final String COVER_URL_STORY = COVER_URL_BASE + + "story/{luid}"; + static private final String COVER_URL_AUTHOR = COVER_URL_BASE + + "author/{author}"; + static private final String COVER_URL_SOURCE = COVER_URL_BASE + + "source/{source}"; + static public String getViewUrl(String luid, Integer chap, Integer para) { return VIEWER_URL // .replace("{luid}", luid) // @@ -47,10 +73,50 @@ class WebLibraryUrls { .replace("{luid}", luid); } + static public String getStoryUrlSource(String luid) { + return STORY_URL_SOURCE // + .replace("{luid}", luid); + } + + static public String getStoryUrlTitle(String luid) { + return STORY_URL_TITLE// + .replace("{luid}", luid); + } + + static public String getStoryUrlAuthor(String luid) { + return STORY_URL_AUTHOR // + .replace("{luid}", luid); + } + + static public String getStoryUrlMetadata(String luid) { + return STORY_URL_METADATA // + .replace("{luid}", luid); + } + + static public String getImprtProgressUrl(String luid) { + return IMPRT_URL_PROGRESS // + .replace("{luid}", luid); + } + static public boolean isSupportedUrl(String url) { return INDEX_URL.equals(url) || VERSION_URL.equals(url) || LOGOUT_URL.equals(url) || isViewUrl(url) || isStoryUrl(url) - || isListUrl(url); + || isListUrl(url) || isCoverUrl(url) || isImprtUrl(url); + } + + static public String getCoverUrlStory(String luid) { + return COVER_URL_STORY // + .replace("{luid}", luid); + } + + static public String getCoverUrlSource(String source) { + return COVER_URL_SOURCE // + .replace("{source}", source); + } + + static public String getCoverUrlAuthor(String author) { + return COVER_URL_AUTHOR // + .replace("{author}", author); } static public boolean isViewUrl(String url) { @@ -64,4 +130,12 @@ class WebLibraryUrls { static public boolean isListUrl(String url) { return url != null && url.startsWith(LIST_URL_BASE); } + + static public boolean isCoverUrl(String url) { + return url != null && url.startsWith(COVER_URL_BASE); + } + + static public boolean isImprtUrl(String url) { + return url != null && url.startsWith(IMPRT_URL_BASE); + } } -- 2.27.0