/* * Specify the code you want to run in the sync adapter. The entire * sync adapter runs in a background thread, so you don't have to set * up your own background processing. */ @Override public void onPerformSync( Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) { SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); boolean wifiOnly = sharedPreferences.getBoolean("pref_wlan_only", false); Log.d(TAG, "Sync only via WIFI? " + wifiOnly); boolean hasWifiConnection = NetworkStateHelper.hasWifiConnection(context); Log.d(TAG, "Has WIFI connection?" + hasWifiConnection); if (!wifiOnly || hasWifiConnection) { Log.d(TAG, "*************** SYNCING: " + ++syncNumber + " *****************"); ServerQueries serverQueries = new ServerQueries(context); Cursor c = serverQueries.getAllServers(); if (c.moveToFirst()) { while (!c.isAfterLast()) { try { getNewNewsForServer( c.getLong(ServerQueries.COL_ID), c.getString(ServerQueries.COL_NAME), c.getInt(ServerQueries.COL_PORT), c.getInt(ServerQueries.COL_AUTH) == 1, c.getString(ServerQueries.COL_USER), c.getString(ServerQueries.COL_PASSWORD)); } catch (IOException | LoginException e) { e.printStackTrace(); } finally { // if we get interrupted during syncing a newsgroup, store date of last message that was // fetched in order // to start the sync next time at the right time if (currentNewsgroupId != -1 && currentMessageDate != -1) { Log.d( TAG, "-----> Sync interrupted! Last sync date in group " + currentNewsgroupId + " is " + currentMessageDate); NewsgroupQueries newsgroupQueries = new NewsgroupQueries(context); newsgroupQueries.setLastSyncDate(currentNewsgroupId, currentMessageDate); currentMessageDate = -1; currentNewsgroupId = -1; } } c.moveToNext(); } Log.d(TAG, "************ FINISHED SYNC: " + syncNumber + "*********************"); } c.close(); } }
@Override public boolean authenticate() { if (!super.authenticate()) { LOG.error( String.format( "blank username or password detected, no %s xword will be downloaded", this.getType())); return false; } final HttpUriRequest loginGet = RequestBuilder.get().setUri(NYT_LOGIN_URL).build(); final String loginPage; try (final CloseableHttpResponse getResponse = this.getHttpClient().execute(loginGet)) { loginPage = EntityUtils.toString(getResponse.getEntity()); } catch (final IOException e) { LOG.error("error while navigating to NYT login page", e); return false; } final String token; final String expires; try { final TagNode node = this.getCleaner().clean(loginPage); final Object[] foundNodes = node.evaluateXPath("//input[@name='token']"); if (foundNodes.length != 1) { this.throwLoginException( "unexpected login page, found %d hidden token input elements, expected 1", foundNodes.length); } final TagNode hiddenTokenInput = (TagNode) foundNodes[0]; token = hiddenTokenInput.getAttributeByName("value"); LOG.debug("found hidden input token {}", token); final Object[] foundExpiresNodes = node.evaluateXPath("//input[@name='expires']"); if (foundExpiresNodes.length != 1) { this.throwLoginException( "unexpected login page, found %d hidden token expiration input elements, expected 1", foundNodes.length); } final TagNode hiddenTokenExpiresInput = (TagNode) foundExpiresNodes[0]; expires = hiddenTokenExpiresInput.getAttributeByName("value"); LOG.debug("found hidden input token expiration {}", expires); } catch (LoginException | XPatherException e) { LOG.error("error while pulling login tokens from NYT login page", e); return false; } // @formatter:off final HttpUriRequest loginPost = RequestBuilder.post() .setUri("https://myaccount.nytimes.com/auth/login") .addParameter("is_continue", Boolean.FALSE.toString()) .addParameter("token", token) .addParameter("expires", expires) .addParameter("userid", this.getLoginInfo().getUsername()) .addParameter("password", this.getLoginInfo().getPassword()) .addParameter("remember", Boolean.TRUE.toString()) .build(); // @formatter:on try (CloseableHttpResponse postResponse = this.getHttpClient().execute(loginPost)) { // successful NYT login should give 302 status final int responseStatus = postResponse.getStatusLine().getStatusCode(); if (responseStatus != 302) { final String errorMessage = String.format("did not detect expected 302 redirect, got %d instead", responseStatus); throw new LoginException(errorMessage); } // successful NYT login redirects to the NYT homepage final Header location = postResponse.getFirstHeader("Location"); // have seen this redirect both with and without the final portion final Pattern expectedRedirectLocation = Pattern.compile("http://www.nytimes.com(\\?login=email)*"); final String actualRedirectLocation = location.getValue(); final Matcher matcher = expectedRedirectLocation.matcher(actualRedirectLocation); if (!matcher.matches()) { final String errorMessage = String.format( "redirect to unexpected URL, expected %s, found Location=%s instead", expectedRedirectLocation, actualRedirectLocation); throw new LoginException(errorMessage); } // successful NYT login should set a few cookies final Header[] cookies = postResponse.getHeaders("Set-Cookie"); if (cookies.length < 1) { throw new LoginException("no post login cookies set, login likely failed"); } } catch (final IOException | LoginException e) { LOG.error("error while logging in, e={}", e.getMessage()); return false; } LOG.info("successfully logged in to nyt"); return true; }