1
0
Fork 0
mirror of https://github.com/geometer/FBReaderJ.git synced 2025-10-05 02:39:23 +02:00

part of litres plugin moved to the main code

This commit is contained in:
Nikolay Pultsin 2014-12-27 05:42:21 +00:00
parent 1219b197fe
commit 3151b9ed82
17 changed files with 1033 additions and 35 deletions

View file

@ -308,6 +308,8 @@
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name="org.geometerplus.android.fbreader.network.AuthorisationMenuActivity" android:process=":networkLibrary" android:theme="@style/FBReader.Dialog" android:configChanges="orientation|keyboardHidden|screenSize"/> <activity android:name="org.geometerplus.android.fbreader.network.AuthorisationMenuActivity" android:process=":networkLibrary" android:theme="@style/FBReader.Dialog" android:configChanges="orientation|keyboardHidden|screenSize"/>
<activity android:name="org.geometerplus.android.fbreader.network.litres.UserRegistrationActivity" android:process=":networkLibrary" android:theme="@style/FBReader.Dialog" android:configChanges="orientation|keyboardHidden|screenSize"/>
<activity android:name="org.geometerplus.android.fbreader.network.litres.AutoRegistrationActivity" android:process=":networkLibrary" android:theme="@style/FBReader.Dialog" android:configChanges="orientation|keyboardHidden|screenSize"/>
<activity android:name="org.geometerplus.android.fbreader.network.TopupMenuActivity" android:process=":networkLibrary" android:theme="@style/FBReader.Dialog" android:configChanges="orientation|keyboardHidden|screenSize"/> <activity android:name="org.geometerplus.android.fbreader.network.TopupMenuActivity" android:process=":networkLibrary" android:theme="@style/FBReader.Dialog" android:configChanges="orientation|keyboardHidden|screenSize"/>
<activity android:name="org.geometerplus.android.fbreader.network.NetworkBookInfoActivity" android:process=":networkLibrary" android:theme="@style/FBReader.Activity" android:configChanges="orientation|keyboardHidden|screenSize"> <activity android:name="org.geometerplus.android.fbreader.network.NetworkBookInfoActivity" android:process=":networkLibrary" android:theme="@style/FBReader.Activity" android:configChanges="orientation|keyboardHidden|screenSize">
<intent-filter> <intent-filter>

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<RadioButton xmlns:android="http://schemas.android.com/apk/res/android"
android:minHeight="?android:attr/listPreferredItemHeight"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
android:gravity="center_vertical|left"
/>

View file

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/lr_user_registration_dialog"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingTop="15dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:orientation="vertical"
>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/lr_auto_registration_text"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignParentTop="true"
android:paddingLeft="10dip"
android:paddingRight="10dip"
android:paddingBottom="14dip"
android:textAppearance="?android:attr/textAppearanceMedium"
/>
<include layout="@layout/lr_action_item" android:id="@+id/lr_auto_registration_action_signin" />
<include layout="@layout/lr_action_item" android:id="@+id/lr_auto_registration_action_recover" />
<include layout="@layout/lr_action_item" android:id="@+id/lr_auto_registration_action_change_email" />
<include layout="@layout/lr_email_control" android:id="@+id/lr_auto_registration_email_control" />
<include layout="@layout/ok_cancel_buttons" android:id="@+id/lr_auto_registration_buttons" />
</LinearLayout>
</ScrollView>

View file

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<Button
android:id="@+id/lr_email_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/dropdown"
android:layout_alignParentRight="true"
/>
<EditText
android:id="@+id/lr_email_edit"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:inputType="textEmailAddress"
android:layout_toLeftOf="@id/lr_email_button"
android:layout_alignWithParentIfMissing="true"
android:layout_alignParentLeft="true"
/>
</RelativeLayout>

View file

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/lr_user_registration_dialog"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingTop="15dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:orientation="vertical"
>
<TextView
android:id="@+id/lr_user_registration_login_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:singleLine="true"
/>
<EditText
android:id="@+id/lr_user_registration_login"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:singleLine="true"
/>
<TextView
android:id="@+id/lr_user_registration_password_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:layout_marginTop="5dp"
/>
<EditText
android:id="@+id/lr_user_registration_password"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:password="true"
/>
<TextView
android:id="@+id/lr_user_registration_confirm_password_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:layout_marginTop="5dp"
/>
<EditText
android:id="@+id/lr_user_registration_confirm_password"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:password="true"
/>
<TextView
android:id="@+id/lr_user_registration_email_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:layout_marginTop="5dp"
/>
<include layout="@layout/lr_email_control" android:id="@+id/lr_user_registration_email_control" />
<TextView
android:id="@+id/lr_user_registration_error"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:textColor="#ff0000"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
/>
<include layout="@layout/ok_cancel_buttons" android:id="@+id/lr_user_registration_buttons" />
</LinearLayout>
</ScrollView>

View file

