diff --git a/libs/httpmime-4.2.5.jar b/libs/httpmime-4.2.5.jar new file mode 100644 index 000000000..cdb56613c Binary files /dev/null and b/libs/httpmime-4.2.5.jar differ diff --git a/src/org/geometerplus/android/fbreader/network/ActivityNetworkContext.java b/src/org/geometerplus/android/fbreader/network/ActivityNetworkContext.java index 8a6892530..c858b6042 100644 --- a/src/org/geometerplus/android/fbreader/network/ActivityNetworkContext.java +++ b/src/org/geometerplus/android/fbreader/network/ActivityNetworkContext.java @@ -155,7 +155,7 @@ public final class ActivityNetworkContext extends AndroidNetworkContext { private String runTokenAuthorization(String authUrl, String authToken, String code) { final StringBuilder buffer = new StringBuilder(); - final ZLNetworkRequest request = new ZLNetworkRequest(authUrl) { + final ZLNetworkRequest.PostWithMap request = new ZLNetworkRequest.PostWithMap(authUrl) { public void handleStream(InputStream stream, int length) throws IOException { final BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); buffer.append(reader.readLine()); diff --git a/src/org/geometerplus/android/fbreader/network/BookDownloaderService.java b/src/org/geometerplus/android/fbreader/network/BookDownloaderService.java index 94bbf0c46..226662a24 100644 --- a/src/org/geometerplus/android/fbreader/network/BookDownloaderService.java +++ b/src/org/geometerplus/android/fbreader/network/BookDownloaderService.java @@ -284,7 +284,7 @@ public class BookDownloaderService extends Service { } }; - final ZLNetworkRequest request = new ZLNetworkRequest(urlString) { + final ZLNetworkRequest request = new ZLNetworkRequest.Get(urlString) { public void handleStream(InputStream inputStream, int length) throws IOException, ZLNetworkException { final int updateIntervalMillis = 1000; // FIXME: remove hardcoded time constant diff --git a/src/org/geometerplus/android/fbreader/synchroniser/SynchroniserService.java b/src/org/geometerplus/android/fbreader/synchroniser/SynchroniserService.java index a0f2ea9db..1f9ad61a4 100644 --- a/src/org/geometerplus/android/fbreader/synchroniser/SynchroniserService.java +++ b/src/org/geometerplus/android/fbreader/synchroniser/SynchroniserService.java @@ -105,10 +105,10 @@ public class SynchroniserService extends Service implements IBookCollection.List return writer.toString(); } - private static abstract class Request extends ZLNetworkRequest { + private static abstract class JsonRequest extends ZLNetworkRequest.PostWithBody { private final static String BASE_URL = "https://demo.fbreader.org/app/"; - Request(String app, Object data) { + JsonRequest(String app, Object data) { super(BASE_URL + app, toJSON(data), false); } @@ -133,7 +133,7 @@ public class SynchroniserService extends Service implements IBookCollection.List return; } System.err.println("SHA-1: " + uid.Id); - myNetworkContext.performQuietly(new Request("books.by.hash", Collections.singletonMap("sha1", uid.Id)) { + myNetworkContext.performQuietly(new JsonRequest("books.by.hash", Collections.singletonMap("sha1", uid.Id)) { public void processResponse(Object response) { System.err.println("RESPONSE = " + response); } diff --git a/src/org/geometerplus/fbreader/network/AllCatalogsSearchItem.java b/src/org/geometerplus/fbreader/network/AllCatalogsSearchItem.java index b0faa07f6..2440902b7 100644 --- a/src/org/geometerplus/fbreader/network/AllCatalogsSearchItem.java +++ b/src/org/geometerplus/fbreader/network/AllCatalogsSearchItem.java @@ -55,7 +55,7 @@ public class AllCatalogsSearchItem extends SearchItem { } final NetworkOperationData data = link.createOperationData(loader); final ZLNetworkRequest request = link.simpleSearchRequest(pattern, data); - if (request != null && MimeType.APP_ATOM_XML.weakEquals(request.Mime)) { + if (request != null) { dataList.add(data); requestList.add(request); } diff --git a/src/org/geometerplus/fbreader/network/SingleCatalogSearchItem.java b/src/org/geometerplus/fbreader/network/SingleCatalogSearchItem.java index 3e060eec5..7d360d8d2 100644 --- a/src/org/geometerplus/fbreader/network/SingleCatalogSearchItem.java +++ b/src/org/geometerplus/fbreader/network/SingleCatalogSearchItem.java @@ -38,7 +38,7 @@ public class SingleCatalogSearchItem extends SearchItem { final NetworkOperationData data = Link.createOperationData(loader); ZLNetworkRequest request = Link.simpleSearchRequest(pattern, data); // TODO: possible infinite loop, use "continue link" instead - while (request != null && MimeType.APP_ATOM_XML.weakEquals(request.Mime)) { + while (request != null) { nc.perform(request); if (loader.confirmInterruption()) { return; diff --git a/src/org/geometerplus/fbreader/network/authentication/litres/LitResNetworkRequest.java b/src/org/geometerplus/fbreader/network/authentication/litres/LitResNetworkRequest.java index dcb7e078b..6b63efee4 100644 --- a/src/org/geometerplus/fbreader/network/authentication/litres/LitResNetworkRequest.java +++ b/src/org/geometerplus/fbreader/network/authentication/litres/LitResNetworkRequest.java @@ -25,7 +25,7 @@ import java.io.InputStream; import org.geometerplus.zlibrary.core.network.ZLNetworkException; import org.geometerplus.zlibrary.core.network.ZLNetworkRequest; -public class LitResNetworkRequest extends ZLNetworkRequest { +public class LitResNetworkRequest extends ZLNetworkRequest.PostWithMap { public final LitResAuthenticationXMLReader Reader; static String clean(String url) { diff --git a/src/org/geometerplus/fbreader/network/opds/OPDSBasketItem.java b/src/org/geometerplus/fbreader/network/opds/OPDSBasketItem.java index 52df28dd1..2dbbb554c 100644 --- a/src/org/geometerplus/fbreader/network/opds/OPDSBasketItem.java +++ b/src/org/geometerplus/fbreader/network/opds/OPDSBasketItem.java @@ -58,6 +58,6 @@ class OPDSBasketItem extends BasketItem { url = url.replace("{ids}", MiscUtil.join(ids, ",")); final OPDSCatalogItem.State state = opdsLink.createOperationData(loader); - doLoadChildren(state, opdsLink.createNetworkData(url, MimeType.APP_ATOM_XML, state)); + doLoadChildren(state, opdsLink.createNetworkData(url, state)); } } diff --git a/src/org/geometerplus/fbreader/network/opds/OPDSBookItem.java b/src/org/geometerplus/fbreader/network/opds/OPDSBookItem.java index 476bb10a4..76f89ab57 100644 --- a/src/org/geometerplus/fbreader/network/opds/OPDSBookItem.java +++ b/src/org/geometerplus/fbreader/network/opds/OPDSBookItem.java @@ -40,7 +40,7 @@ public class OPDSBookItem extends NetworkBookItem implements OPDSConstants { final CreateBookHandler handler = new CreateBookHandler(link, url); try { - nc.perform(new ZLNetworkRequest(url) { + nc.perform(new ZLNetworkRequest.Get(url) { @Override public void handleStream(InputStream inputStream, int length) throws IOException, ZLNetworkException { new OPDSXMLReader(handler, true).read(inputStream); @@ -263,7 +263,7 @@ public class OPDSBookItem extends NetworkBookItem implements OPDSConstants { return true; } - return nc.performQuietly(new ZLNetworkRequest(url) { + return nc.performQuietly(new ZLNetworkRequest.Get(url) { @Override public void handleStream(InputStream inputStream, int length) throws IOException, ZLNetworkException { new OPDSXMLReader(new LoadInfoHandler(url), true).read(inputStream); diff --git a/src/org/geometerplus/fbreader/network/opds/OPDSCatalogItem.java b/src/org/geometerplus/fbreader/network/opds/OPDSCatalogItem.java index d5f26c008..de47e477d 100644 --- a/src/org/geometerplus/fbreader/network/opds/OPDSCatalogItem.java +++ b/src/org/geometerplus/fbreader/network/opds/OPDSCatalogItem.java @@ -81,7 +81,7 @@ public class OPDSCatalogItem extends NetworkURLCatalogItem { myLoadingState = opdsLink.createOperationData(loader); doLoadChildren( - opdsLink.createNetworkData(getCatalogUrl(), MimeType.APP_ATOM_XML, myLoadingState) + opdsLink.createNetworkData(getCatalogUrl(), myLoadingState) ); } diff --git a/src/org/geometerplus/fbreader/network/opds/OPDSCustomNetworkLink.java b/src/org/geometerplus/fbreader/network/opds/OPDSCustomNetworkLink.java index 5afe03ae8..ca971bb0f 100644 --- a/src/org/geometerplus/fbreader/network/opds/OPDSCustomNetworkLink.java +++ b/src/org/geometerplus/fbreader/network/opds/OPDSCustomNetworkLink.java @@ -107,7 +107,7 @@ public class OPDSCustomNetworkLink extends OPDSNetworkLink implements ICustomNet ZLNetworkException error = null; try { - nc.perform(new ZLNetworkRequest(getUrl(UrlInfo.Type.Catalog), quietly) { + nc.perform(new ZLNetworkRequest.Get(getUrl(UrlInfo.Type.Catalog), quietly) { @Override public void handleStream(InputStream inputStream, int length) throws IOException, ZLNetworkException { final OPDSCatalogInfoHandler info = new OPDSCatalogInfoHandler(getURL(), OPDSCustomNetworkLink.this, opensearchDescriptionURLs); @@ -136,7 +136,7 @@ public class OPDSCustomNetworkLink extends OPDSNetworkLink implements ICustomNet if (!opensearchDescriptionURLs.isEmpty()) { LinkedList requests = new LinkedList(); for (String url : opensearchDescriptionURLs) { - requests.add(new ZLNetworkRequest(url, quietly) { + requests.add(new ZLNetworkRequest.Get(url, quietly) { @Override public void handleStream(InputStream inputStream, int length) throws IOException, ZLNetworkException { new OpenSearchXMLReader(getURL(), descriptions).read(inputStream); diff --git a/src/org/geometerplus/fbreader/network/opds/OPDSLinkReader.java b/src/org/geometerplus/fbreader/network/opds/OPDSLinkReader.java index 06583c5ab..11c680671 100644 --- a/src/org/geometerplus/fbreader/network/opds/OPDSLinkReader.java +++ b/src/org/geometerplus/fbreader/network/opds/OPDSLinkReader.java @@ -44,7 +44,7 @@ public class OPDSLinkReader { final File dirFile = new File(Paths.networkCacheDirectory()); if (!dirFile.exists() && !dirFile.mkdirs()) { - nc.perform(new ZLNetworkRequest(CATALOGS_URL) { + nc.perform(new ZLNetworkRequest.Get(CATALOGS_URL) { @Override public void handleStream(InputStream inputStream, int length) throws IOException, ZLNetworkException { xmlReader.read(inputStream); diff --git a/src/org/geometerplus/fbreader/network/opds/OPDSNetworkLink.java b/src/org/geometerplus/fbreader/network/opds/OPDSNetworkLink.java index 02c3a890e..50dcce675 100644 --- a/src/org/geometerplus/fbreader/network/opds/OPDSNetworkLink.java +++ b/src/org/geometerplus/fbreader/network/opds/OPDSNetworkLink.java @@ -82,7 +82,7 @@ public abstract class OPDSNetworkLink extends AbstractNetworkLink { NotChecked */ - ZLNetworkRequest createNetworkData(String url, MimeType mime, final OPDSCatalogItem.State state) { + ZLNetworkRequest createNetworkData(String url, final OPDSCatalogItem.State state) { if (url == null) { return null; } @@ -90,7 +90,7 @@ public abstract class OPDSNetworkLink extends AbstractNetworkLink { final NetworkCatalogItem catalogItem = state.Loader.getTree().Item; library.startLoading(catalogItem); url = rewriteUrl(url, false); - return new ZLNetworkRequest(url, mime, null, false) { + return new ZLNetworkRequest.Get(url, false) { @Override public void handleStream(InputStream inputStream, int length) throws IOException, ZLNetworkException { if (state.Loader.confirmInterruption()) { @@ -123,18 +123,18 @@ public abstract class OPDSNetworkLink extends AbstractNetworkLink { public ZLNetworkRequest simpleSearchRequest(String pattern, NetworkOperationData data) { final UrlInfo info = getUrlInfo(UrlInfo.Type.Search); - if (info == null || info.Url == null) { + if (info == null || info.Url == null || !MimeType.APP_ATOM_XML.weakEquals(info.Mime)) { return null; } try { pattern = URLEncoder.encode(pattern, "utf-8"); } catch (UnsupportedEncodingException e) { } - return createNetworkData(info.Url.replace("%s", pattern), info.Mime, (OPDSCatalogItem.State)data); + return createNetworkData(info.Url.replace("%s", pattern), (OPDSCatalogItem.State)data); } public ZLNetworkRequest resume(NetworkOperationData data) { - return createNetworkData(data.ResumeURI, MimeType.APP_ATOM_XML, (OPDSCatalogItem.State)data); + return createNetworkData(data.ResumeURI, (OPDSCatalogItem.State)data); } public NetworkCatalogItem libraryItem() { diff --git a/src/org/geometerplus/fbreader/network/rss/RSSCatalogItem.java b/src/org/geometerplus/fbreader/network/rss/RSSCatalogItem.java index fd0d4003f..382cd6ff6 100644 --- a/src/org/geometerplus/fbreader/network/rss/RSSCatalogItem.java +++ b/src/org/geometerplus/fbreader/network/rss/RSSCatalogItem.java @@ -52,7 +52,7 @@ public class RSSCatalogItem extends NetworkURLCatalogItem { final RSSNetworkLink rssLink = (RSSNetworkLink)Link; myLoadingState = rssLink.createOperationData(loader); - doLoadChildren(rssLink.createNetworkData(getCatalogUrl(), MimeType.APP_RSS_XML, myLoadingState)); + doLoadChildren(rssLink.createNetworkData(getCatalogUrl(), myLoadingState)); } private void doLoadChildren(ZLNetworkRequest networkRequest) throws ZLNetworkException { diff --git a/src/org/geometerplus/fbreader/network/rss/RSSNetworkLink.java b/src/org/geometerplus/fbreader/network/rss/RSSNetworkLink.java index 945330e81..d87454d21 100644 --- a/src/org/geometerplus/fbreader/network/rss/RSSNetworkLink.java +++ b/src/org/geometerplus/fbreader/network/rss/RSSNetworkLink.java @@ -46,7 +46,7 @@ public class RSSNetworkLink extends AbstractNetworkLink implements IPredefinedNe myPredefinedId = predefinedId; } - ZLNetworkRequest createNetworkData(String url, MimeType mime, final RSSCatalogItem.State result) { + ZLNetworkRequest createNetworkData(String url, final RSSCatalogItem.State result) { if (url == null) { return null; } @@ -55,7 +55,7 @@ public class RSSNetworkLink extends AbstractNetworkLink implements IPredefinedNe final NetworkCatalogItem catalogItem = result.Loader.getTree().Item; library.startLoading(catalogItem); - return new ZLNetworkRequest(url, mime, null, false) { + return new ZLNetworkRequest.Get(url, false) { @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public void handleStream(InputStream inputStream, int length) throws IOException, ZLNetworkException { @@ -100,8 +100,7 @@ public class RSSNetworkLink extends AbstractNetworkLink implements IPredefinedNe } @Override - public ZLNetworkRequest simpleSearchRequest(String pattern, - NetworkOperationData data) { + public ZLNetworkRequest simpleSearchRequest(String pattern, NetworkOperationData data) { return null; } diff --git a/src/org/geometerplus/zlibrary/core/network/ZLNetworkContext.java b/src/org/geometerplus/zlibrary/core/network/ZLNetworkContext.java index fbbe4224b..a6a5ab100 100644 --- a/src/org/geometerplus/zlibrary/core/network/ZLNetworkContext.java +++ b/src/org/geometerplus/zlibrary/core/network/ZLNetworkContext.java @@ -84,7 +84,7 @@ public abstract class ZLNetworkContext implements ZLNetworkManager.BearerAuthent } private final void downloadToFile(String url, final File outFile, final int bufferSize) throws ZLNetworkException { - myManager.perform(new ZLNetworkRequest(url) { + myManager.perform(new ZLNetworkRequest.Get(url) { public void handleStream(InputStream inputStream, int length) throws IOException, ZLNetworkException { OutputStream outStream = new FileOutputStream(outFile); try { diff --git a/src/org/geometerplus/zlibrary/core/network/ZLNetworkManager.java b/src/org/geometerplus/zlibrary/core/network/ZLNetworkManager.java index 3632d7f98..df49a8071 100644 --- a/src/org/geometerplus/zlibrary/core/network/ZLNetworkManager.java +++ b/src/org/geometerplus/zlibrary/core/network/ZLNetworkManager.java @@ -33,15 +33,19 @@ import org.apache.http.client.methods.*; import org.apache.http.client.protocol.ClientContext; import org.apache.http.cookie.Cookie; import org.apache.http.entity.StringEntity; +import org.apache.http.entity.mime.HttpMultipartMode; +import org.apache.http.entity.mime.MultipartEntity; +import org.apache.http.entity.mime.content.InputStreamBody; import org.apache.http.impl.client.*; import org.apache.http.message.BasicNameValuePair; import org.apache.http.params.*; import org.apache.http.protocol.HttpContext; import org.apache.http.protocol.BasicHttpContext; +import org.geometerplus.zlibrary.core.filesystem.ZLFile; +import org.geometerplus.zlibrary.core.options.ZLStringOption; import org.geometerplus.zlibrary.core.util.MiscUtil; import org.geometerplus.zlibrary.core.util.ZLNetworkUtil; -import org.geometerplus.zlibrary.core.options.ZLStringOption; public class ZLNetworkManager { private static ZLNetworkManager ourManager; @@ -320,29 +324,35 @@ public class ZLNetworkManager { } }; final HttpRequestBase httpRequest; - if (request.PostData != null) { + if (request instanceof ZLNetworkRequest.Get) { + httpRequest = new HttpGet(request.URL); + } else if (request instanceof ZLNetworkRequest.PostWithBody) { httpRequest = new HttpPost(request.URL); - ((HttpPost)httpRequest).setEntity(new StringEntity(request.PostData, "utf-8")); + ((HttpPost)httpRequest).setEntity(new StringEntity(((ZLNetworkRequest.PostWithBody)request).Body, "utf-8")); /* httpConnection.setRequestProperty( "Content-Length", - Integer.toString(request.PostData.getBytes().length) - ); - httpConnection.setRequestProperty( - "Content-Type", - "application/x-www-form-urlencoded" + Integer.toString(request.Body.getBytes().length) ); */ - } else if (!request.PostParameters.isEmpty()) { + } else if (request instanceof ZLNetworkRequest.PostWithMap) { + final Map parameters = + ((ZLNetworkRequest.PostWithMap)request).PostParameters; httpRequest = new HttpPost(request.URL); final List list = - new ArrayList(request.PostParameters.size()); - for (Map.Entry entry : request.PostParameters.entrySet()) { + new ArrayList(parameters.size()); + for (Map.Entry entry : parameters.entrySet()) { list.add(new BasicNameValuePair(entry.getKey(), entry.getValue())); } ((HttpPost)httpRequest).setEntity(new UrlEncodedFormEntity(list, "utf-8")); + } else if (request instanceof ZLNetworkRequest.FileUpload) { + final ZLFile file = ((ZLNetworkRequest.FileUpload)request).File; + httpRequest = new HttpPost(request.URL); + final MultipartEntity data = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE); + data.addPart("file", new InputStreamBody(file.getInputStream(), file.getPath())); + ((HttpPost)httpRequest).setEntity(data); } else { - httpRequest = new HttpGet(request.URL); + throw new ZLNetworkException(true, "Unknown request type"); } httpRequest.setHeader("User-Agent", ZLNetworkUtil.getUserAgent()); if (!request.isQuiet()) { diff --git a/src/org/geometerplus/zlibrary/core/network/ZLNetworkRequest.java b/src/org/geometerplus/zlibrary/core/network/ZLNetworkRequest.java index 1e1e01d0d..eb2ee051a 100644 --- a/src/org/geometerplus/zlibrary/core/network/ZLNetworkRequest.java +++ b/src/org/geometerplus/zlibrary/core/network/ZLNetworkRequest.java @@ -24,40 +24,67 @@ import java.io.IOException; import java.util.Map; import java.util.HashMap; -import org.geometerplus.zlibrary.core.util.MimeType; +import org.geometerplus.zlibrary.core.filesystem.ZLFile; public abstract class ZLNetworkRequest { + public static abstract class Get extends ZLNetworkRequest { + protected Get(String url) { + this(url, false); + } + + protected Get(String url, boolean quiet) { + super(url, quiet); + } + } + + public static abstract class PostWithMap extends ZLNetworkRequest { + public final Map PostParameters = new HashMap(); + + protected PostWithMap(String url) { + this(url, false); + } + + protected PostWithMap(String url, boolean quiet) { + super(url, quiet); + } + + public void addPostParameter(String name, String value) { + PostParameters.put(name, value); + } + } + + public static abstract class PostWithBody extends ZLNetworkRequest { + public final String Body; + + protected PostWithBody(String url, String body, boolean quiet) { + super(url, quiet); + Body = body; + } + } + + public static abstract class FileUpload extends ZLNetworkRequest { + public final ZLFile File; + + protected FileUpload(String url, ZLFile file, boolean quiet) { + super(url, quiet); + File = file; + } + } + String URL; - public final String PostData; - public final Map PostParameters = new HashMap(); - public final MimeType Mime; public final Map Headers = new HashMap(); private final boolean myIsQuiet; - protected ZLNetworkRequest(String url) { + private ZLNetworkRequest(String url) { this(url, false); } - protected ZLNetworkRequest(String url, boolean quiet) { - this(url, null, quiet); - } - - protected ZLNetworkRequest(String url, String postData, boolean quiet) { - this(url, MimeType.NULL, postData, quiet); - } - - protected ZLNetworkRequest(String url, MimeType mime, String postData, boolean quiet) { + private ZLNetworkRequest(String url, boolean quiet) { URL = url; - Mime = mime; - PostData = postData; myIsQuiet = quiet; } - public void addPostParameter(String name, String value) { - PostParameters.put(name, value); - } - public void addHeader(String name, String value) { Headers.put(name, value); }