diff --git a/src/org/geometerplus/android/fbreader/synchroniser/SynchroniserService.java b/src/org/geometerplus/android/fbreader/synchroniser/SynchroniserService.java index 1f9ad61a4..0a995697b 100644 --- a/src/org/geometerplus/android/fbreader/synchroniser/SynchroniserService.java +++ b/src/org/geometerplus/android/fbreader/synchroniser/SynchroniserService.java @@ -28,6 +28,7 @@ import android.os.IBinder; import org.json.simple.JSONValue; +import org.geometerplus.zlibrary.core.filesystem.ZLPhysicalFile; import org.geometerplus.zlibrary.core.network.*; import org.geometerplus.zlibrary.ui.android.network.SQLiteCookieDatabase; import org.geometerplus.fbreader.book.*; @@ -84,7 +85,7 @@ public class SynchroniserService extends Service implements IBookCollection.List } myProcessed.add(book); System.err.println("Processing " + book.getTitle() + " [" + book.File.getPath() + "]"); - uploadBookToServer(book); + uploadBookToServer(book.File.getPhysicalFile()); } System.err.println("BYE-BYE THREAD"); ourSynchronizationThread = null; @@ -105,9 +106,10 @@ public class SynchroniserService extends Service implements IBookCollection.List return writer.toString(); } - private static abstract class JsonRequest extends ZLNetworkRequest.PostWithBody { - private final static String BASE_URL = "https://demo.fbreader.org/app/"; + private final static String DOMAIN = "demo.fbreader.org"; + private final static String BASE_URL = "https://" + DOMAIN + "/app/"; + private static abstract class JsonRequest extends ZLNetworkRequest.PostWithBody { JsonRequest(String app, Object data) { super(BASE_URL + app, toJSON(data), false); } @@ -126,18 +128,61 @@ public class SynchroniserService extends Service implements IBookCollection.List protected abstract void processResponse(Object response); } - private void uploadBookToServer(Book book) { - final UID uid = BookUtil.createUid(book.File.getPhysicalFile(), "SHA-1"); + private static final class UploadRequest extends ZLNetworkRequest.FileUpload { + UploadRequest(File file) { + super(BASE_URL + "book.upload", file, false); + } + + @Override + public void handleStream(InputStream stream, int length) throws IOException, ZLNetworkException { + final BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); + final StringBuilder buffer = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + buffer.append(line); + } + final Object response = JSONValue.parse(buffer.toString()); + if (response instanceof Map && ((Map)response).isEmpty()) { + System.err.println("UPLOADED SUCCESSFULLY"); + } else { + System.err.println("UPLOAD FAILURE: " + response); + } + } + } + + private void uploadBookToServer(ZLPhysicalFile file) { + final UID uid = BookUtil.createUid(file, "SHA-1"); if (uid == null) { System.err.println("Failed: SHA-1 checksum not computed"); return; } - System.err.println("SHA-1: " + uid.Id); - myNetworkContext.performQuietly(new JsonRequest("books.by.hash", Collections.singletonMap("sha1", uid.Id)) { - public void processResponse(Object response) { - System.err.println("RESPONSE = " + response); + final Map result = new HashMap(); + final JsonRequest verificationRequest = + new JsonRequest("books.by.hash", Collections.singletonMap("sha1", uid.Id)) { + @Override + public void processResponse(Object response) { + result.put("result", response); + } + }; + myNetworkContext.performQuietly(verificationRequest); + final String csrfToken = myNetworkContext.getCookieValue(DOMAIN, "csrftoken"); + final Object response = result.get("result"); + if (response == null) { + System.err.println("UNEXPECTED ERROR: NO RESPONSE"); + } else if (!(response instanceof List)) { + System.err.println("UNEXPECTED RESPONSE: " + response); + } else if (!((List)response).isEmpty()) { + System.err.println("BOOK ALREADY UPLOADED"); + } else { + try { + final UploadRequest uploadRequest = new UploadRequest(file.javaFile()); + uploadRequest.addHeader("Referer", verificationRequest.getURL()); + uploadRequest.addHeader("X-CSRFToken", csrfToken); + myNetworkContext.perform(uploadRequest); + } catch (ZLNetworkException e) { + e.printStackTrace(); } - }); + } } @Override diff --git a/src/org/geometerplus/zlibrary/core/network/ZLNetworkContext.java b/src/org/geometerplus/zlibrary/core/network/ZLNetworkContext.java index a6a5ab100..566309886 100644 --- a/src/org/geometerplus/zlibrary/core/network/ZLNetworkContext.java +++ b/src/org/geometerplus/zlibrary/core/network/ZLNetworkContext.java @@ -25,6 +25,7 @@ import java.util.HashSet; import java.util.List; import org.apache.http.client.CookieStore; +import org.apache.http.cookie.Cookie; public abstract class ZLNetworkContext implements ZLNetworkManager.BearerAuthenticator { private final ZLNetworkManager myManager = ZLNetworkManager.Instance(); @@ -36,6 +37,15 @@ public abstract class ZLNetworkContext implements ZLNetworkManager.BearerAuthent return myManager.CookieStore; } + public String getCookieValue(String domain, String name) { + for (Cookie c : cookieStore().getCookies()) { + if (domain.equals(c.getDomain()) && name.equals(c.getName())) { + return c.getValue(); + } + } + return null; + } + public boolean performQuietly(ZLNetworkRequest request) { try { perform(request); diff --git a/src/org/geometerplus/zlibrary/core/network/ZLNetworkManager.java b/src/org/geometerplus/zlibrary/core/network/ZLNetworkManager.java index df49a8071..4f1299c9a 100644 --- a/src/org/geometerplus/zlibrary/core/network/ZLNetworkManager.java +++ b/src/org/geometerplus/zlibrary/core/network/ZLNetworkManager.java @@ -35,14 +35,13 @@ 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.entity.mime.content.FileBody; 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; @@ -346,10 +345,11 @@ public class ZLNetworkManager { } ((HttpPost)httpRequest).setEntity(new UrlEncodedFormEntity(list, "utf-8")); } else if (request instanceof ZLNetworkRequest.FileUpload) { - final ZLFile file = ((ZLNetworkRequest.FileUpload)request).File; + final ZLNetworkRequest.FileUpload uploadRequest = (ZLNetworkRequest.FileUpload)request; + final File 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())); + data.addPart("file", new FileBody(uploadRequest.File)); ((HttpPost)httpRequest).setEntity(data); } else { throw new ZLNetworkException(true, "Unknown request type"); @@ -364,30 +364,17 @@ public class ZLNetworkManager { httpRequest.setHeader(header.getKey(), header.getValue()); } httpClient.setCredentialsProvider(new MyCredentialsProvider(httpRequest, request.isQuiet())); - HttpResponse response = null; - IOException lastException = null; - for (int retryCounter = 0; retryCounter < 3 && entity == null; ++retryCounter) { - try { - response = execute(httpClient, httpRequest, httpContext, authenticator); - entity = response.getEntity(); - lastException = null; - if (response.getStatusLine().getStatusCode() == HttpURLConnection.HTTP_UNAUTHORIZED) { - final AuthState state = (AuthState)httpContext.getAttribute(ClientContext.TARGET_AUTH_STATE); - if (state != null) { - final AuthScopeKey key = new AuthScopeKey(state.getAuthScope()); - if (myCredentialsCreator.removeCredentials(key)) { - entity = null; - } - } + final HttpResponse response = execute(httpClient, httpRequest, httpContext, authenticator); + entity = response.getEntity(); + if (response.getStatusLine().getStatusCode() == HttpURLConnection.HTTP_UNAUTHORIZED) { + final AuthState state = (AuthState)httpContext.getAttribute(ClientContext.TARGET_AUTH_STATE); + if (state != null) { + final AuthScopeKey key = new AuthScopeKey(state.getAuthScope()); + if (myCredentialsCreator.removeCredentials(key)) { + entity = null; } - } catch (IOException e) { - e.printStackTrace(); - lastException = e; } } - if (lastException != null) { - throw lastException; - } final int responseCode = response.getStatusLine().getStatusCode(); InputStream stream = null; diff --git a/src/org/geometerplus/zlibrary/core/network/ZLNetworkRequest.java b/src/org/geometerplus/zlibrary/core/network/ZLNetworkRequest.java index eb2ee051a..01759e294 100644 --- a/src/org/geometerplus/zlibrary/core/network/ZLNetworkRequest.java +++ b/src/org/geometerplus/zlibrary/core/network/ZLNetworkRequest.java @@ -19,13 +19,10 @@ package org.geometerplus.zlibrary.core.network; -import java.io.InputStream; -import java.io.IOException; +import java.io.*; import java.util.Map; import java.util.HashMap; -import org.geometerplus.zlibrary.core.filesystem.ZLFile; - public abstract class ZLNetworkRequest { public static abstract class Get extends ZLNetworkRequest { protected Get(String url) { @@ -63,9 +60,9 @@ public abstract class ZLNetworkRequest { } public static abstract class FileUpload extends ZLNetworkRequest { - public final ZLFile File; + final File File; - protected FileUpload(String url, ZLFile file, boolean quiet) { + protected FileUpload(String url, File file, boolean quiet) { super(url, quiet); File = file; }