@ -23,14 +23,16 @@ import android.app.Activity;
import android.content.*; import android.content.*;
import android.net.Uri; import android.net.Uri;
import org.geometerplus.zlibrary.core.resources.ZLResource;
import org.geometerplus.fbreader.network.INetworkLink; import org.geometerplus.fbreader.network.INetworkLink;
import org.geometerplus.fbreader.network.NetworkLibrary; import org.geometerplus.fbreader.network.NetworkLibrary;
import org.geometerplus.fbreader.network.urlInfo.UrlInfo; import org.geometerplus.fbreader.network.urlInfo.UrlInfo;
import org.geometerplus.fbreader.network.authentication.NetworkAuthenticationManager; import org.geometerplus.fbreader.network.authentication.NetworkAuthenticationManager;
import org.geometerplus.android.util.PackageUtil;
import org.geometerplus.android.fbreader.api.PluginApi; import org.geometerplus.android.fbreader.api.PluginApi;
import org.geometerplus.android.fbreader.network.litres.AutoRegistrationActivity;
import org.geometerplus.android.fbreader.network.litres.UserRegistrationActivity;
public class AuthorisationMenuActivity extends MenuActivity { public class AuthorisationMenuActivity extends MenuActivity {
public static void runMenu(Context context, INetworkLink link) { public static void runMenu(Context context, INetworkLink link) {
@ -49,22 +51,34 @@ public class AuthorisationMenuActivity extends MenuActivity {
@Override @Override
protected void init() { protected void init() {
setTitle(NetworkLibrary.resource().getResource("authorisationMenuTitle").getValue()); final String baseUrl = getIntent().getData().toString();
final String url = getIntent().getData().toString(); final ZLResource resource = NetworkLibrary.resource();
myLink = NetworkLibrary.Instance().getLinkByUrl(url);
setTitle(resource.getResource("authorisationMenuTitle").getValue());
myLink = NetworkLibrary.Instance().getLinkByUrl(baseUrl);
if (myLink.getUrlInfo(UrlInfo.Type.SignIn) != null) { if (myLink.getUrlInfo(UrlInfo.Type.SignIn) != null) {
myInfos.add(new PluginApi.MenuActionInfo( myInfos.add(new PluginApi.MenuActionInfo(
Uri.parse(url + "/signIn"), Uri.parse(baseUrl + "/signIn"),
NetworkLibrary.resource().getResource("signIn").getValue(), resource.getResource("signIn").getValue(),
0 0
)); ));
myInfos.add(new PluginApi.MenuActionInfo(
Uri.parse(baseUrl + "/signUp"),
resource.getResource("signUp").getValue(),
1
));
myInfos.add(new PluginApi.MenuActionInfo(
Uri.parse(baseUrl + "/quickBuy"),
resource.getResource("quickBuy").getValue(),
2
));
} }
} }
@Override @Override
protected String getAction() { protected String getAction() {
return Util.AUTHORIZATION_ACTION; return Util.AUTHORISATION_ACTION;
} }
@Override @Override
@ -73,11 +87,10 @@ public class AuthorisationMenuActivity extends MenuActivity {
final NetworkAuthenticationManager mgr = myLink.authenticationManager(); final NetworkAuthenticationManager mgr = myLink.authenticationManager();
if (info.getId().toString().endsWith("/signIn")) { if (info.getId().toString().endsWith("/signIn")) {
Util.runAuthenticationDialog(AuthorisationMenuActivity.this, myLink, null); Util.runAuthenticationDialog(AuthorisationMenuActivity.this, myLink, null);
} else { } else if (info.getId().toString().endsWith("/signUp")) {
final Intent intent = Util.authorisationIntent(myLink, info.getId()); startActivity(Util.authorisationIntent(myLink, this, UserRegistrationActivity.class));
if (PackageUtil.canBeStarted(AuthorisationMenuActivity.this, intent, true)) { } else if (info.getId().toString().endsWith("/quickBuy")) {
startActivity(intent); startActivity(Util.authorisationIntent(myLink, this, AutoRegistrationActivity.class));
}
} }
} catch (Exception e) { } catch (Exception e) {
// do nothing // do nothing

View file

@ -38,8 +38,10 @@ import org.geometerplus.fbreader.network.urlInfo.UrlInfo;
import org.geometerplus.android.util.UIUtil; import org.geometerplus.android.util.UIUtil;
import org.geometerplus.android.util.PackageUtil; import org.geometerplus.android.util.PackageUtil;
import org.geometerplus.android.fbreader.network.litres.UserRegistrationActivity;
public abstract class Util implements UserRegistrationConstants { public abstract class Util implements UserRegistrationConstants {
static final String AUTHORIZATION_ACTION = "android.fbreader.action.network.AUTHORIZATION"; static final String AUTHORISATION_ACTION = "android.fbreader.action.network.AUTHORISATION";
static final String SIGNIN_ACTION = "android.fbreader.action.network.SIGNIN"; static final String SIGNIN_ACTION = "android.fbreader.action.network.SIGNIN";
static final String TOPUP_ACTION = "android.fbreader.action.network.TOPUP"; static final String TOPUP_ACTION = "android.fbreader.action.network.TOPUP";
static final String EXTRA_CATALOG_ACTION = "android.fbreader.action.network.EXTRA_CATALOG"; static final String EXTRA_CATALOG_ACTION = "android.fbreader.action.network.EXTRA_CATALOG";
@ -80,8 +82,8 @@ public abstract class Util implements UserRegistrationConstants {
}); });
} }
static Intent authorisationIntent(INetworkLink link, Uri id) { static Intent authorisationIntent(INetworkLink link, Activity activity, Class<? extends Activity> cls) {
final Intent intent = new Intent(AUTHORIZATION_ACTION, id); final Intent intent = new Intent(activity, cls);
intent.putExtra(CATALOG_URL, link.getUrl(UrlInfo.Type.Catalog)); intent.putExtra(CATALOG_URL, link.getUrl(UrlInfo.Type.Catalog));
intent.putExtra(SIGNIN_URL, link.getUrl(UrlInfo.Type.SignIn)); intent.putExtra(SIGNIN_URL, link.getUrl(UrlInfo.Type.SignIn));
intent.putExtra(SIGNUP_URL, link.getUrl(UrlInfo.Type.SignUp)); intent.putExtra(SIGNUP_URL, link.getUrl(UrlInfo.Type.SignUp));
@ -89,21 +91,17 @@ public abstract class Util implements UserRegistrationConstants {
return intent; return intent;
} }
private static Intent registrationIntent(INetworkLink link) { public static boolean isRegistrationSupported(INetworkLink link) {
return authorisationIntent(link, Uri.parse(link.getUrl(UrlInfo.Type.Catalog) + "/register")); return "litres.ru".equals(link.getHostName());
}
public static boolean isRegistrationSupported(Activity activity, INetworkLink link) {
return PackageUtil.canBeStarted(activity, registrationIntent(link), true);
} }
public static void runRegistrationDialog(Activity activity, INetworkLink link) { public static void runRegistrationDialog(Activity activity, INetworkLink link) {
try { if (isRegistrationSupported(link)) {
final Intent intent = registrationIntent(link); try {
if (PackageUtil.canBeStarted(activity, intent, true)) { final Intent intent = authorisationIntent(link, activity, UserRegistrationActivity.class);
activity.startActivity(intent); activity.startActivity(intent);
} catch (ActivityNotFoundException e) {
} }
} catch (ActivityNotFoundException e) {
} }
} }

View file

@ -44,7 +44,7 @@ public class SignUpAction extends Action {
return return
mgr != null && mgr != null &&
!mgr.mayBeAuthorised(false) && !mgr.mayBeAuthorised(false) &&
Util.isRegistrationSupported(myActivity, link); Util.isRegistrationSupported(link);
} }
@Override @Override

View file

@ -0,0 +1,305 @@
/*
* Copyright (C) 2010-2011 Geometer Plus <contact@geometerplus.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
package org.geometerplus.android.fbreader.network.litres;
import java.util.ArrayList;
import android.content.Intent;
import android.os.Bundle;
import android.view.*;
import android.widget.*;
import org.geometerplus.zlibrary.core.network.ZLNetworkAuthenticationException;
import org.geometerplus.zlibrary.core.network.ZLNetworkException;
import org.geometerplus.zlibrary.core.resources.ZLResource;
import org.geometerplus.zlibrary.ui.android.R;
import org.geometerplus.fbreader.network.authentication.litres.*;
/*
* Algorithm:
* step 0. Select first e-mail from the list
* a. Success =} 1
* b. E-mails list is empty =} 4
* step 1. try to login with auto-generated username/password
* a. Success =} 'login successful' dilaog =} finish
* b. Authentication failure =} 2
* c. Any other problem =} show error message =} finish
* step 2. try to register with given e-mail + auto-generated username/password
* a. Success =} 'registration successful' dialog =} finish
* b. Username already in used =} 3
* c. E-address already in use =} 3
* d. Any other problem =} show error message =} finish
* step 3. 'e-address already in use' dialog, choices:
* a. Sign in =} standard sign in dialog
* b. Send password =} 5
* c. Select other email =} 4
* step 4. 'email selection' dialog
* a. Ok =} 1
* b. Cancel =} finish
* step 5. send password
* a. Success =} 'password sent dialog' =} finish
* b. Failure =} show error message =} finish
*/
public class AutoRegistrationActivity extends RegistrationActivity {
private final RegistrationUtils myUtil = new RegistrationUtils(this);
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
final ZLResource dialogResource = ZLResource.resource("dialog");
final ZLResource buttonResource = dialogResource.getResource("button");
myResource = dialogResource.getResource("litresAutoSignIn");
setContentView(R.layout.lr_auto_registration);
setTitle(myResource.getResource("title").getValue());
getOkButton().setText(buttonResource.getResource("ok").getValue());
getCancelButton().setText(buttonResource.getResource("cancel").getValue());
getTextArea().setVisibility(View.GONE);
getActionSignIn().setVisibility(View.GONE);
getActionAnotherEmail().setVisibility(View.GONE);
getActionRecover().setVisibility(View.GONE);
getEmailControl().setVisibility(View.GONE);
getButtons().setVisibility(View.GONE);
startAutoRegistration();
}
// step 0
private void startAutoRegistration() {
final String email = myUtil.firstEMail();
if (email != null) {
runAutoLogin(email);
} else {
runEmailSelectionDialog(null);
}
}
// step 1
private void runAutoLogin(final String email) {
final String username = myUtil.getAutoLogin(email);
final String password = myUtil.getAutoPassword();
final SignInNetworkRunnable runnable = new SignInNetworkRunnable(username, password);
final PostRunnable post = new PostRunnable() {
public void run(ZLNetworkException e) {
if (e == null) {
reportSuccess(username, password, runnable.XmlReader.Sid);
showFinalMessage(
myResource.getResource("signedIn").getValue()
.replace("%s", email)
);
} else if (e instanceof ZLNetworkAuthenticationException) {
runAutoRegistraion(email);
} else {
showErrorMessage(e);
}
}
};
runWithMessage("autoSignIn", runnable, post);
}
// step 2
private void runAutoRegistraion(final String email) {
final String username = myUtil.getAutoLogin(email);
final String password = myUtil.getAutoPassword();
final RegistrationNetworkRunnable runnable =
new RegistrationNetworkRunnable(username, password, email);
final PostRunnable post = new PostRunnable() {
public void run(ZLNetworkException e) {
if (e == null) {
reportSuccess(username, password, runnable.XmlReader.Sid);
showFinalMessage(
myResource.getResource("registrationSuccessful").getValue()
.replace("%s", email)
);
} else if (e instanceof LitResRegisterUserXMLReader.AlreadyInUseException) {
runEmailAlreadyInUseDialog(email);
} else {
showErrorMessage(e);
}
}
};
runWithMessage("autoSignIn", runnable, post);
}
// step 3
private void runEmailAlreadyInUseDialog(final String email) {
final ZLResource actionResource = myResource.getResource("actions");
getTextArea().setVisibility(View.VISIBLE);
getTextArea().setText(actionResource.getResource("title").getValue().replace("%s", email));
final View.OnClickListener rbListener = new View.OnClickListener() {
public void onClick(View view) {
final RadioButton rb = (RadioButton)view;
getActionSignIn().setChecked(false);
getActionAnotherEmail().setChecked(false);
getActionRecover().setChecked(false);
rb.setChecked(true);
getOkButton().setEnabled(true);
}
};
getActionSignIn().setVisibility(View.GONE);
/*
getActionSignIn().setVisibility(View.VISIBLE);
getActionSignIn().setText(actionResource.getResource("signIn").getValue());
getActionSignIn().setOnClickListener(rbListener);
*/
getActionAnotherEmail().setVisibility(View.VISIBLE);
getActionAnotherEmail().setText(actionResource.getResource("anotherEmail").getValue());
getActionAnotherEmail().setOnClickListener(rbListener);
getActionRecover().setVisibility(View.VISIBLE);
getActionRecover().setText(actionResource.getResource("recover").getValue());
getActionRecover().setOnClickListener(rbListener);
getEmailControl().setVisibility(View.GONE);
getButtons().setVisibility(View.VISIBLE);
getOkButton().setVisibility(View.VISIBLE);
getOkButton().setEnabled(false);
getOkButton().setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
if (getActionSignIn().isChecked()) {
// TODO: implement
} else if (getActionAnotherEmail().isChecked()) {
runEmailSelectionDialog(email);
} else if (getActionRecover().isChecked()) {
recoverAccountInformation(email);
}
}
});
getCancelButton().setVisibility(View.VISIBLE);
getCancelButton().setOnClickListener(myFinishListener);
}
// step 4
private void runEmailSelectionDialog(String email) {
getTextArea().setVisibility(View.VISIBLE);
getTextArea().setText(myResource.getResource("email").getValue());
getActionSignIn().setVisibility(View.GONE);
getActionAnotherEmail().setVisibility(View.GONE);
getActionRecover().setVisibility(View.GONE);
getEmailControl().setVisibility(View.VISIBLE);
setupEmailControl(getEmailControl(), email);
getButtons().setVisibility(View.VISIBLE);
getOkButton().setVisibility(View.VISIBLE);
getOkButton().setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
runAutoLogin(getEmailTextView().getText().toString().trim());
}
});
getCancelButton().setVisibility(View.VISIBLE);
getCancelButton().setOnClickListener(myFinishListener);
}
// step 5
private void recoverAccountInformation(final String email) {
System.err.println("recoverAccountInformation 0");
final LitResPasswordRecoveryXMLReader xmlReader = new LitResPasswordRecoveryXMLReader();
final NetworkRunnable runnable = new NetworkRunnable() {
public void run() throws ZLNetworkException {
System.err.println("recoverAccountInformation 1");
final LitResNetworkRequest request = new LitResNetworkRequest(myRecoverPasswordURL, xmlReader);
request.addPostParameter("mail", email);
myNetworkContext.perform(request);
}
};
final PostRunnable post = new PostRunnable() {
public void run(ZLNetworkException e) {
System.err.println("recoverAccountInformation 2");
if (e == null) {
System.err.println("recoverAccountInformation 3");
showFinalMessage(
myResource.getResource("passwordSent").getValue().replace("%s", email)
);
} else {
System.err.println("recoverAccountInformation 4");
showErrorMessage(e);
}
}
};
System.err.println("recoverAccountInformation 5");
runWithMessage("recoverPassword", runnable, post);
System.err.println("recoverAccountInformation 6");
}
private TextView getTextArea() {
return (TextView)findViewById(R.id.lr_auto_registration_text);
}
private RadioButton getActionSignIn() {
return (RadioButton)findViewById(R.id.lr_auto_registration_action_signin);
}
private RadioButton getActionAnotherEmail() {
return (RadioButton)findViewById(R.id.lr_auto_registration_action_change_email);
}
private RadioButton getActionRecover() {
return (RadioButton)findViewById(R.id.lr_auto_registration_action_recover);
}
private View getEmailControl() {
return findViewById(R.id.lr_auto_registration_email_control);
}
private TextView getEmailTextView() {
return (TextView)getEmailControl().findViewById(R.id.lr_email_edit);
}
private View getButtons() {
return findViewById(R.id.lr_auto_registration_buttons);
}
private Button getOkButton() {
return (Button)getButtons().findViewById(R.id.ok_button);
}
private Button getCancelButton() {
return (Button)getButtons().findViewById(R.id.cancel_button);
}
private final View.OnClickListener myFinishListener = new View.OnClickListener() {
public void onClick(View view) {
AutoRegistrationActivity.this.finish();
}
};
private void showFinalMessage(String message) {
getTextArea().setVisibility(View.VISIBLE);
getTextArea().setText(message);
getActionSignIn().setVisibility(View.GONE);
getActionAnotherEmail().setVisibility(View.GONE);
getActionRecover().setVisibility(View.GONE);
getEmailControl().setVisibility(View.GONE);
getButtons().setVisibility(View.VISIBLE);
getOkButton().setVisibility(View.VISIBLE);
getOkButton().setOnClickListener(myFinishListener);
getCancelButton().setVisibility(View.GONE);
}
private void showErrorMessage(ZLNetworkException exception) {
exception.printStackTrace();
showFinalMessage(exception.getMessage());
}
}

