@ -0,0 +1,265 @@ |
|||
package gr.auth.databases.flavours.base; |
|||
|
|||
import android.Manifest; |
|||
import android.content.Intent; |
|||
import android.content.SharedPreferences; |
|||
import android.content.pm.PackageManager; |
|||
import android.os.Build; |
|||
import android.os.Bundle; |
|||
import android.view.View; |
|||
|
|||
import com.mikepenz.fontawesome_typeface_library.FontAwesome; |
|||
import com.mikepenz.google_material_typeface_library.GoogleMaterial; |
|||
import com.mikepenz.iconics.IconicsDrawable; |
|||
import com.mikepenz.materialdrawer.AccountHeader; |
|||
import com.mikepenz.materialdrawer.AccountHeaderBuilder; |
|||
import com.mikepenz.materialdrawer.Drawer; |
|||
import com.mikepenz.materialdrawer.DrawerBuilder; |
|||
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem; |
|||
import com.mikepenz.materialdrawer.model.ProfileDrawerItem; |
|||
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem; |
|||
|
|||
import androidx.annotation.NonNull; |
|||
import androidx.appcompat.app.AppCompatActivity; |
|||
import androidx.appcompat.widget.Toolbar; |
|||
import androidx.core.content.ContextCompat; |
|||
import androidx.preference.PreferenceManager; |
|||
import gr.auth.databases.flavours.R; |
|||
import gr.auth.databases.flavours.activities.LoginActivity; |
|||
import gr.auth.databases.flavours.activities.main.MainActivity; |
|||
import gr.auth.databases.flavours.session.SessionManager; |
|||
import okhttp3.OkHttpClient; |
|||
|
|||
public abstract class BaseActivity extends AppCompatActivity { |
|||
// Client & Cookies
|
|||
protected static OkHttpClient client; |
|||
|
|||
//SessionManager
|
|||
protected static SessionManager sessionManager; |
|||
|
|||
private SharedPreferences sharedPreferences; |
|||
|
|||
//Common UI elements
|
|||
protected Toolbar toolbar; |
|||
protected Drawer drawer; |
|||
|
|||
private boolean isMainActivity; |
|||
|
|||
@Override |
|||
protected void onCreate(Bundle savedInstanceState) { |
|||
super.onCreate(savedInstanceState); |
|||
|
|||
isMainActivity = this instanceof MainActivity; |
|||
|
|||
if (client == null) |
|||
client = BaseApplication.getInstance().getClient(); //must check every time - e.g.
|
|||
|
|||
// they become null when app restarts after crash
|
|||
if (sessionManager == null) |
|||
sessionManager = BaseApplication.getInstance().getSessionManager(); |
|||
|
|||
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); |
|||
} |
|||
|
|||
@Override |
|||
protected void onResume() { |
|||
super.onResume(); |
|||
updateDrawer(); |
|||
} |
|||
|
|||
@Override |
|||
protected void onPause() { |
|||
super.onPause(); |
|||
if (drawer != null) //close drawer animation after returning to activity
|
|||
drawer.closeDrawer(); |
|||
} |
|||
|
|||
|
|||
public static OkHttpClient getClient() { |
|||
return client; |
|||
} |
|||
|
|||
public static SessionManager getSessionManager() { |
|||
return sessionManager; |
|||
} |
|||
|
|||
//------------------------------------------DRAWER STUFF----------------------------------------
|
|||
protected static final int HOME_ID = 0; |
|||
protected static final int LOG_ID = 4; |
|||
|
|||
private AccountHeader accountHeader; |
|||
private ProfileDrawerItem profileDrawerItem; |
|||
private PrimaryDrawerItem loginLogoutItem; |
|||
|
|||
protected void createDrawer() { |
|||
final int primaryColor = ContextCompat.getColor(this, R.color.textPrimary); |
|||
final int selectedPrimaryColor = ContextCompat.getColor(this, R.color.primary_dark); |
|||
final int selectedSecondaryColor = ContextCompat.getColor(this, R.color.iron); |
|||
|
|||
PrimaryDrawerItem homeItem; |
|||
IconicsDrawable homeIcon, homeIconSelected; |
|||
|
|||
//Drawer Icons
|
|||
homeIcon = new IconicsDrawable(this) |
|||
.icon(GoogleMaterial.Icon.gmd_home) |
|||
.color(primaryColor); |
|||
|
|||
homeIconSelected = new IconicsDrawable(this) |
|||
.icon(GoogleMaterial.Icon.gmd_home) |
|||
.color(selectedSecondaryColor); |
|||
|
|||
IconicsDrawable loginIcon = new IconicsDrawable(this) |
|||
.icon(FontAwesome.Icon.faw_sign_in) |
|||
.color(primaryColor); |
|||
|
|||
IconicsDrawable logoutIcon = new IconicsDrawable(this) |
|||
.icon(FontAwesome.Icon.faw_sign_out) |
|||
.color(primaryColor); |
|||
|
|||
//Drawer Items
|
|||
homeItem = new PrimaryDrawerItem() |
|||
.withTextColor(primaryColor) |
|||
.withSelectedColor(selectedPrimaryColor) |
|||
.withSelectedTextColor(selectedSecondaryColor) |
|||
.withIdentifier(HOME_ID) |
|||
.withName(R.string.drawer_home) |
|||
.withIcon(homeIcon) |
|||
.withSelectedIcon(homeIconSelected); |
|||
|
|||
if (sessionManager.isLoggedIn()) { |
|||
loginLogoutItem = new PrimaryDrawerItem() |
|||
.withTextColor(primaryColor) |
|||
.withSelectedColor(selectedSecondaryColor) |
|||
.withIdentifier(LOG_ID) |
|||
.withName(R.string.drawer_logout) |
|||
.withIcon(logoutIcon) |
|||
.withSelectable(false); |
|||
} else { |
|||
loginLogoutItem = new PrimaryDrawerItem() |
|||
.withTextColor(primaryColor) |
|||
.withSelectedColor(selectedSecondaryColor) |
|||
.withIdentifier(LOG_ID).withName(R.string.drawer_login) |
|||
.withIcon(loginIcon) |
|||
.withSelectable(false); |
|||
} |
|||
|
|||
//Profile
|
|||
profileDrawerItem = new ProfileDrawerItem().withName(sessionManager.getUsername()).withIdentifier(0); |
|||
|
|||
//AccountHeader
|
|||
accountHeader = new AccountHeaderBuilder() |
|||
.withActivity(this) |
|||
.withCompactStyle(true) |
|||
.withSelectionListEnabledForSingleProfile(false) |
|||
.withHeaderBackground(R.color.primary) |
|||
.withTextColor(getResources().getColor(R.color.iron)) |
|||
.addProfiles(profileDrawerItem) |
|||
/*.withOnAccountHeaderListener((view, profile, currentProfile) -> { |
|||
if (sessionManager.isLoggedIn()) { |
|||
Intent intent = new Intent(BaseActivity.this, ProfileActivity.class); |
|||
Bundle extras = new Bundle(); |
|||
extras.putString(BUNDLE_PROFILE_URL, "https://www.thmmy.gr/smf/index.php?action=profile"); |
|||
extras.putString(BUNDLE_PROFILE_USERNAME, sessionManager.getUsername()); |
|||
intent.putExtras(extras); |
|||
intent.setFlags(FLAG_ACTIVITY_NEW_TASK); |
|||
startActivity(intent); |
|||
return false; |
|||
} else |
|||
startLoginActivity(); |
|||
return true; |
|||
|
|||
})*/ |
|||
.build(); |
|||
|
|||
DrawerBuilder drawerBuilder = new DrawerBuilder() |
|||
.withActivity(this) |
|||
.withToolbar(toolbar) |
|||
.withDrawerWidthDp((int) BaseApplication.getInstance().getDpWidth() / 2) |
|||
.withSliderBackgroundColor(ContextCompat.getColor(this, R.color.colorBackground)) |
|||
.withAccountHeader(accountHeader) |
|||
.withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() { |
|||
@Override |
|||
public boolean onItemClick(View view, int position, IDrawerItem drawerItem) { |
|||
if (drawerItem.equals(HOME_ID)) { |
|||
if (!isMainActivity) { |
|||
Intent intent = new Intent(BaseActivity.this, MainActivity.class); |
|||
startActivity(intent); |
|||
} |
|||
} else if (drawerItem.equals(LOG_ID)) { |
|||
if (!sessionManager.isLoggedIn()) //When logged out or if user is guest
|
|||
startLoginActivity(); |
|||
/*else |
|||
new LogoutTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);*/ |
|||
} |
|||
|
|||
drawer.closeDrawer(); |
|||
return true; |
|||
} |
|||
}); |
|||
|
|||
|
|||
drawerBuilder.addDrawerItems(homeItem, loginLogoutItem); |
|||
drawer = drawerBuilder.build(); |
|||
|
|||
if (!isMainActivity) |
|||
drawer.getActionBarDrawerToggle().setDrawerIndicatorEnabled(false); |
|||
|
|||
drawer.setOnDrawerNavigationListener(new Drawer.OnDrawerNavigationListener() { |
|||
@Override |
|||
public boolean onNavigationClickListener(View clickedView) { |
|||
onBackPressed(); |
|||
return true; |
|||
} |
|||
}); |
|||
} |
|||
|
|||
private void updateDrawer() { |
|||
if (drawer != null) { |
|||
accountHeader.updateProfile(profileDrawerItem); |
|||
drawer.updateItem(loginLogoutItem); |
|||
} |
|||
} |
|||
|
|||
//-------PERMS---------
|
|||
private static final int PERMISSIONS_REQUEST_CODE = 69; |
|||
|
|||
//True if permissions are OK
|
|||
private boolean checkPerms() { |
|||
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) { |
|||
String[] PERMISSIONS_STORAGE = { |
|||
Manifest.permission.READ_EXTERNAL_STORAGE, |
|||
Manifest.permission.WRITE_EXTERNAL_STORAGE}; |
|||
|
|||
return !(checkSelfPermission(PERMISSIONS_STORAGE[0]) == PackageManager.PERMISSION_DENIED || |
|||
checkSelfPermission(PERMISSIONS_STORAGE[1]) == PackageManager.PERMISSION_DENIED); |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
//Display popup for user to grant permission
|
|||
private void requestPerms() { //Runtime permissions request for devices with API >= 23
|
|||
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) { |
|||
String[] PERMISSIONS_STORAGE = { |
|||
Manifest.permission.READ_EXTERNAL_STORAGE, |
|||
Manifest.permission.WRITE_EXTERNAL_STORAGE}; |
|||
|
|||
requestPermissions(PERMISSIONS_STORAGE, PERMISSIONS_REQUEST_CODE); |
|||
} |
|||
} |
|||
|
|||
|
|||
@Override |
|||
public void onRequestPermissionsResult(int permsRequestCode, @NonNull String[] permissions |
|||
, @NonNull int[] grantResults) { |
|||
switch (permsRequestCode) { |
|||
case PERMISSIONS_REQUEST_CODE: |
|||
//downloadFile();
|
|||
break; |
|||
} |
|||
} |
|||
|
|||
private void startLoginActivity() { |
|||
Intent intent = new Intent(BaseActivity.this, LoginActivity.class); |
|||
startActivity(intent); |
|||
} |
|||
} |
@ -0,0 +1,72 @@ |
|||
package gr.auth.databases.flavours.base; |
|||
|
|||
import android.app.Application; |
|||
import android.content.Context; |
|||
import android.content.SharedPreferences; |
|||
import android.util.DisplayMetrics; |
|||
|
|||
import com.franmontiel.persistentcookiejar.PersistentCookieJar; |
|||
import com.franmontiel.persistentcookiejar.cache.SetCookieCache; |
|||
import com.franmontiel.persistentcookiejar.persistence.SharedPrefsCookiePersistor; |
|||
|
|||
import java.util.concurrent.TimeUnit; |
|||
|
|||
import gr.auth.databases.flavours.session.SessionManager; |
|||
import okhttp3.OkHttpClient; |
|||
|
|||
public class BaseApplication extends Application { |
|||
private static BaseApplication baseApplication; //BaseApplication singleton
|
|||
|
|||
//Client & SessionManager
|
|||
private OkHttpClient client; |
|||
private SessionManager sessionManager; |
|||
|
|||
private static final String SHARED_PREFS = "ThmmySharedPrefs"; |
|||
|
|||
private static float dpWidth; |
|||
|
|||
public static BaseApplication getInstance() { |
|||
return baseApplication; |
|||
} |
|||
|
|||
@Override |
|||
public void onCreate() { |
|||
super.onCreate(); |
|||
baseApplication = this; //init singleton
|
|||
|
|||
//Shared Preferences
|
|||
SharedPreferences sharedPrefs = getSharedPreferences(SHARED_PREFS, MODE_PRIVATE); |
|||
|
|||
SharedPrefsCookiePersistor sharedPrefsCookiePersistor = new SharedPrefsCookiePersistor(getApplicationContext()); |
|||
PersistentCookieJar cookieJar = new PersistentCookieJar(new SetCookieCache(), sharedPrefsCookiePersistor); |
|||
OkHttpClient.Builder builder = new OkHttpClient.Builder() |
|||
.cookieJar(cookieJar) |
|||
.connectTimeout(40, TimeUnit.SECONDS) |
|||
.writeTimeout(40, TimeUnit.SECONDS) |
|||
.readTimeout(40, TimeUnit.SECONDS); |
|||
|
|||
client = builder.build(); |
|||
|
|||
sessionManager = new SessionManager(client, cookieJar, sharedPrefsCookiePersistor, sharedPrefs); |
|||
|
|||
DisplayMetrics displayMetrics = getApplicationContext().getResources().getDisplayMetrics(); |
|||
dpWidth = displayMetrics.widthPixels / displayMetrics.density; |
|||
} |
|||
|
|||
//Getters
|
|||
public Context getContext() { |
|||
return getApplicationContext(); |
|||
} |
|||
|
|||
public OkHttpClient getClient() { |
|||
return client; |
|||
} |
|||
|
|||
public SessionManager getSessionManager() { |
|||
return sessionManager; |
|||
} |
|||
|
|||
public float getDpWidth() { |
|||
return dpWidth; |
|||
} |
|||
} |
@ -0,0 +1,205 @@ |
|||
package gr.auth.databases.flavours.session; |
|||
|
|||
|
|||
import android.content.SharedPreferences; |
|||
|
|||
import com.franmontiel.persistentcookiejar.PersistentCookieJar; |
|||
import com.franmontiel.persistentcookiejar.persistence.SharedPrefsCookiePersistor; |
|||
|
|||
import java.util.List; |
|||
|
|||
import okhttp3.Cookie; |
|||
import okhttp3.FormBody; |
|||
import okhttp3.HttpUrl; |
|||
import okhttp3.OkHttpClient; |
|||
import okhttp3.Request; |
|||
import okhttp3.RequestBody; |
|||
import okhttp3.Response; |
|||
|
|||
public class SessionManager { |
|||
//Generic constants
|
|||
public static final HttpUrl indexUrl = HttpUrl.parse("https://www.thmmy.gr/smf/index.php?theme=4"); |
|||
private static final HttpUrl loginUrl = HttpUrl.parse("https://www.thmmy.gr/smf/index.php?action=login2"); |
|||
|
|||
// Client & Cookies
|
|||
private final OkHttpClient client; |
|||
private final PersistentCookieJar cookieJar; |
|||
private final SharedPrefsCookiePersistor cookiePersistor; //Used to explicitly edit cookies in cookieJar
|
|||
|
|||
//Shared Preferences & its keys
|
|||
private final SharedPreferences sharedPrefs; |
|||
private static final String USERNAME = "Username"; |
|||
private static final String USER_ID = "UserID"; |
|||
private static final String LOGOUT_LINK = "LogoutLink"; |
|||
private static final String LOGGED_IN = "LoggedIn"; |
|||
private static final String LOGIN_SCREEN_AS_DEFAULT = "LoginScreenAsDefault"; |
|||
|
|||
//Constructor
|
|||
public SessionManager(OkHttpClient client, PersistentCookieJar cookieJar, |
|||
SharedPrefsCookiePersistor cookiePersistor, SharedPreferences sharedPrefs) { |
|||
this.client = client; |
|||
this.cookiePersistor = cookiePersistor; |
|||
this.cookieJar = cookieJar; |
|||
this.sharedPrefs = sharedPrefs; |
|||
} |
|||
|
|||
public int login(String... strings) { |
|||
//Builds 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 { |
|||
//Makes request & handles response
|
|||
Response response = client.newCall(request).execute(); |
|||
|
|||
if (validateRetrievedCookies()) { |
|||
setPersistentCookieSession(); //Store cookies
|
|||
|
|||
//Edit SharedPreferences, save session's data
|
|||
SharedPreferences.Editor editor = sharedPrefs.edit(); |
|||
setLoginScreenAsDefault(false); |
|||
editor.putBoolean(LOGGED_IN, true); |
|||
/*editor.putString(USERNAME, extractUserName(document)); |
|||
editor.putInt(USER_ID, extractUserId(document)); |
|||
String avatar = extractAvatarLink(document);*/ |
|||
/*if (avatar != null) |
|||
editor.putString(AVATAR_LINK, avatar); |
|||
editor.putBoolean(HAS_AVATAR, avatar != null); |
|||
editor.putString(LOGOUT_LINK, extractLogoutLink(document));*/ |
|||
editor.apply(); |
|||
|
|||
return 0; |
|||
} else { |
|||
//Investigates login failure
|
|||
/*if (error.size() > 0) { //Wrong username
|
|||
return WRONG_USER; |
|||
} |
|||
|
|||
if (error.size() > 0) { //Wrong password
|
|||
return WRONG_PASSWORD; |
|||
} |
|||
|
|||
if (error.size() > 0) { //User is banned
|
|||
return BANNED_USER; |
|||
}*/ |
|||
|
|||
//Other error e.g. session was reset server-side
|
|||
clearSessionData(); //Clear invalid saved data
|
|||
return 1; |
|||
} |
|||
//Handles exceptions
|
|||
} catch (Exception e) { |
|||
return 2; |
|||
} |
|||
} |
|||
|
|||
public void validateSession() { |
|||
if (isLoggedIn()) { |
|||
int loginResult = login(); |
|||
if (loginResult != 1) |
|||
return; |
|||
} else if (isLoginScreenDefault()) |
|||
return; |
|||
|
|||
setLoginScreenAsDefault(true); |
|||
clearSessionData(); |
|||
} |
|||
|
|||
public int logout() { |
|||
Request request = new Request.Builder() |
|||
.url(sharedPrefs.getString(LOGOUT_LINK, "LogoutLink")) |
|||
.build(); |
|||
|
|||
try { |
|||
//Makes request & handles response
|
|||
Response response = client.newCall(request).execute(); |
|||
} catch (Exception e) { |
|||
return 2; |
|||
} finally { |
|||
//All data should always be cleared from device regardless the result of logout
|
|||
clearSessionData(); |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
public String getUsername() { |
|||
return sharedPrefs.getString(USERNAME, USERNAME); |
|||
} |
|||
|
|||
public int getUserId() { |
|||
return sharedPrefs.getInt(USER_ID, -1); |
|||
} |
|||
|
|||
public Cookie getThmmyCookie() { |
|||
List<Cookie> cookieList = cookieJar.loadForRequest(indexUrl); |
|||
for (Cookie cookie : cookieList) { |
|||
if (cookie.name().equals("THMMYgrC00ki3")) |
|||
return cookie; |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
public boolean isLoggedIn() { |
|||
return sharedPrefs.getBoolean(LOGGED_IN, false); |
|||
} |
|||
|
|||
public boolean isLoginScreenDefault() { |
|||
return sharedPrefs.getBoolean(LOGIN_SCREEN_AS_DEFAULT, true); |
|||
} |
|||
|
|||
private boolean validateRetrievedCookies() { |
|||
List<Cookie> cookieList = cookieJar.loadForRequest(indexUrl); |
|||
for (Cookie cookie : cookieList) { |
|||
if (cookie.name().equals("THMMYgrC00ki3")) |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
// Call validateRetrievedCookies() first
|
|||
private void setPersistentCookieSession() { |
|||
List<Cookie> cookieList = cookieJar.loadForRequest(indexUrl); |
|||
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, "Guest").apply(); |
|||
sharedPrefs.edit().putInt(USER_ID, -1).apply(); |
|||
sharedPrefs.edit().putBoolean(LOGGED_IN, false).apply(); //User logs out
|
|||
} |
|||
|
|||
private void setLoginScreenAsDefault(boolean b) { |
|||
sharedPrefs.edit().putBoolean(LOGIN_SCREEN_AS_DEFAULT, b).apply(); |
|||
} |
|||
} |
After Width: | Height: | Size: 128 B |
After Width: | Height: | Size: 103 B |
After Width: | Height: | Size: 94 B |
After Width: | Height: | Size: 90 B |
After Width: | Height: | Size: 116 B |
After Width: | Height: | Size: 112 B |
After Width: | Height: | Size: 140 B |
After Width: | Height: | Size: 135 B |
After Width: | Height: | Size: 173 B |
After Width: | Height: | Size: 163 B |