Browse Source

First fix login/logout

pull/24/head
Ezerous 8 years ago
parent
commit
8b841ebe67
  1. 8
      app/build.gradle
  2. 261
      app/src/main/java/gr/thmmy/mthmmy/activities/BaseActivity.java
  3. 46
      app/src/main/java/gr/thmmy/mthmmy/activities/LoginActivity.java
  4. 31
      app/src/main/java/gr/thmmy/mthmmy/activities/MainActivity.java
  5. 4
      app/src/main/java/gr/thmmy/mthmmy/sections/recent/RecentFragment.java
  6. 291
      app/src/main/java/gr/thmmy/mthmmy/session/SessionManager.java

8
app/build.gradle

@ -2,15 +2,15 @@ apply plugin: 'com.android.application'
android { android {
compileSdkVersion 25 compileSdkVersion 25
buildToolsVersion "25.0.0" buildToolsVersion "25.0.1"
defaultConfig { defaultConfig {
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
applicationId "gr.thmmy.mthmmy" applicationId "gr.thmmy.mthmmy"
minSdkVersion 19 minSdkVersion 19
targetSdkVersion 25 targetSdkVersion 25
versionCode 2 versionCode 3
versionName "0.16" versionName "0.17"
} }
buildTypes { buildTypes {
release { release {
@ -23,7 +23,7 @@ android {
dependencies { dependencies {
compile fileTree(dir: 'libs', include: ['*.jar']) compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:25.0.1' compile 'com.android.support:appcompat-v7:25.0.1'
compile 'com.android.support:design:25.0.0' compile 'com.android.support:design:25.0.1'
compile 'com.squareup.okhttp3:okhttp:3.4.0' compile 'com.squareup.okhttp3:okhttp:3.4.0'
compile 'com.jakewharton:butterknife:7.0.1' compile 'com.jakewharton:butterknife:7.0.1'
compile 'org.jsoup:jsoup:1.10.1' compile 'org.jsoup:jsoup:1.10.1'

261
app/src/main/java/gr/thmmy/mthmmy/activities/BaseActivity.java

@ -3,279 +3,52 @@ package gr.thmmy.mthmmy.activities;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import com.franmontiel.persistentcookiejar.PersistentCookieJar; import com.franmontiel.persistentcookiejar.PersistentCookieJar;
import com.franmontiel.persistentcookiejar.cache.SetCookieCache; import com.franmontiel.persistentcookiejar.cache.SetCookieCache;
import com.franmontiel.persistentcookiejar.persistence.SharedPrefsCookiePersistor; import com.franmontiel.persistentcookiejar.persistence.SharedPrefsCookiePersistor;
import org.jsoup.Jsoup; import gr.thmmy.mthmmy.session.SessionManager;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.IOException;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.net.ssl.SSLHandshakeException;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.FormBody;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient; import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class BaseActivity extends AppCompatActivity { public class BaseActivity extends AppCompatActivity
{
// Client & Cookies
protected static OkHttpClient client;
private static PersistentCookieJar cookieJar;
private static SharedPrefsCookiePersistor sharedPrefsCookiePersistor;
//----------------------------------------CLASS VARIABLES----------------------------------------- //Shared Preferences
/* --Response Codes-- */ private static final String SHARED_PREFS_NAME = "ThmmySharedPrefs";
static final int LOGGED_OUT = 0; protected static SharedPreferences sharedPrefs;
static final int LOGGED_IN = 1;
static final int WRONG_USER = 2;
static final int WRONG_PASSWORD = 3;
static final int FAILED = 4;
static final int CERTIFICATE_ERROR = 5;
static final int OTHER_ERROR = 6;
/* --Response Codes End-- */
/* --Shared Preferences-- */
static final String USER_NAME = "userNameKey";
static final String GUEST_PREF_USERNAME = "GUEST";
static final String LOG_STATUS = "isLoggedIn";
private static final String SHARED_PREFS_NAME = "thmmySharedPrefs";
static SharedPreferences _prefs;
/* --Shared Preferences End-- */
/* --Client Stuff-- */ //SessionManager
static OkHttpClient client; protected static SessionManager sessionManager;
private static CookieJar cookieJar;
private static SharedPrefsCookiePersistor sharedPrefsCookiePersistor;
/* --Client Stuff End-- */
//Other variables //Other variables
private static boolean init = false; //To initialize stuff only once per app start private static boolean init = false; //To initialize stuff only once per app start
private static final String TAG = "BaseActivity";
//--------------------------------------CLASS VARIABLES END---------------------------------------
//-------------------------------------CLIENT AND COOKIES-----------------------------------------
private static CookieJar getCookieJar() {
return cookieJar;
}
private static SharedPrefsCookiePersistor getSharedPrefsCookiePersistor() {
return sharedPrefsCookiePersistor;
}
public static OkHttpClient getClient() {
return client;
}
//-----------------------------------CLIENT AND COOKIES END---------------------------------------
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
if (!init) { if (!init) {
_prefs = getSharedPreferences(SHARED_PREFS_NAME, MODE_PRIVATE); sharedPrefs = getSharedPreferences(SHARED_PREFS_NAME, MODE_PRIVATE);
sharedPrefsCookiePersistor = new SharedPrefsCookiePersistor(BaseActivity.this); sharedPrefsCookiePersistor = new SharedPrefsCookiePersistor(BaseActivity.this);
cookieJar = new PersistentCookieJar(new SetCookieCache(), sharedPrefsCookiePersistor); cookieJar = new PersistentCookieJar(new SetCookieCache(), sharedPrefsCookiePersistor);
client = new OkHttpClient.Builder() client = new OkHttpClient.Builder()
.cookieJar(cookieJar) .cookieJar(cookieJar)
.build(); .build();
sessionManager = new SessionManager(client, cookieJar, sharedPrefsCookiePersistor, sharedPrefs);
init = true; init = true;
} }
} }
/* public static OkHttpClient getClient()
THMMY CLASS {
-- inner class of BaseActivity return client;
This class handles all session related operations (e.g. login, logout)
Also stores data to SharedPreferences file.
*/
//---------------------------------------INNER CLASS BEGINS---------------------------------------
public static class Thmmy {
//Class variables
private static final HttpUrl loginUrl = HttpUrl
.parse("https://www.thmmy.gr/smf/index.php?action=login2");
private static final HttpUrl indexUrl = HttpUrl
.parse("https://www.thmmy.gr/smf/index.php");
//-------------------------------------------LOGIN------------------------------------------------
//Two options: (username, password, duration) or nothing - cookies
static void login(String... strings) {
Log.d("Login", "Logging in...");
Request request;
if (strings.length == 3) { //Actual login
String loginName = strings[0];
String password = strings[1];
String duration = strings[2];
((PersistentCookieJar) getCookieJar()).clear();
RequestBody formBody = new FormBody.Builder() //Build login form
.add("user", loginName)
.add("passwrd", password)
.add("cookielength", duration) //Forever is -1
.build();
request = new Request.Builder() //Build the request
.url(loginUrl)
.post(formBody)
.build();
} else { //Already logged in, just get cookies
request = new Request.Builder() //Build the request
.url(loginUrl)
.build();
}
try {
Response response = client.newCall(request).execute(); //Make the request
/* --Handle response-- */
Document document = Jsoup.parse(response.body().string());
Element logout = document.getElementById("logoutbtn"); //Get logout button
if (logout != null) { //If there is a logout button, then I successfully logged in
Log.i("Login", "Login successful");
setPersistentCookieSession();
//Edit SharedPreferences, save session's data
_prefs.edit().putString(USER_NAME, extractUserName(document)).apply();
_prefs.edit().putInt(LOG_STATUS, LOGGED_IN).apply();
} else { //I am not logged in, what went wrong?
Log.w("Login", "Login failed");
_prefs.edit().putInt(LOG_STATUS, FAILED).apply(); //Request failed
//Making error more specific
Elements error = document.select("b:contains(That username does not exist.)");
if (error.size() == 1) { //Wrong username
_prefs.edit().putInt(LOG_STATUS, WRONG_USER).apply();
Log.d("Login", "Wrong Username");
}
error = document.select("body:contains(Password incorrect)");
if (error.size() == 1) { //Wrong password
_prefs.edit().putInt(LOG_STATUS, WRONG_PASSWORD).apply();
Log.d("Login", "Wrong Password");
}
((PersistentCookieJar) getCookieJar()).clear();
}
//Request exception handling
} catch (SSLHandshakeException e) {
_prefs.edit().putInt(LOG_STATUS, CERTIFICATE_ERROR).apply();
Log.w("Login", "Certificate problem");
} catch (Exception e) {
_prefs.edit().putInt(LOG_STATUS, OTHER_ERROR).apply();
Log.e("Login", "Error", e);
}
}
//--------------------------------------LOGIN ENDS------------------------------------------------
//---------------------------------------LOGOUT---------------------------------------------------
static int logout() {
String _logout_link = "";
{ //Find current logout link
try {
//Build and make a request for the index (home) page
Request request = new Request.Builder()
.url(indexUrl)
.build();
Response response = client.newCall(request).execute();
Document document = Jsoup.parse(response.body().string());
Element logout = document.getElementById("logoutbtn"); //Find the logout button
_logout_link = HttpUrl.parse(logout.attr("href")).toString(); //Get the url
} catch (IOException e) {
e.printStackTrace();
}
}
if (Objects.equals(_logout_link, "")) { //If logout button wasn't found
return OTHER_ERROR; //Something went wrong
}
//Attempt logout
OkHttpClient client = getClient();
Request request = new Request.Builder()
.url(_logout_link)
.build();
try {
Response response = client.newCall(request).execute();
Document document = Jsoup.parse(response.body().string());
Elements login = document.select("[pageValue=Login]"); //Find login button
((PersistentCookieJar) getCookieJar()).clear();
if (!login.isEmpty()) { //If found, logout was successful
Log.i("Logout", "Logout successful");
_prefs.edit().clear().apply(); //Clear session data
//User is now guest
_prefs.edit().putString(USER_NAME, GUEST_PREF_USERNAME).apply();
_prefs.edit().putInt(LOG_STATUS, LOGGED_IN).apply();
return LOGGED_OUT;
} else {
Log.w("Logout", "Logout failed");
return FAILED;
}
} catch (SSLHandshakeException e) {
Log.w("Logout", "Certificate problem (please switch to unsafe connection).");
return CERTIFICATE_ERROR;
} catch (Exception e) {
Log.d("Logout", "ERROR", e);
return OTHER_ERROR;
}
}
//----------------------------------------LOGOUT ENDS---------------------------------------------
//-------------------------------------------MISC-------------------------------------------------
private static String extractUserName(Document doc) {
if (doc != null) {
Elements user = doc.select("div[id=myuser] > h3");
if (user.size() == 1) {
String txt = user.first().ownText();
Pattern pattern = Pattern.compile(", (.*?),");
Matcher matcher = pattern.matcher(txt);
if (matcher.find())
return matcher.group(1);
}
}
return null;
} }
private static void setPersistentCookieSession() {
List<Cookie> cookieList = getCookieJar().loadForRequest(HttpUrl
.parse("https://www.thmmy.gr"));
if (cookieList.size() == 2) {
if ((cookieList.get(0).name().equals("THMMYgrC00ki3"))
&& (cookieList.get(1).name().equals("PHPSESSID"))) {
Cookie.Builder builder = new Cookie.Builder();
builder.name(cookieList.get(1).name())
.value(cookieList.get(1).value())
.domain(cookieList.get(1).domain())
.expiresAt(cookieList.get(0).expiresAt());
cookieList.remove(1);
cookieList.add(builder.build());
getSharedPrefsCookiePersistor().clear();
getSharedPrefsCookiePersistor().saveAll(cookieList);
}
}
}
}
//----------------------------------------INNER CLASS ENDS----------------------------------------
} }

46
app/src/main/java/gr/thmmy/mthmmy/activities/LoginActivity.java

@ -12,6 +12,12 @@ import android.widget.Toast;
import gr.thmmy.mthmmy.R; import gr.thmmy.mthmmy.R;
import static gr.thmmy.mthmmy.session.SessionManager.EXCEPTION;
import static gr.thmmy.mthmmy.session.SessionManager.FAILURE;
import static gr.thmmy.mthmmy.session.SessionManager.SUCCESS;
import static gr.thmmy.mthmmy.session.SessionManager.WRONG_PASSWORD;
import static gr.thmmy.mthmmy.session.SessionManager.WRONG_USER;
public class LoginActivity extends BaseActivity { public class LoginActivity extends BaseActivity {
//-----------------------------------------CLASS VARIABLES------------------------------------------ //-----------------------------------------CLASS VARIABLES------------------------------------------
@ -64,8 +70,7 @@ public class LoginActivity extends BaseActivity {
public void onClick(View view) { public void onClick(View view) {
//Session data update //Session data update
_prefs.edit().putString(USER_NAME, GUEST_PREF_USERNAME).apply(); sessionManager.guestLogin();
_prefs.edit().putInt(LOG_STATUS, LOGGED_IN).apply();
//Go to main //Go to main
Intent intent = new Intent(LoginActivity.this, MainActivity.class); Intent intent = new Intent(LoginActivity.this, MainActivity.class);
@ -115,8 +120,7 @@ public class LoginActivity extends BaseActivity {
@Override @Override
protected Integer doInBackground(String... params) { protected Integer doInBackground(String... params) {
Thmmy.login(params[0], params[1], "-1"); //Attempt login return sessionManager.login(params[0], params[1]);
return _prefs.getInt(LOG_STATUS, OTHER_ERROR);
} }
@Override @Override
@ -134,6 +138,16 @@ public class LoginActivity extends BaseActivity {
@Override @Override
protected void onPostExecute(Integer result) { //Handle attempt result protected void onPostExecute(Integer result) { //Handle attempt result
switch (result) { switch (result) {
case SUCCESS: //Successful login
Toast.makeText(getApplicationContext(),
"Login successful!", Toast.LENGTH_LONG)
.show();
//Go to main
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
startActivity(intent);
finish();
overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out);
break;
case WRONG_USER: case WRONG_USER:
Toast.makeText(getApplicationContext(), Toast.makeText(getApplicationContext(),
"Wrong username!", Toast.LENGTH_LONG).show(); "Wrong username!", Toast.LENGTH_LONG).show();
@ -143,31 +157,17 @@ public class LoginActivity extends BaseActivity {
"Wrong password!", Toast.LENGTH_LONG) "Wrong password!", Toast.LENGTH_LONG)
.show(); .show();
break; break;
case FAILED: case FAILURE:
Toast.makeText(getApplicationContext(), Toast.makeText(getApplicationContext(),
"Check your connection!", Toast.LENGTH_LONG) "Login failed...", Toast.LENGTH_LONG)
.show(); .show();
break; break;
case CERTIFICATE_ERROR: case EXCEPTION:
Toast.makeText(getApplicationContext(), Toast.makeText(getApplicationContext(),
"Certificate error!", Toast.LENGTH_LONG) "Login failed...", Toast.LENGTH_LONG)
.show(); .show();
break; break;
case OTHER_ERROR:
Toast.makeText(getApplicationContext(),
"Check your connection!", Toast.LENGTH_LONG)
.show();
break;
case LOGGED_IN: //Successful login
Toast.makeText(getApplicationContext(),
"Login successful!", Toast.LENGTH_LONG)
.show();
//Go to main
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
startActivity(intent);
finish();
overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out);
break;
} }
//Login failed //Login failed
btnLogin.setEnabled(true); //Re-enable login button btnLogin.setEnabled(true); //Re-enable login button

31
app/src/main/java/gr/thmmy/mthmmy/activities/MainActivity.java

@ -14,13 +14,12 @@ import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.widget.Toast; import android.widget.Toast;
import java.util.Objects;
import gr.thmmy.mthmmy.R; import gr.thmmy.mthmmy.R;
import gr.thmmy.mthmmy.data.TopicSummary; import gr.thmmy.mthmmy.data.TopicSummary;
import gr.thmmy.mthmmy.sections.recent.RecentFragment; import gr.thmmy.mthmmy.sections.recent.RecentFragment;
import static gr.thmmy.mthmmy.activities.BaseActivity.Thmmy.logout; import static gr.thmmy.mthmmy.session.SessionManager.LOGGED_IN;
import static gr.thmmy.mthmmy.session.SessionManager.LOGGED_OUT;
public class MainActivity extends BaseActivity implements RecentFragment.OnListFragmentInteractionListener { public class MainActivity extends BaseActivity implements RecentFragment.OnListFragmentInteractionListener {
@ -33,7 +32,7 @@ public class MainActivity extends BaseActivity implements RecentFragment.OnListF
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); setContentView(R.layout.activity_main);
if (_prefs.getInt(LOG_STATUS, OTHER_ERROR) != LOGGED_IN) { //If not logged in if (sessionManager.getLogStatus()== LOGGED_OUT) { //If not logged in
//Go to login //Go to login
Intent intent = new Intent(MainActivity.this, LoginActivity.class); Intent intent = new Intent(MainActivity.this, LoginActivity.class);
startActivity(intent); startActivity(intent);
@ -69,13 +68,11 @@ public class MainActivity extends BaseActivity implements RecentFragment.OnListF
this.menu = menu; this.menu = menu;
getMenuInflater().inflate(R.menu.menu_main, menu); getMenuInflater().inflate(R.menu.menu_main, menu);
if (_prefs.getInt(LOG_STATUS, OTHER_ERROR) == LOGGED_IN if (sessionManager.getLogStatus()!= LOGGED_IN) //When logged out or if user is guest
&& !Objects.equals(_prefs.getString(USER_NAME, null), GUEST_PREF_USERNAME)) {
//Will enter when logged out or if user is guest
hideLogin();
} else
//Will enter when logged in
hideLogout(); hideLogout();
else
hideLogin();
return true; return true;
} }
@ -171,7 +168,7 @@ public class MainActivity extends BaseActivity implements RecentFragment.OnListF
ProgressDialog progressDialog; ProgressDialog progressDialog;
protected Integer doInBackground(Void... voids) { protected Integer doInBackground(Void... voids) {
return logout(); return sessionManager.logout();
} }
protected void onPreExecute() { //Show a progress dialog until done protected void onPreExecute() { //Show a progress dialog until done
@ -184,15 +181,13 @@ public class MainActivity extends BaseActivity implements RecentFragment.OnListF
protected void onPostExecute(Integer result) { //Handle attempt result protected void onPostExecute(Integer result) { //Handle attempt result
progressDialog.dismiss(); //Hide progress dialog progressDialog.dismiss(); //Hide progress dialog
if (result == LOGGED_OUT) { //Successful logout if (result == LOGGED_OUT) //Successful logout
/* {
At this point result is LOGGED_OUT
BUT pref's LOGIN_STATUS variable is LOGGED_IN!!
and USER_NAME is GUEST
*/
Toast.makeText(getBaseContext(), "Logged out successfully!", Toast.LENGTH_LONG).show(); Toast.makeText(getBaseContext(), "Logged out successfully!", Toast.LENGTH_LONG).show();
sessionManager.guestLogin(); //Fall to guest login
hideLogout(); hideLogout();
} else //Logout failed }
else //Logout failed
hideLogin(); hideLogin();
} }
} }

4
app/src/main/java/gr/thmmy/mthmmy/sections/recent/RecentFragment.java

@ -27,7 +27,9 @@ import java.util.regex.Pattern;
import gr.thmmy.mthmmy.R; import gr.thmmy.mthmmy.R;
import gr.thmmy.mthmmy.activities.BaseActivity; import gr.thmmy.mthmmy.activities.BaseActivity;
import gr.thmmy.mthmmy.data.TopicSummary; import gr.thmmy.mthmmy.data.TopicSummary;
import gr.thmmy.mthmmy.session.SessionManager;
import gr.thmmy.mthmmy.utils.CustomRecyclerView; import gr.thmmy.mthmmy.utils.CustomRecyclerView;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient; import okhttp3.OkHttpClient;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.Response; import okhttp3.Response;
@ -202,7 +204,7 @@ public class RecentFragment extends Fragment {
public class RecentTask extends AsyncTask<Void, Void, Integer> { public class RecentTask extends AsyncTask<Void, Void, Integer> {
private static final String TAG = "RecentTask"; private static final String TAG = "RecentTask";
private final String thmmyUrl = "https://www.thmmy.gr/smf/index.php"; private final HttpUrl thmmyUrl = SessionManager.indexUrl;
private Document document; private Document document;

291
app/src/main/java/gr/thmmy/mthmmy/session/SessionManager.java

@ -0,0 +1,291 @@
package gr.thmmy.mthmmy.session;
import android.content.SharedPreferences;
import android.util.Log;
import com.franmontiel.persistentcookiejar.PersistentCookieJar;
import com.franmontiel.persistentcookiejar.persistence.SharedPrefsCookiePersistor;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import okhttp3.Cookie;
import okhttp3.FormBody;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
/**
This class handles all session related operations (e.g. login, logout)
and stores data to SharedPreferences (session informarion and cookies).
*/
public class SessionManager
{
//Class TAG
private static final String TAG = "SessionManager";
//Generic constants
public static final HttpUrl indexUrl = HttpUrl.parse("https://www.thmmy.gr/smf/index.php");
private static final HttpUrl loginUrl = HttpUrl.parse("https://www.thmmy.gr/smf/index.php?action=login2");
private static final String guestName = "Guest";
//Response Codes
public static final int SUCCESS = 0;
public static final int FAILURE = 1; //Generic Error
public static final int WRONG_USER = 2;
public static final int WRONG_PASSWORD = 3;
public static final int EXCEPTION = 4;
//Login status codes
public static final int LOGGED_OUT = 0;
public static final int LOGGED_IN = 1; //Logged in (as a normal user)
public static final int AS_GUEST = 2; //User chose to continue as guest
// Client & Cookies
private OkHttpClient client;
private PersistentCookieJar cookieJar;
private SharedPrefsCookiePersistor cookiePersistor; //Used to explicitly edit cookies in cookieJar
//Shared Preferences & its keys
private SharedPreferences sharedPrefs;
private static final String USERNAME = "Username";
private static final String LOGOUT_LINK = "LogoutLink";
private static final String LOGIN_STATUS = "IsLoggedIn";
//Constructor
public SessionManager(OkHttpClient client, PersistentCookieJar cookieJar,
SharedPrefsCookiePersistor cookiePersistor, SharedPreferences sharedPrefs)
{
this.client = client;
this.cookiePersistor=cookiePersistor;
this.cookieJar = cookieJar;
this.sharedPrefs = sharedPrefs;
}
//------------------------------------AUTH BEGINS----------------------------------------------
/**
* Login function with two options: (username, password) or nothing (using saved cookies).
* Always call it in a separate thread.
*/
public int login(String... strings)
{
Log.i(TAG, "Logging in...");
//Build the login request for each case
Request request;
if (strings.length == 2)
{
clearSessionData();
String loginName = strings[0];
String password = strings[1];
RequestBody formBody = new FormBody.Builder()
.add("user", loginName)
.add("passwrd", password)
.add("cookielength", "-1") //-1 is forever
.build();
request = new Request.Builder()
.url(loginUrl)
.post(formBody)
.build();
}
else
{
request = new Request.Builder()
.url(loginUrl)
.build();
}
try {
//Make request & handle response
Response response = client.newCall(request).execute();
Document document = Jsoup.parse(response.body().string());
Element logoutButton = document.getElementById("logoutbtn"); //Attempt to find logout button
if (logoutButton != null) //If logout button exists, login was successful
{
Log.i(TAG, "Login successful!");
setPersistentCookieSession(); //Store cookies
//Edit SharedPreferences, save session's data
sharedPrefs.edit().putInt(LOGIN_STATUS, LOGGED_IN).apply();
sharedPrefs.edit().putString(USERNAME, extractUserName(document)).apply();
sharedPrefs.edit().putString(LOGOUT_LINK, HttpUrl.parse(logoutButton.attr("href")).toString()).apply();
return SUCCESS;
}
else
{
Log.i(TAG, "Login failed.");
//Investigate login failure
Elements error = document.select("b:contains(That username does not exist.)");
if (error.size() == 1) { //Wrong username
Log.i(TAG, "Wrong Username");
return WRONG_USER;
}
error = document.select("body:contains(Password incorrect)");
if (error.size() == 1) { //Wrong password
Log.i(TAG, "Wrong Password");
return WRONG_PASSWORD;
}
//Other error e.g. session was reset server-side
clearSessionData(); //Clear invalid saved data
return FAILURE;
}
//Handle exception
} catch (Exception e) {
Log.w(TAG, "Login Exception: "+ e.getMessage(), e);
return EXCEPTION;
}
}
/**
* A function that checks the validity of the current saved session (if it exists).
* If LOGIN_STATUS is true, it will call login() with cookies. This can only return
* the codes {SUCCESS, FAILURE, EXCEPTION}. EXCEPTION is considered a SUCCESS (e.g. no internet
* connection), at least until a more thorough handling of different exceptions is implemented.
* Always call it in a separate thread.
*/
public void validateSession()
{
Log.i(TAG, "Validating session...");
//Check if user is currently logged in
int status = sharedPrefs.getInt(LOGIN_STATUS,LOGGED_OUT);
if(status==LOGGED_IN)
{
int loginResult = login();
if(loginResult == SUCCESS || loginResult == EXCEPTION)
return;
}
else if(status==AS_GUEST)
return;
clearSessionData();
}
/**
* Call this function when user explicitly chooses to continue as a guest (UI thread).
*/
public void guestLogin()
{
Log.i("TAG", "Continuing as a guest, as chosen by the user.");
clearSessionData();
sharedPrefs.edit().putInt(LOGIN_STATUS, AS_GUEST).apply();
}
/**
* Logout function. Always call it in a separate thread.
*/
public int logout()
{
Log.i(TAG, "Logging out...");
Request request = new Request.Builder()
.url(sharedPrefs.getString(LOGOUT_LINK,"LogoutLink"))
.build();
try {
//Make request & handle response
Response response = client.newCall(request).execute();
Document document = Jsoup.parse(response.body().string());
Elements loginButton = document.select("[value=Login]"); //Attempt to find login button
if (!loginButton.isEmpty()) //If login button exists, logout was successful
{
Log.i("Logout", "Logout successful!");
return SUCCESS;
}
else
{
Log.i(TAG, "Logout failed.");
return FAILURE;
}
} catch (Exception e) {
Log.w(TAG, "Logout Exception: "+ e.getMessage(), e);
return EXCEPTION;
} finally {
//All data should always be cleared from device regardless the result of logout
clearSessionData();
Log.i(TAG,"Session data cleared.");
}
}
//--------------------------------------AUTH ENDS-----------------------------------------------
//---------------------------------------GETTERS------------------------------------------------
public String getUsername() {
return sharedPrefs.getString(USERNAME, "Username");
}
public String getLogoutLink() {
return sharedPrefs.getString(LOGOUT_LINK, "LogoutLink");
}
public int getLogStatus() {
return sharedPrefs.getInt(LOGIN_STATUS, LOGGED_OUT);
}
//--------------------------------------GETTERS END---------------------------------------------
//------------------------------------OTHER FUNCTIONS-------------------------------------------
private void setPersistentCookieSession()
{
List<Cookie> cookieList = cookieJar.loadForRequest(indexUrl);
if (cookieList.size() == 2)
{
if ((cookieList.get(0).name().equals("THMMYgrC00ki3"))
&& (cookieList.get(1).name().equals("PHPSESSID"))) {
Cookie.Builder builder = new Cookie.Builder();
builder.name(cookieList.get(1).name())
.value(cookieList.get(1).value())
.domain(cookieList.get(1).domain())
.expiresAt(cookieList.get(0).expiresAt());
cookieList.remove(1);
cookieList.add(builder.build());
cookiePersistor.clear();
cookiePersistor.saveAll(cookieList);
}
}
}
private void clearSessionData()
{
cookieJar.clear();
sharedPrefs.edit().clear().apply(); //Clear session data
sharedPrefs.edit().putString(USERNAME, guestName).apply(); //User becomes guest
sharedPrefs.edit().putInt(LOGIN_STATUS, LOGGED_OUT).apply();
}
private String extractUserName(Document doc)
{
if (doc != null) {
Elements user = doc.select("div[id=myuser] > h3");
if (user.size() == 1) {
String txt = user.first().ownText();
Pattern pattern = Pattern.compile(", (.*?),");
Matcher matcher = pattern.matcher(txt);
if (matcher.find())
return matcher.group(1);
}
}
return null;
}
//----------------------------------OTHER FUNCTIONS END-----------------------------------------
}
Loading…
Cancel
Save