View file

@ -0,0 +1,186 @@
/*
* Copyright (C) 2010-2011 Geometer Plus <contact@geometerplus.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
package org.geometerplus.android.fbreader.network.litres;
import java.util.List;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import org.geometerplus.zlibrary.core.network.ZLNetworkException;
import org.geometerplus.zlibrary.core.resources.ZLResource;
import org.geometerplus.zlibrary.ui.android.R;
import org.geometerplus.fbreader.network.authentication.litres.*;
import org.geometerplus.android.fbreader.network.auth.ActivityNetworkContext;
abstract class RegistrationActivity extends Activity implements UserRegistrationConstants {
protected final ActivityNetworkContext myNetworkContext = new ActivityNetworkContext(this);
protected ZLResource myResource;
protected String myCatalogURL;
private String mySignInURL;
private String mySignUpURL;
protected String myRecoverPasswordURL;
protected void reportSuccess(String username, String password, String sid) {
final Intent data = new Intent("android.fbreader.action.network.SIGNIN");
data.putExtra(USER_REGISTRATION_USERNAME, username);
data.putExtra(USER_REGISTRATION_PASSWORD, password);
data.putExtra(USER_REGISTRATION_LITRES_SID, sid);
data.putExtra(CATALOG_URL, myCatalogURL);
sendBroadcast(data);
}
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
final Intent intent = getIntent();
myCatalogURL = intent.getStringExtra(CATALOG_URL);
mySignInURL = intent.getStringExtra(SIGNIN_URL);
mySignUpURL = intent.getStringExtra(SIGNUP_URL);
myRecoverPasswordURL = intent.getStringExtra(RECOVER_PASSWORD_URL);
}
protected static interface NetworkRunnable {
void run() throws ZLNetworkException;
}
protected class RegistrationNetworkRunnable implements NetworkRunnable {
final String Username;
final String Password;
final String Email;
final LitResRegisterUserXMLReader XmlReader = new LitResRegisterUserXMLReader();
public RegistrationNetworkRunnable(String username, String password, String email) {
Username = username;
Password = password;
Email = email;
}
public void run() throws ZLNetworkException {
final LitResNetworkRequest request = new LitResNetworkRequest(mySignUpURL, XmlReader);
request.addPostParameter("new_login", Username);
request.addPostParameter("new_pwd1", Password);
request.addPostParameter("mail", Email);
myNetworkContext.perform(request);
}
}
protected class SignInNetworkRunnable implements NetworkRunnable {
final String Username;
final String Password;
final LitResLoginXMLReader XmlReader = new LitResLoginXMLReader();
public SignInNetworkRunnable(String username, String password) {
Username = username;
Password = password;
}
public void run() throws ZLNetworkException {
final LitResNetworkRequest request = new LitResNetworkRequest(mySignInURL, XmlReader);
request.addPostParameter("login", Username);
request.addPostParameter("pwd", Password);
myNetworkContext.perform(request);
}
}
protected static interface PostRunnable {
void run(ZLNetworkException exception);
}
protected synchronized void runWithMessage(String key, final NetworkRunnable action, final PostRunnable postAction) {
final String message =
ZLResource.resource("dialog").getResource("waitMessage").getResource(key).getValue();
final ProgressDialog progress = ProgressDialog.show(this, null, message, true, false);
new Thread(new Runnable() {
public void run() {
try {
action.run();
postRun(null);
} catch (ZLNetworkException e) {
postRun(e);
}
}
private void postRun(final ZLNetworkException e) {
runOnUiThread(new Runnable() {
public void run() {
progress.dismiss();
postAction.run(e);
}
});
}
}).start();
}
protected void setupEmailControl(View emailControl, String eMailToSkip) {
final Button emailListButton = (Button)emailControl.findViewById(R.id.lr_email_button);
final TextView emailTextView = (TextView)emailControl.findViewById(R.id.lr_email_edit);
final List<String> emails = new RegistrationUtils(getApplicationContext()).eMails();
emailListButton.setVisibility(emails.size() > 1 ? View.VISIBLE : View.GONE);
if (!emails.isEmpty()) {
emailTextView.setText(emails.get(0));
for (String e : emails) {
if (!e.equals(eMailToSkip)) {
emailTextView.setText(e);
break;
}
}
final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (which >= 0 && which < emails.size()) {
emailTextView.setText(emails.get(which));
}
dialog.dismiss();
}
};
emailListButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
final String selectedEmail = emailTextView.getText().toString().trim();
final int selected = emails.indexOf(selectedEmail);
final ZLResource buttonResource = ZLResource.resource("dialog").getResource("button");
final AlertDialog dialog = new AlertDialog.Builder(RegistrationActivity.this)
.setSingleChoiceItems(emails.toArray(new String[emails.size()]), selected, listener)
.setTitle(myResource.getResource("email").getValue())
.setNegativeButton(buttonResource.getResource("cancel").getValue(), null)
.create();
dialog.show();
}
});
}
}
}

View file

@ -0,0 +1,100 @@
/*
* Copyright (C) 2010-2011 Geometer Plus <contact@geometerplus.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
package org.geometerplus.android.fbreader.network.litres;
import java.util.*;
import java.lang.reflect.*;
import java.math.BigInteger;
import java.security.SecureRandom;
import android.content.Context;
import android.net.wifi.WifiManager;
public class RegistrationUtils {
private final Context myContext;
public RegistrationUtils(Context context) {
myContext = context;
}
public String getAutoLogin(String email) {
return email != null
? "fbreader-auto-" + email.replace(".", "-").replace("@", "-at-") : null;
}
public String getAutoPassword() {
try {
final WifiManager wifi = (WifiManager)myContext.getSystemService(Context.WIFI_SERVICE);
final String mac = wifi.getConnectionInfo().getMacAddress();
if (mac.length() > 3) {
return "XXX" + mac;
}
} catch (Exception e) {
}
return new BigInteger(50, new SecureRandom()).toString(32);
}
private List<String> myEMails;
public List<String> eMails() {
collectEMails();
return myEMails;
}
public String firstEMail() {
collectEMails();
return myEMails.size() > 0 ? myEMails.get(0) : null;
}
private void collectEMails() {
if (myEMails != null) {
return;
}
try {
final Class<?> cls$AccountManager = Class.forName("android.accounts.AccountManager");
final Class<?> cls$Account = Class.forName("android.accounts.Account");
final Method meth$AccountManager$get = cls$AccountManager.getMethod("get", Context.class);
final Method meth$AccountManager$getAccountsByType = cls$AccountManager.getMethod("getAccountsByType", String.class);
final Field fld$Account$name = cls$Account.getField("name");
if (meth$AccountManager$get.getReturnType() == cls$AccountManager
&& meth$AccountManager$getAccountsByType.getReturnType().getComponentType() == cls$Account
&& fld$Account$name.getType() == String.class) {
final Object mgr = meth$AccountManager$get.invoke(null, myContext);
final Object[] accountsByType = (Object[]) meth$AccountManager$getAccountsByType.invoke(mgr, "com.google");
myEMails = new ArrayList<String>(accountsByType.length);
for (Object a: accountsByType) {
final String value = (String) fld$Account$name.get(a);
if (value != null && value.length() > 0) {
myEMails.add(value);
}
}
return;
}
} catch (ClassNotFoundException e) {
} catch (NoSuchMethodException e) {
} catch (NoSuchFieldException e) {
} catch (IllegalAccessException e) {
} catch (IllegalArgumentException e) {
} catch (InvocationTargetException e) {
}
myEMails = Collections.<String>emptyList();
}
}

View file

@ -0,0 +1,147 @@
/*
* Copyright (C) 2010-2011 Geometer Plus <contact@geometerplus.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
package org.geometerplus.android.fbreader.network.litres;
import java.util.List;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import org.geometerplus.zlibrary.core.network.ZLNetworkManager;
import org.geometerplus.zlibrary.core.network.ZLNetworkException;
import org.geometerplus.zlibrary.core.resources.ZLResource;
import org.geometerplus.zlibrary.ui.android.R;
public class UserRegistrationActivity extends RegistrationActivity {
private TextView findTextView(int resourceId) {
return (TextView)findViewById(resourceId);
}
private Button findButton(int resourceId) {
return (Button)findViewById(resourceId);
}
private String getViewText(int resourceId) {
return findTextView(resourceId).getText().toString().trim();
}
private void setViewText(int resourceId, String text) {
findTextView(resourceId).setText(text);
}
private void setViewTextFromResource(int resourceId, String fbResourceKey) {
setViewText(resourceId, myResource.getResource(fbResourceKey).getValue());
}
private void setErrorMessage(String errorMessage) {
final TextView errorLabel = findTextView(R.id.lr_user_registration_error);
errorLabel.setVisibility(View.VISIBLE);
errorLabel.setText(errorMessage);
}
private void setErrorMessageFromResource(String resourceKey) {
setErrorMessage(ZLResource.resource("dialog").getResource("networkError").getResource(resourceKey).getValue());
}
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
myResource = ZLResource.resource("dialog").getResource("litresUserRegistration");
//Thread.setDefaultUncaughtExceptionHandler(new org.geometerplus.zlibrary.ui.android.library.UncaughtExceptionHandler(this));
setContentView(R.layout.lr_user_registration);
setTitle(myResource.getResource("title").getValue());
setViewTextFromResource(R.id.lr_user_registration_login_text, "login");
setViewTextFromResource(R.id.lr_user_registration_password_text, "password");
setViewTextFromResource(R.id.lr_user_registration_confirm_password_text, "confirmPassword");
setViewTextFromResource(R.id.lr_user_registration_email_text, "email");
final TextView errorLabel = findTextView(R.id.lr_user_registration_error);
errorLabel.setVisibility(View.GONE);
errorLabel.setText("");
final ZLResource buttonResource = ZLResource.resource("dialog").getResource("button");
final View buttonsView = findViewById(R.id.lr_user_registration_buttons);
final Button okButton = (Button)buttonsView.findViewById(R.id.ok_button);
final Button cancelButton = (Button)buttonsView.findViewById(R.id.cancel_button);
final View emailControl = findViewById(R.id.lr_user_registration_email_control);
final TextView emailTextView = (TextView)emailControl.findViewById(R.id.lr_email_edit);
okButton.setText(buttonResource.getResource("ok").getValue());
okButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
final String userName = getViewText(R.id.lr_user_registration_login);
final String password = getViewText(R.id.lr_user_registration_password);
final String confirmPassword = getViewText(R.id.lr_user_registration_confirm_password);
final String email = emailTextView.getText().toString().trim();
if (userName.length() == 0) {
setErrorMessageFromResource("usernameNotSpecified");
return;
}
if (!password.equals(confirmPassword)) {
setErrorMessageFromResource("passwordsDoNotMatch");
return;
}
if (password.length() == 0) {
setErrorMessageFromResource("passwordNotSpecified");
return;
}
if (email.length() == 0) {
setErrorMessageFromResource("emailNotSpecified");
return;
}
final int atPos = email.indexOf("@");
if (atPos == -1 || email.indexOf(".", atPos) == -1) {
setErrorMessageFromResource("invalidEMail");
return;
}
final RegistrationNetworkRunnable runnable =
new RegistrationNetworkRunnable(userName, password, email);
final PostRunnable postRunnable = new PostRunnable() {
public void run(ZLNetworkException exception) {
if (exception == null) {
reportSuccess(userName, password, runnable.XmlReader.Sid);
finish();
} else {
setErrorMessage(exception.getMessage());
}
}
};
runWithMessage("registerUser", runnable, postRunnable);
}
});
cancelButton.setText(buttonResource.getResource("cancel").getValue());
cancelButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
finish();
}
});
setupEmailControl(emailControl, null);
}
}

View file

@ -0,0 +1,32 @@
/*
* Copyright (C) 2010-2011 Geometer Plus <contact@geometerplus.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
package org.geometerplus.android.fbreader.network.litres;
public interface UserRegistrationConstants {
String CATALOG_URL = "catalogUrl";
String SIGNIN_URL = "signinUrl";
String SIGNUP_URL = "signupUrl";
String RECOVER_PASSWORD_URL = "recoverPasswordUrl";
String USER_REGISTRATION_USERNAME = "userName";
String USER_REGISTRATION_PASSWORD = "password";
String USER_REGISTRATION_EMAIL = "eMail";
String USER_REGISTRATION_LITRES_SID = "litres:sid";
}

View file

@ -30,9 +30,9 @@ public abstract class NetworkException extends ZLNetworkException {
public static final String ERROR_BOOK_NOT_PURCHASED = "bookNotPurchased"; public static final String ERROR_BOOK_NOT_PURCHASED = "bookNotPurchased";
public static final String ERROR_DOWNLOAD_LIMIT_EXCEEDED = "downloadLimitExceeded"; public static final String ERROR_DOWNLOAD_LIMIT_EXCEEDED = "downloadLimitExceeded";
public static final String ERROR_EMAIL_WAS_NOT_SPECIFIED = "emailNotSpecified"; public static final String ERROR_EMAIL_NOT_SPECIFIED = "emailNotSpecified";
public static final String ERROR_NO_USER_EMAIL = "noUserEmail"; public static final String ERROR_NO_USER_FOR_EMAIL = "noUserForEmail";
public static final String ERROR_UNSUPPORTED_OPERATION = "unsupportedOperation"; public static final String ERROR_UNSUPPORTED_OPERATION = "unsupportedOperation";

View file

@ -23,7 +23,7 @@ import org.geometerplus.zlibrary.core.xml.ZLStringMap;
import org.geometerplus.zlibrary.core.network.ZLNetworkAuthenticationException; import org.geometerplus.zlibrary.core.network.ZLNetworkAuthenticationException;
import org.geometerplus.zlibrary.core.network.ZLNetworkException; import org.geometerplus.zlibrary.core.network.ZLNetworkException;
class LitResLoginXMLReader extends LitResAuthenticationXMLReader { public class LitResLoginXMLReader extends LitResAuthenticationXMLReader {
private static final String TAG_AUTHORIZATION_OK = "catalit-authorization-ok"; private static final String TAG_AUTHORIZATION_OK = "catalit-authorization-ok";
private static final String TAG_AUTHORIZATION_FAILED = "catalit-authorization-failed"; private static final String TAG_AUTHORIZATION_FAILED = "catalit-authorization-failed";

View file

@ -24,7 +24,7 @@ import org.geometerplus.zlibrary.core.network.ZLNetworkException;
import org.geometerplus.fbreader.network.NetworkException; import org.geometerplus.fbreader.network.NetworkException;
class LitResPasswordRecoveryXMLReader extends LitResAuthenticationXMLReader { public class LitResPasswordRecoveryXMLReader extends LitResAuthenticationXMLReader {
private static final String TAG_PASSWORD_RECOVERY_OK = "catalit-pass-recover-ok"; private static final String TAG_PASSWORD_RECOVERY_OK = "catalit-pass-recover-ok";
private static final String TAG_PASSWORD_RECOVERY_FAILED = "catalit-pass-recover-failed"; private static final String TAG_PASSWORD_RECOVERY_FAILED = "catalit-pass-recover-failed";
@ -34,16 +34,21 @@ class LitResPasswordRecoveryXMLReader extends LitResAuthenticationXMLReader {
if (TAG_PASSWORD_RECOVERY_FAILED == tag) { if (TAG_PASSWORD_RECOVERY_FAILED == tag) {
final String error = attributes.getValue("error"); final String error = attributes.getValue("error");
if ("1".equals(error)) { if ("1".equals(error)) {
setException(ZLNetworkException.forCode(NetworkException.ERROR_NO_USER_EMAIL)); setException(ZLNetworkException.forCode(NetworkException.ERROR_NO_USER_FOR_EMAIL));
} else if ("2".equals(error)) { } else if ("2".equals(error)) {
setException(ZLNetworkException.forCode(NetworkException.ERROR_EMAIL_WAS_NOT_SPECIFIED)); setException(ZLNetworkException.forCode(NetworkException.ERROR_EMAIL_NOT_SPECIFIED));
} else { } else {
setException(ZLNetworkException.forCode(NetworkException.ERROR_INTERNAL)); final String comment = attributes.getValue("coment");
if (comment != null) {
setException(new ZLNetworkException(comment));
} else {
setException(ZLNetworkException.forCode(NetworkException.ERROR_INTERNAL, error));
}
} }
} else if (TAG_PASSWORD_RECOVERY_OK == tag) { } else if (TAG_PASSWORD_RECOVERY_OK == tag) {
// NOP // NOP
} else { } else {
setException(ZLNetworkException.forCode(NetworkException.ERROR_SOMETHING_WRONG, LitResUtil.HOST_NAME)); setException(ZLNetworkException.forCode(ZLNetworkException.ERROR_SOMETHING_WRONG, LitResUtil.HOST_NAME));
} }
return true; return true;
} }

View file

@ -0,0 +1,71 @@
/*
* Copyright (C) 2010-2011 Geometer Plus <contact@geometerplus.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
package org.geometerplus.fbreader.network.authentication.litres;
import org.geometerplus.zlibrary.core.xml.ZLStringMap;
import org.geometerplus.zlibrary.core.network.ZLNetworkException;
import org.geometerplus.fbreader.network.NetworkException;
public class LitResRegisterUserXMLReader extends LitResAuthenticationXMLReader {
private static final String TAG_AUTHORIZATION_OK = "catalit-authorization-ok";
private static final String TAG_REGISTRATION_FAILED = "catalit-registration-failed";
public String Sid;
public static final class AlreadyInUseException extends ZLNetworkException {
public AlreadyInUseException(String code) {
super(errorMessage(code));
}
}
@Override
public boolean startElementHandler(String tag, ZLStringMap attributes) {
tag = tag.toLowerCase().intern();
if (TAG_REGISTRATION_FAILED == tag) {
final String error = attributes.getValue("error");
if ("1".equals(error)) {
setException(new AlreadyInUseException("usernameAlreadyInUse"));
} else if ("2".equals(error)) {
setException(ZLNetworkException.forCode("usernameNotSpecified"));
} else if ("3".equals(error)) {
setException(ZLNetworkException.forCode("passwordNotSpecified"));
} else if ("4".equals(error)) {
setException(ZLNetworkException.forCode("invalidEMail"));
} else if ("5".equals(error)) {
setException(ZLNetworkException.forCode("tooManyRegistrations"));
} else if ("6".equals(error)) {
setException(new AlreadyInUseException("emailAlreadyInUse"));
} else {
final String comment = attributes.getValue("coment");
if (comment != null) {
setException(new ZLNetworkException(comment));
} else {
setException(ZLNetworkException.forCode(NetworkException.ERROR_INTERNAL));
}
}
} else if (TAG_AUTHORIZATION_OK == tag) {
Sid = attributes.getValue("sid");
} else {
setException(ZLNetworkException.forCode("somethingWrongMessage", LitResUtil.HOST_NAME));
}
return true;
}
}