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) {
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<String> toListString(JSONArray array) {
if (array != null) {
List<String> values = new ArrayList<String>();
*
* @return the next luid
*/
- protected abstract int getNextId();
+ protected abstract String getNextId();
/**
* Delete the target {@link Story}.
pg.setName("Saving story");
if (luid == null || luid.isEmpty()) {
- meta.setLuid(String.format("%03d", getNextId()));
+ meta.setLuid(getNextId());
} else {
meta.setLuid(luid);
}
// BasicLibrary:
@Override
- protected int getNextId() {
+ protected String getNextId() {
throw new java.lang.InternalError("Should not have been called");
}
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.
}
@Override
- protected int getNextId() {
+ protected String getNextId() {
getStories(null); // make sure lastId is set
synchronized (lock) {
- return ++lastId;
+ return String.format("%03d", ++lastId);
}
}
*/
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());
// 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");
}
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;
private boolean isAllowed(MetaData meta, List<String> whitelist,
List<String> 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;
this.host = host;
this.port = port;
-
- // TODO: not supported yet
- this.rw = false;
}
+ /**
+ * Return the version of the program running server-side.
+ * <p>
+ * 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 {
@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;
@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 {
}
@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<String, String> post = new HashMap<String, String>();
+ 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<String, String> post = new HashMap<String, String>();
+ 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);
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));
}
}
+ pg.add(1);
number++;
}
chapNum++;
}
+ pg.done();
return story;
}
@Override
protected List<MetaData> getMetas(Progress pg) throws IOException {
List<MetaData> metas = new ArrayList<MetaData>();
- 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);
@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
// Import it remotely if it is an URL
- // TODO
- return super.imprt(url, pg);
+ try {
+ String luid = null;
+
+ Map<String, String> post = new HashMap<String, String>();
+ 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
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<String, String> post = new HashMap<String, String>();
+ post.put("value", newSource);
+ post(WebLibraryUrls.getStoryUrlSource(luid), post).close();
+ }
+ if (!meta.getTitle().equals(newTitle)) {
+ Map<String, String> post = new HashMap<String, String>();
+ post.put("value", newTitle);
+ post(WebLibraryUrls.getStoryUrlTitle(luid), post).close();
+ }
+ if (!meta.getAuthor().equals(newAuthor)) {
+ Map<String, String> post = new HashMap<String, String>();
+ post.put("value", newAuthor);
+ post(WebLibraryUrls.getStoryUrlAuthor(luid), post).close();
+ }
+ }
}
@Override
// 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");
}
}
// 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<String, String> post)
+ throws IOException {
URL url = new URL(host + ":" + port + path);
- Map<String, String> post = new HashMap<String, String>();
+ if (post == null) {
+ post = new HashMap<String, String>();
+ }
post.put("login", subkey);
post.put("password", key);
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;
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 {
private List<String> whitelist;
private List<String> blacklist;
+ private Map<String, Progress> imprts = new HashMap<String, Progress>();
+
public WebLibraryServer(boolean secure) throws IOException {
super(secure);
// /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;
InputStream in = null;
try {
if ("cover".equals(chapterStr)) {
- Image img = cover(luid, login);
+ Image img = storyCover(luid, login);
if (img != null) {
in = img.newInputStream();
}
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<MetaData> metas(WLoginResult login) throws IOException {
BasicLibrary lib = Instance.getInstance().getLibrary();
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();
return null;
}
+ private Image authorCover(String author, WLoginResult login)
+ throws IOException {
+ Image img = null;
+
+ List<MetaData> 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<MetaData> 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<MetaData> 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<MetaData> 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;
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<MetaData> 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);
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: "
}
};
- if (ssf != null) {
+ if (ssf != null)
+
+ {
getTraceHandler().trace("Install SSL on the web server...");
server.makeSecure(ssf, null);
getTraceHandler().trace("Done.");
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) //
.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) {
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);
+ }
}