package io.codetail.client.mover; import android.accounts.Account; import android.accounts.AccountManager; import android.os.Bundle; import android.text.Html; import org.json.JSONException; import org.json.JSONObject; import org.jsoup.Jsoup; import java.io.IOException; import java.net.HttpCookie; import java.util.List; import codetail.utils.ResourceUtils; import io.codetail.Constants; import io.codetail.WatchMeApplication; import io.codetail.client.BaseNetworkJob; import io.codetail.client.auth.Authenticator; import io.codetail.watchme.R; import io.codetail.work.Params; import retrofit.RetrofitError; import retrofit.client.Header; import retrofit.client.Response; import retrofit.mime.TypedByteArray; import static android.accounts.AccountManager.ERROR_CODE_NETWORK_ERROR; import static android.accounts.AccountManager.KEY_AUTHTOKEN; import static android.accounts.AccountManager.KEY_ERROR_CODE; import static io.codetail.client.auth.BasicAccountAuthenticator.ERROR_CODE_INVALID_USER_DATA; import static io.codetail.fragments.NavigationFragment.USER_PICTURE_URL; public class MoverAuthenticator implements Authenticator { MoverService mService; Account mAccount; String mPassword; boolean mSigning; public MoverAuthenticator(MoverService service){ mService = service; } @Override public CharSequence getHeadline() { return ResourceUtils.getString(R.string.mover_auth_headline); } @Override public CharSequence getDescription() { return Html.fromHtml(ResourceUtils.getString(R.string.mover_auth_description)); } @Override public void login(Account account, String password) { mAccount = account; mPassword = password; mSigning = true; Constants.getJobManager().addJob(new AuthorizeJob(this)); } @Override public void logout(Account account) { } @Override public Bundle getAuthToken(AccountManager manager, Account account) { if(!mSigning){ mPassword = manager.getPassword(account); } Bundle result = new Bundle(); try { Response response = mService.signIn(account.name, mPassword); if (isResponseSuccess(response)) { JSONObject json = asJson(asString(response)); if (json == null || json.has("errors") || json.has("error")) { result.putInt(KEY_ERROR_CODE, ERROR_CODE_INVALID_USER_DATA); return result; } for (Header header : response.getHeaders()) { if (isCookiesHeader(header)) { String cookies = header.getValue(); String token = findToken(HttpCookie.parse(cookies)); if (token != null) { result.putString(KEY_AUTHTOKEN, token); result.putString(USER_PICTURE_URL, findUserImage(mService.channel(account.name))); } } } } else { result.putInt(KEY_ERROR_CODE, ERROR_CODE_NETWORK_ERROR); } }catch (RetrofitError error){ result.putInt(KEY_ERROR_CODE, ERROR_CODE_NETWORK_ERROR); } return result; } boolean isResponseSuccess(Response response){ return response.getStatus() >= 200 && response.getStatus() < 300; } private String findUserImage(Response response){ try { if (isResponseSuccess(response)) { return Jsoup.parse(asString(response)) .select("#channel-box .userpic img").attr("src"); } }catch (RetrofitError er){ return null; } return null; } private JSONObject asJson(String input){ try { return new JSONObject(input); } catch (JSONException e) { e.printStackTrace(); } return null; } private String asString(Response body){ return new String(((TypedByteArray) body.getBody()).getBytes()); } private String findToken(List<HttpCookie> cookies){ for(HttpCookie cookie : cookies){ if(cookie.getName().equalsIgnoreCase("auth_sess")){ return cookie.getValue(); } } return null; } private boolean isCookiesHeader(Header header){ return header.getName() != null && header.getName().equalsIgnoreCase("set-cookie"); } public static class AuthorizeJob extends BaseNetworkJob<Bundle>{ MoverAuthenticator mAuth; public AuthorizeJob(MoverAuthenticator auth) { super(new Params(PRIORITY_HIGH) .requireNetwork() .groupBy("auth")); mAuth = auth; } @Override public void onPreRunning() { } @Override public Bundle doBackgroundJob() throws IOException { AccountManager manager = AccountManager.get(WatchMeApplication.getApplication()); return mAuth.getAuthToken(manager, mAuth.mAccount); } @Override public void onJobPostResult(Bundle result) { getEventBus().post(new AuthenticationEvent(result.getInt(KEY_ERROR_CODE) == 0, result)); } @Override public void onAdded() { } @Override protected boolean shouldReRunOnThrowable(Throwable throwable) { throw new RuntimeException(throwable); } } }