private Payload doInBackgroundRegister(Payload data) { String username = (String) data.data[0]; String password = (String) data.data[1]; BasicHttpSyncer server = new RemoteServer(this, null); HttpResponse ret = server.register(username, password); String hostkey = null; boolean valid = false; data.returnType = ret.getStatusLine().getStatusCode(); String status = null; if (data.returnType == 200) { try { JSONObject jo = (new JSONObject(server.stream2String(ret.getEntity().getContent()))); status = jo.getString("status"); if (status.equals("ok")) { hostkey = jo.getString("hkey"); valid = (hostkey != null) && (hostkey.length() > 0); } } catch (JSONException e) { } catch (IllegalStateException e) { throw new RuntimeException(e); } catch (IOException e) { throw new RuntimeException(e); } } if (valid) { data.success = true; data.data = new String[] {username, hostkey}; } else { data.success = false; if (status != null) { data.data = new String[] {status}; } } return data; }
private Payload doInBackgroundLogin(Payload data) { String username = (String) data.data[0]; String password = (String) data.data[1]; BasicHttpSyncer server = new RemoteServer(this, null); HttpResponse ret = server.hostKey(username, password); String hostkey = null; boolean valid = false; if (ret != null) { data.returnType = ret.getStatusLine().getStatusCode(); Log.i( AnkiDroidApp.TAG, "doInBackgroundLogin - response from server: " + data.returnType + " (" + ret.getStatusLine().getReasonPhrase() + ")"); if (data.returnType == 200) { try { JSONObject jo = (new JSONObject(server.stream2String(ret.getEntity().getContent()))); hostkey = jo.getString("key"); valid = (hostkey != null) && (hostkey.length() > 0); } catch (JSONException e) { valid = false; } catch (IllegalStateException e) { throw new RuntimeException(e); } catch (IOException e) { throw new RuntimeException(e); } } } else { Log.e(AnkiDroidApp.TAG, "doInBackgroundLogin - empty response from server"); } if (valid) { data.success = true; data.data = new String[] {username, hostkey}; } else { data.success = false; } return data; }
/** * Downloads any missing media files according to the mediaURL deckvar. * * @param data * @return The return type contains data.resultType and an array of Integer in data.data. * data.data[0] is the number of total missing media, data.data[1] is the number of downloaded * ones. */ private Payload doInBackgroundDownloadMissingMedia(Payload data) { Log.i(AnkiDroidApp.TAG, "DownloadMissingMedia"); HashMap<String, String> missingPaths = new HashMap<String, String>(); HashMap<String, String> missingSums = new HashMap<String, String>(); Decks deck = (Decks) data.data[0]; data.result = deck; // pass it to the return object so we close the deck in the deck picker String syncName = ""; // deck.getDeckName(); data.success = false; data.data = new Object[] {0, 0, 0}; // if (!deck.hasKey("mediaURL")) { // data.success = true; // return data; // } String urlbase = ""; // deck.getVar("mediaURL"); if (urlbase.equals("")) { data.success = true; return data; } String mdir = ""; // deck.mediaDir(true); int totalMissing = 0; int missing = 0; int grabbed = 0; Cursor cursor = null; try { cursor = null; // deck.getDB().getDatabase().rawQuery("SELECT filename, originalPath FROM media", // null); String path = null; String f = null; while (cursor.moveToNext()) { f = cursor.getString(0); path = mdir + "/" + f; File file = new File(path); if (!file.exists()) { missingPaths.put(f, path); missingSums.put(f, cursor.getString(1)); Log.i(AnkiDroidApp.TAG, "Missing file: " + f); } } } finally { if (cursor != null) { cursor.close(); } } totalMissing = missingPaths.size(); data.data[0] = new Integer(totalMissing); if (totalMissing == 0) { data.success = true; return data; } publishProgress(Boolean.FALSE, new Integer(totalMissing), new Integer(0), syncName); URL url = null; HttpURLConnection connection = null; String path = null; String sum = null; int readbytes = 0; byte[] buf = new byte[4096]; for (String file : missingPaths.keySet()) { try { android.net.Uri uri = android.net.Uri.parse(Uri.encode(urlbase, ":/@%") + Uri.encode(file)); url = new URI(uri.toString()).toURL(); connection = (HttpURLConnection) url.openConnection(); connection.connect(); if (connection.getResponseCode() == 200) { path = missingPaths.get(file); InputStream is = connection.getInputStream(); BufferedInputStream bis = new BufferedInputStream(is, 4096); FileOutputStream fos = new FileOutputStream(path); while ((readbytes = bis.read(buf, 0, 4096)) != -1) { fos.write(buf, 0, readbytes); Log.i(AnkiDroidApp.TAG, "Downloaded " + readbytes + " file: " + path); } fos.close(); // Verify with checksum sum = missingSums.get(file); if (true) { // sum.equals("") || sum.equals(Utils.fileChecksum(path))) { grabbed++; } else { // Download corrupted, delete file Log.i(AnkiDroidApp.TAG, "Downloaded media file " + path + " failed checksum."); File f = new File(path); f.delete(); missing++; } } else { Log.e( AnkiDroidApp.TAG, "Connection error (" + connection.getResponseCode() + ") while retrieving media file " + urlbase + file); Log.e(AnkiDroidApp.TAG, "Connection message: " + connection.getResponseMessage()); if (missingSums.get(file).equals("")) { // Ignore and keep going missing++; } else { data.success = false; data.data = new Object[] {file}; return data; } } connection.disconnect(); } catch (URISyntaxException e) { Log.e(AnkiDroidApp.TAG, Log.getStackTraceString(e)); } catch (MalformedURLException e) { Log.e(AnkiDroidApp.TAG, Log.getStackTraceString(e)); Log.e(AnkiDroidApp.TAG, "MalformedURLException while download media file " + path); if (missingSums.get(file).equals("")) { // Ignore and keep going missing++; } else { data.success = false; data.data = new Object[] {file}; return data; } } catch (IOException e) { Log.e(AnkiDroidApp.TAG, Log.getStackTraceString(e)); Log.e(AnkiDroidApp.TAG, "IOException while download media file " + path); if (missingSums.get(file).equals("")) { // Ignore and keep going missing++; } else { data.success = false; data.data = new Object[] {file}; return data; } } finally { if (connection != null) { connection.disconnect(); } } publishProgress( Boolean.TRUE, new Integer(totalMissing), new Integer(grabbed + missing), syncName); } data.data[1] = new Integer(grabbed); data.data[2] = new Integer(missing); data.success = true; return data; }
private Payload doInBackgroundSync(Payload data) { // for for doInBackgroundLoadDeckCounts if any DeckTask.waitToFinish(); String hkey = (String) data.data[0]; boolean media = (Boolean) data.data[1]; String conflictResolution = (String) data.data[2]; int mediaUsn = (Integer) data.data[3]; Collection col = Collection.currentCollection(); if (col == null) { data.success = false; data.result = new Object[] {"genericError"}; return data; } String path = col.getPath(); BasicHttpSyncer server = new RemoteServer(this, hkey); Syncer client = new Syncer(col, server); // run sync and check state boolean noChanges = false; if (conflictResolution == null) { Log.i(AnkiDroidApp.TAG, "Sync - starting sync"); publishProgress(R.string.sync_prepare_syncing); Object[] ret = client.sync(this); mediaUsn = client.getmMediaUsn(); if (ret == null) { data.success = false; data.result = new Object[] {"genericError"}; return data; } String retCode = (String) ret[0]; if (!retCode.equals("noChanges") && !retCode.equals("success")) { data.success = false; data.result = ret; // note mediaUSN for later data.data = new Object[] {mediaUsn}; return data; } // save and note success state col.save(); if (retCode.equals("noChanges")) { // publishProgress(R.string.sync_no_changes_message); noChanges = true; } else { // publishProgress(R.string.sync_database_success); } } else { try { server = new FullSyncer(col, hkey, this); if (conflictResolution.equals("upload")) { Log.i(AnkiDroidApp.TAG, "Sync - fullsync - upload collection"); publishProgress(R.string.sync_preparing_full_sync_message); Object[] ret = server.upload(); if (ret == null) { data.success = false; data.result = new Object[] {"genericError"}; data.data = new Object[] {Collection.openCollection(path)}; return data; } if (!((String) ret[0]).equals(BasicHttpSyncer.ANKIWEB_STATUS_OK)) { data.success = false; data.result = ret; data.data = new Object[] {Collection.openCollection(path)}; return data; } } else if (conflictResolution.equals("download")) { Log.i(AnkiDroidApp.TAG, "Sync - fullsync - download collection"); publishProgress(R.string.sync_downloading_message); Object[] ret = server.download(); if (ret == null) { data.success = false; data.result = new Object[] {"genericError"}; data.data = new Object[] {Collection.openCollection(path)}; return data; } if (!((String) ret[0]).equals("success")) { data.success = false; data.result = ret; data.data = new Object[] {Collection.openCollection(path)}; return data; } } } finally { publishProgress(R.string.sync_reload_message); col = Collection.openCollection(path); } } // then move on to media sync boolean noMediaChanges = false; if (media) { server = new RemoteMediaServer(hkey, this); MediaSyncer mediaClient = new MediaSyncer(col, (RemoteMediaServer) server); String ret = mediaClient.sync(mediaUsn, this); if (ret.equals("noChanges")) { publishProgress(R.string.sync_media_no_changes); noMediaChanges = true; } else { publishProgress(R.string.sync_media_success); } } if (noChanges && noMediaChanges) { data.success = false; data.result = new Object[] {"noChanges"}; return data; } else { data.success = true; TreeSet<Object[]> decks = col.getSched().deckDueTree(Sched.DECK_INFORMATION_SIMPLE_COUNTS); int[] counts = new int[] {0, 0, 0}; for (Object[] deck : decks) { if (((String[]) deck[0]).length == 1) { counts[0] += (Integer) deck[2]; counts[1] += (Integer) deck[3]; counts[2] += (Integer) deck[4]; } } data.result = decks; data.data = new Object[] {conflictResolution, col, col.getSched().eta(counts), col.cardCount()}; return data; } }