Merge branch 'master' into Branch_KeeChallenge

Conflicts:
	src/KeePassLib2Android/KeePassLib2Android.csproj
	src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj
	src/keepass2android/Properties/AndroidManifest_nonet.xml
	src/keepass2android/Resources/Resource.designer.cs
	src/keepass2android/keepass2android.csproj
This commit is contained in:
Philipp Crocoll 2014-04-02 06:28:16 +02:00
commit 2cb6c79f0c
51 changed files with 4414 additions and 3666 deletions

33
.gitignore vendored
View File

@ -197,3 +197,36 @@ Thumbs.db
/src/java/JavaFileStorage/.google_apis/drive-v2r102lv1.16.0-rc/drive
/src/java/JavaFileStorage/libs
/src/ArtTestApp/obj
/src/ArtTestApp/bin
/src/KP2AKdbLibraryBinding/bin
/src/KP2AKdbLibraryBinding/obj
/src/ArtTestApp.zip
/src/java/KP2ASoftKeyboard/alt
/src/java/KP2ASoftKeyboard/bin
/src/java/KP2ASoftKeyboard/gen
/src/java/KP2ASoftKeyboard/projectalt
/src/java/KP2ASoftKeyboard/projectzip
/src/java/KP2ASoftKeyboard/projectzip_neu
/src/JavaFileStorageBindings/bin
/src/JavaFileStorageBindings/obj
/src/java/jsch-0.1.50/ChangeLog
/src/java/jsch-0.1.50/LICENSE.txt
/src/java/jsch-0.1.50/README
/src/java/jsch-0.1.50/build.bat
/src/java/jsch-0.1.50/build.sh
/src/java/jsch-0.1.50/build.xml
/src/java/jsch-0.1.50/examples
/src/java/yetanotherworkspace
/src/java/kp2akeytransform - Kopie
/src/java/workspace
/src/java/workspace_
/src/java/workspace_tmp_

Binary file not shown.

Binary file not shown.

View File

@ -31,6 +31,15 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'ReleaseNoNet|AnyCPU'">
<OutputPath>bin\ReleaseNoNet\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="Mono.Android" />
<Reference Include="System" />

View File

@ -29,6 +29,3 @@ using Android.App;
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
// Add some common permissions, these can be removed if not needed
[assembly: UsesPermission(Android.Manifest.Permission.Internet)]
[assembly: UsesPermission(Android.Manifest.Permission.WriteExternalStorage)]

View File

@ -256,8 +256,8 @@ Global
{70D3844A-D9FA-4A64-B205-A84C6A822196}.Release|x64.ActiveCfg = Release|Any CPU
{70D3844A-D9FA-4A64-B205-A84C6A822196}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU
{70D3844A-D9FA-4A64-B205-A84C6A822196}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU
{70D3844A-D9FA-4A64-B205-A84C6A822196}.ReleaseNoNet|Mixed Platforms.ActiveCfg = Release|Any CPU
{70D3844A-D9FA-4A64-B205-A84C6A822196}.ReleaseNoNet|Mixed Platforms.Build.0 = Release|Any CPU
{70D3844A-D9FA-4A64-B205-A84C6A822196}.ReleaseNoNet|Mixed Platforms.ActiveCfg = ReleaseNoNet|Any CPU
{70D3844A-D9FA-4A64-B205-A84C6A822196}.ReleaseNoNet|Mixed Platforms.Build.0 = ReleaseNoNet|Any CPU
{70D3844A-D9FA-4A64-B205-A84C6A822196}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
{70D3844A-D9FA-4A64-B205-A84C6A822196}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
{1FF6C335-A627-43C9-AAA7-CBAC2E74CD18}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

View File

@ -11,5 +11,6 @@ namespace KeePassLib
byte[] HashOfLastStream { get; }
bool CanWrite { get; }
string SuccessMessage { get; }
}
}

View File

@ -20,7 +20,7 @@
<DebugType>full</DebugType>
<Optimize>False</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;EXCLUDE_TWOFISH;EXCLUDE_KEYBOARD;EXCLUDE_FILECHOOSER;EXCLUDE_JAVAFILESTORAGE;EXCLUDE_KEYTRANSFORM</DefineConstants>
<DefineConstants>DEBUG;EXCLUDE_TWOFISH;INCLUDE_KEYBOARD;INCLUDE_FILECHOOSER;INCLUDE_JAVAFILESTORAGE;INCLUDE_KEYTRANSFORM</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>False</ConsolePause>

View File

@ -71,7 +71,7 @@ namespace KeePassLib.Serialization
if(m_bTransacted)
{
m_iocTemp = m_iocBase.CloneDeep();
m_iocTemp.Path += StrTempSuffix;
m_iocTemp.Path += "."+new PwUuid(true).ToHexString().Substring(0,6)+ StrTempSuffix;
}
else m_iocTemp = m_iocBase;
}

View File

@ -506,11 +506,12 @@ namespace KeePassLib.Serialization
}
catch (WebException ex)
{
if ((ex.Response is HttpWebResponse) && (((HttpWebResponse)ex.Response).StatusCode == HttpStatusCode.Unauthorized))
if ((ex.Response is HttpWebResponse) && (((HttpWebResponse) ex.Response).StatusCode == HttpStatusCode.Unauthorized))
{
req = CreateWebRequest(ioc, true);
f(req);
}
else throw;
}
}

View File

@ -146,10 +146,12 @@ namespace keepass2android.Io
if (!IsCached(ioc)
|| GetLocalVersionHash(ioc) == GetBaseVersionHash(ioc))
{
Kp2aLog.Log("CFS: OpenWhenNoLocalChanges");
return OpenFileForReadWhenNoLocalChanges(ioc, cachedFilePath);
}
else
{
Kp2aLog.Log("CFS: OpenWhenLocalChanges");
return OpenFileForReadWhenLocalChanges(ioc, cachedFilePath);
}
}
@ -174,16 +176,21 @@ namespace keepass2android.Io
if (File.ReadAllText(BaseVersionFilePath(ioc)) == hash)
{
Kp2aLog.Log("CFS: No changes in remote");
//no changes in remote file -> upload
using (Stream localData = File.OpenRead(CachedFilePath(ioc)))
{
if (TryUpdateRemoteFile(localData, ioc, true, hash))
{
_cacheSupervisor.UpdatedRemoteFileOnLoad(ioc);
Kp2aLog.Log("CFS: Updated remote file");
}
return File.OpenRead(cachedFilePath);
}
}
else
{
Kp2aLog.Log("CFS: Files in conflict");
//conflict: both files changed.
return OpenFileForReadWithConflict(ioc, cachedFilePath);
}
@ -232,20 +239,27 @@ namespace keepass2android.Io
string previousHash = null;
string baseVersionFilePath = BaseVersionFilePath(ioc);
if (File.Exists(baseVersionFilePath))
{
Kp2aLog.Log("CFS: hashing cached version");
previousHash = File.ReadAllText(baseVersionFilePath);
}
//copy to cache:
var fileHash = UpdateCacheFromRemote(ioc, cachedFilePath);
//notify supervisor what we did:
if (previousHash != fileHash)
{
Kp2aLog.Log("CFS: Updated Cache");
_cacheSupervisor.UpdatedCachedFileOnLoad(ioc);
}
else
{
Kp2aLog.Log("CFS: Files in Sync");
_cacheSupervisor.LoadedFromRemoteInSync(ioc);
}
//copy to cache:
var fileHash = UpdateCacheFromRemote(ioc, cachedFilePath);
//notify supervisor what we did:
if (previousHash != fileHash)
_cacheSupervisor.UpdatedCachedFileOnLoad(ioc);
else
_cacheSupervisor.LoadedFromRemoteInSync(ioc);
return File.OpenRead(cachedFilePath);
return File.OpenRead(cachedFilePath);
}

View File

@ -20,7 +20,7 @@
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;EXCLUDE_TWOFISH;EXCLUDE_KEYBOARD;EXCLUDE_FILECHOOSER;EXCLUDE_JAVAFILESTORAGE;EXCLUDE_KEYTRANSFORM</DefineConstants>
<DefineConstants>TRACE;DEBUG;EXCLUDE_TWOFISH;INCLUDE_KEYBOARD;INCLUDE_FILECHOOSER;INCLUDE_JAVAFILESTORAGE;INCLUDE_KEYTRANSFORM</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>

View File

@ -164,6 +164,11 @@ namespace keepass2android
#endif
public byte[] HashOfLastStream { get; private set; }
public bool CanWrite { get { return false; } }
public string SuccessMessage { get
{
return
".kdb-support is read-only. Export as .kdbx if you want to modify the database. This app is for use with Keepass 2.x!";
} }
}

View File

@ -28,5 +28,6 @@ namespace keepass2android
public byte[] HashOfLastStream { get; private set; }
public bool CanWrite { get { return true; } }
public string SuccessMessage { get { return null; } }
}
}

View File

@ -65,7 +65,8 @@ namespace keepass2android
db.KpDatabase.KeyEncryptionRounds = DefaultEncryptionRounds;
db.KpDatabase.Name = "Keepass2Android Password Database";
//re-set the name of the root group because the PwDatabase uses UrlUtil which is not appropriate for all file storages:
db.KpDatabase.RootGroup.Name = _app.GetFileStorage(_ioc).GetFilenameWithoutPathAndExt(_ioc);
// Set Database state
db.Root = db.KpDatabase.RootGroup;

View File

@ -115,7 +115,7 @@ namespace keepass2android
_app.LoadDatabase(_ioc, workingCopy, _compositeKey, StatusLogger, _loader);
SaveFileData(_ioc, _keyfileOrProvider);
Kp2aLog.Log("LoadDB OK");
Finish(true);
Finish(true, _loader.SuccessMessage);
}
catch (OldFormatException)
{

View File

@ -99,6 +99,8 @@ namespace Kp2aUnitTests
[TestMethod]
public void LoadFromRemoteWithDomain()
{
//warning, looks like credentials are no longer valid
var ioc = RemoteDomainIoc; //note: this property is defined in "TestLoadDbCredentials.cs" which is deliberately excluded from Git because the credentials are not public!
var app = new TestKp2aApp();
app.ServerCertificateErrorResponse = true; //accept invalid cert

View File

@ -3,7 +3,6 @@
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
<classpathentry kind="con" path="com.google.gdt.eclipse.managedapis.MANAGED_API_CONTAINER/drive-v2r102lv1.16.0-rc"/>
<classpathentry exported="true" kind="lib" path="C:/Users/Philipp/AppData/Local/Android/android-sdk/extras/google/google_play_services/libproject/google-play-services_lib/libs/google-play-services.jar"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>

View File

@ -11,8 +11,6 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import keepass2android.javafilestorage.JavaFileStorageBase.InvalidPathException;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;
@ -34,7 +32,7 @@ import android.app.Activity;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.text.TextUtils;
public class GoogleDriveFileStorage extends JavaFileStorageBase {
@ -56,10 +54,13 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase {
class AccountData
{
//guaranteed to be set if AccountData is in HashMap
Drive drive;
//may be null if first initialization failed
HashMap<String /*fileId*/, FileSystemEntryData> mFolderCache;
//may be null if first initialization failed
protected String mRootFolderId;
};
@ -126,7 +127,7 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase {
}
//make sure the path exists
private void verify() throws FileNotFoundException, UnsupportedEncodingException {
private void verify() throws IOException {
if (mAccountLocalPath.equals(""))
return;
@ -139,6 +140,9 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase {
throw new IllegalStateException("Looks like account "+mAccount+" was not properly initialized!");
}
//if initialization failed, try to repeat:
finishInitialization(accountData, mAccount);
String parentId = accountData.mRootFolderId;
for (int i=0;i<parts.length;i++)
@ -218,13 +222,15 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase {
}
public String getGDriveId() throws InvalidPathException, UnsupportedEncodingException {
public String getGDriveId() throws InvalidPathException, IOException {
String pathWithoutTrailingSlash = mAccountLocalPath;
if (pathWithoutTrailingSlash.endsWith("/"))
pathWithoutTrailingSlash = pathWithoutTrailingSlash.substring(0,pathWithoutTrailingSlash.length()-1);
if (pathWithoutTrailingSlash.equals(""))
{
return mAccountData.get(mAccount).mRootFolderId;
AccountData accountData = mAccountData.get(mAccount);
finishInitialization(accountData, mAccount);
return accountData.mRootFolderId;
}
String lastPart = pathWithoutTrailingSlash.substring(pathWithoutTrailingSlash.lastIndexOf(NAME_ID_SEP)+NAME_ID_SEP.length());
if (lastPart.contains("/"))
@ -265,6 +271,10 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase {
};
public GoogleDriveFileStorage()
{
logDebug("Creating GDrive FileStorage");
}
@Override
public boolean checkForFileChangeFast(String path,
@ -547,7 +557,7 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase {
}
catch (Exception e)
{
Log.d(TAG, "Exception in getFileEntry! "+e);
logDebug("Exception in getFileEntry! "+e);
throw convertException(e);
}
}
@ -570,6 +580,7 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase {
private Drive createDriveService(String accountName, Activity activity) {
logDebug("createDriveService "+accountName);
GoogleAccountCredential credential = createCredential(activity);
credential.setSelectedAccountName(accountName);
@ -601,7 +612,7 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase {
return;
}
}
Log.i(TAG, "Error selecting account");
logDebug("Error selecting account");
//Intent retData = new Intent();
//retData.putExtra(EXTRA_ERROR_MESSAGE, t.getMessage());
((Activity)setupAct).setResult(Activity.RESULT_CANCELED, data);
@ -615,15 +626,15 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase {
//}
String accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
if (accountName != null) {
Log.d(TAG, "Account name="+accountName);
logDebug("Account name="+accountName);
initializeAccountOrPath(setupAct, accountName);
}
else
{
Log.d(TAG, "Account name is null");
logDebug("Account name is null");
}
} else {
Log.i(TAG, "Error authenticating");
logDebug("Error authenticating");
//Intent retData = new Intent();
//retData.putExtra(EXTRA_ERROR_MESSAGE, t.getMessage());
((Activity)setupAct).setResult(Activity.RESULT_CANCELED, data);
@ -670,10 +681,11 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase {
newAccountData.drive = createDriveService(accountName, activity);
mAccountData.put(accountName, newAccountData);
logDebug("Added account data for " + accountName);
newAccountData.mFolderCache = buildFoldersCache(accountName);
About about = newAccountData.drive.about().get().execute();
newAccountData.mRootFolderId = about.getRootFolderId();
//try to finish the initialization. If this fails, we throw.
//in case of "Always return true" (inside CachingFileStorage) this means
//we have a partially uninitialized AccountData object.
//We'll try to initialize later in verify() if (e.g.) network is available again.
finishInitialization(newAccountData, accountName);
}
if (setupAct.getProcessName().equals(PROCESS_NAME_SELECTFILE))
@ -726,6 +738,19 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase {
}
private void finishInitialization(AccountData newAccountData, String accountName) throws IOException
{
if (newAccountData.mFolderCache == null)
{
newAccountData.mFolderCache = buildFoldersCache(accountName);
}
if (TextUtils.isEmpty(newAccountData.mRootFolderId))
{
About about = newAccountData.drive.about().get().execute();
newAccountData.mRootFolderId = about.getRootFolderId();
}
}
private HashMap<String,FileSystemEntryData> buildFoldersCache(String accountName) throws IOException {

View File

@ -1,11 +1,19 @@
package keepass2android.javafilestorage;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import org.apache.http.protocol.HTTP;
import android.app.Activity;
import android.content.Intent;
import android.text.format.DateFormat;
import android.util.Log;
public abstract class JavaFileStorageBase implements JavaFileStorage{
@ -16,9 +24,36 @@ public abstract class JavaFileStorageBase implements JavaFileStorage{
final static protected String NAME_ID_SEP = "-KP2A-";
final static protected String TAG = "KP2AJ";
protected void logDebug(String text)
protected synchronized void logDebug(String text)
{
Log.d(TAG, text);
File logFile = new File("/mnt/sdcard/keepass2android.cloud.log");
if (logFile.exists())
{
try
{
// Create an instance of SimpleDateFormat used for formatting
// the string representation of date (month/day/year)
SimpleDateFormat df = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss");
// Get the date today using Calendar object.
java.util.Date today = Calendar.getInstance().getTime();
// Using DateFormat format method we can create a string
// representation of a date with the defined format.
String reportDate = df.format(today);
//BufferedWriter for performance, true to set append to file flag
BufferedWriter buf = new BufferedWriter(new FileWriter(logFile, true));
buf.append(reportDate + " JFS: "+text);
buf.newLine();
buf.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
protected String getProtocolPrefix()
@ -61,7 +96,7 @@ public abstract class JavaFileStorageBase implements JavaFileStorage{
protected void finishWithError(final FileStorageSetupActivity setupAct, Exception error) {
Log.e("KP2AJ", "Exception: " + error.toString());
logDebug( "Exception: " + error.toString());
error.printStackTrace();
final Activity activity = (Activity)setupAct;
@ -72,7 +107,7 @@ public abstract class JavaFileStorageBase implements JavaFileStorage{
//This can make sense if there is a higher-level FileStorage which has the file cached.
if (activity.getIntent().getBooleanExtra(EXTRA_ALWAYS_RETURN_SUCCESS, false))
{
Log.d(TAG, "Returning success as desired in intent despite of exception.");
logDebug("Returning success as desired in intent despite of exception.");
finishActivityWithSuccess(setupAct);
return;
}
@ -108,7 +143,7 @@ public abstract class JavaFileStorageBase implements JavaFileStorage{
return;
}
Log.w("KP2AJ", "Unknown process: " + setupActivity.getProcessName());
logDebug("Unknown process: " + setupActivity.getProcessName());
}

View File

@ -49,7 +49,7 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
private HashMap<String /* id */, SkyDriveObject> mFolderCache = new HashMap<String, SkyDriveObject>();
public static final String[] SCOPES = { "wl.signin", "wl.skydrive_update", };
public static final String[] SCOPES = { "wl.signin", "wl.skydrive_update", "wl.offline_access"};
// see http://stackoverflow.com/questions/17997688/howto-to-parse-skydrive-api-date-in-java
SimpleDateFormat SKYDRIVE_DATEFORMATTER = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.ENGLISH);
@ -136,8 +136,7 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
public void setPathWithoutVerify(String path)
throws UnsupportedEncodingException, InvalidPathException {
mPath = path.substring(getProtocolPrefix().length());
// Log.d(TAG, " mAccount=" + mAccount);
// Log.d(TAG, " mAccountLocalPath=" + mAccountLocalPath);
logDebug( " mPath=" + mPath);
}
// make sure the path exists
@ -153,17 +152,17 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
for (int i = 0; i < parts.length; i++) {
String part = parts[i];
// Log.d(TAG, "parsing part " + part);
logDebug( "parsing part " + part);
int indexOfSeparator = part.lastIndexOf(NAME_ID_SEP);
if (indexOfSeparator < 0)
throw new FileNotFoundException("invalid path " + mPath);
String id = decode(part.substring(indexOfSeparator
+ NAME_ID_SEP.length()));
String name = decode(part.substring(0, indexOfSeparator));
// Log.d(TAG, " name=" + name);
logDebug( " name=" + name);
SkyDriveObject thisFolder = mFolderCache.get(id);
if (thisFolder == null) {
//Log.d(TAG, "adding to cache");
logDebug( "adding to cache");
thisFolder = tryAddToCache(id);
// check if it's still null
@ -199,7 +198,7 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
for (int i = 0; i < parts.length; i++) {
String part = parts[i];
// Log.d(TAG, "parsing part " + part);
logDebug("parsing part " + part);
int indexOfSeparator = part.lastIndexOf(NAME_ID_SEP);
if (indexOfSeparator < 0) {
// seems invalid, but we're very generous here
@ -284,6 +283,7 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
};
public SkyDriveFileStorage(String clientId, Context appContext) {
logDebug("Constructing SkyDriveFileStorage");
mAuthClient = new LiveAuthClient(appContext, clientId);
mAppContext = appContext;
mClientId = clientId;
@ -291,6 +291,7 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
}
void login(final FileStorageSetupActivity activity) {
logDebug("skydrive login");
mAuthClient.login((Activity) activity, Arrays.asList(SCOPES),
new LiveAuthListener() {
@Override
@ -315,7 +316,7 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
private void initialize(final FileStorageSetupActivity setupAct,
LiveConnectSession session) {
logDebug("skydrive initialize");
mConnectClient = new LiveConnectClient(session);
final Activity activity = (Activity)setupAct;
@ -359,6 +360,7 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
private void initializeFoldersCache() throws LiveOperationException,
SkyDriveException, FileNotFoundException {
logDebug("skydrive initializeFoldersCache");
//use alias for now (overwritten later):
mRootFolderId = "me/skydrive";
@ -375,7 +377,7 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
.optJSONObject(i));
if (skyDriveObj == null)
continue; // ignored type
//Log.d(TAG, "adding "+skyDriveObj.getName()+" to cache with id " + skyDriveObj.getId()+" in "+skyDriveObj.getParentId());
logDebug( "adding "+skyDriveObj.getName()+" to cache with id " + skyDriveObj.getId()+" in "+skyDriveObj.getParentId());
mFolderCache.put(skyDriveObj.getId(), skyDriveObj);
mRootFolderId = skyDriveObj.getParentId();
@ -397,7 +399,7 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
JSONObject error = result.optJSONObject(JsonKeys.ERROR);
String message = error.optString(JsonKeys.MESSAGE);
String code = error.optString(JsonKeys.CODE);
//Log.d(TAG, "Code: "+code);
logDebug( "Code: "+code);
if ("resource_not_found".equals(code))
throw new FileNotFoundException(message);
else
@ -503,6 +505,7 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
}
catch (Exception e)
{
logDebug("Error getting file version.");
Log.w(TAG,"Error getting file version:");
e.printStackTrace();
return null;
@ -514,7 +517,9 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
public InputStream openFileForRead(String path) throws Exception {
try
{
logDebug("openFileForRead: " + path);
LiveDownloadOperation op = mConnectClient.download(new SkyDrivePath(path).getSkyDriveId()+"/content");
logDebug("openFileForRead ok" + path);
return op.getStream();
}
catch (Exception e)
@ -529,6 +534,7 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
try
{
logDebug("uploadFile to "+path);
SkyDrivePath driveTargetPath = new SkyDrivePath(path);
SkyDrivePath driveUploadPath = driveTargetPath;
SkyDrivePath driveTempPath = null;
@ -600,7 +606,7 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
private Exception convertException(Exception e) throws Exception {
e.printStackTrace();
logDebug(e.toString());
Log.w(TAG, e);
throw e;
@ -640,7 +646,7 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
.optJSONObject(i));
if (skyDriveObj == null)
continue; // ignored type
//Log.d(TAG, "listing "+skyDriveObj.getName()+" with id " + skyDriveObj.getId()+" in "+skyDriveObj.getParentId());
logDebug( "listing "+skyDriveObj.getName()+" with id " + skyDriveObj.getId()+" in "+skyDriveObj.getParentId());
resultList.add(convertToFileEntry(parentDrivePath, skyDriveObj));
}
@ -667,13 +673,14 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
catch (Exception e)
{
Log.w(TAG, "Cannot parse time " + skyDriveObj.getUpdatedTime());
logDebug("Cannot parse time! " + e.toString());
res.lastModifiedTime = -1;
}
if (parentPath == null) //this is the case if we're listing the parent path itself
res.path = getProtocolPrefix();
else
res.path = new SkyDrivePath(parentPath.getFullPath(), skyDriveObj.toJson()).getFullPath();
//Log.d(TAG, "path: "+res.path);
logDebug( "path: "+res.path);
if (SkyDriveFile.class.isAssignableFrom(skyDriveObj.getClass()))
{
res.sizeInBytes = ((SkyDriveFile)skyDriveObj).getSize();
@ -687,8 +694,8 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
try
{
SkyDrivePath drivePath = new SkyDrivePath(filename);
//Log.d(TAG, "getFileEntry for "+ filename +" = "+drivePath.getFullPath());
//Log.d(TAG, " parent is "+drivePath.getParentPath());
logDebug( "getFileEntry for "+ filename +" = "+drivePath.getFullPath());
logDebug( " parent is "+drivePath.getParentPath());
return convertToFileEntry(drivePath.getParentPath(),getSkyDriveObject(drivePath));
}
catch (Exception e)
@ -730,6 +737,7 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
public void onStart(final FileStorageSetupActivity activity) {
try
{
logDebug("skydrive onStart");
initialize(activity);
}
catch (Exception e)
@ -751,15 +759,16 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
LiveConnectSession session, Object userState) {
if (status == LiveStatus.CONNECTED) {
logDebug("connected!");
initialize(activity, session);
} else {
if (status == LiveStatus.NOT_CONNECTED)
Log.d(TAG, "not connected");
logDebug( "not connected");
else if (status == LiveStatus.UNKNOWN)
Log.d(TAG, "unknown");
logDebug( "unknown");
else
Log.d(TAG, "unexpected status " + status);
logDebug( "unexpected status " + status);
try
{
login(activity);
@ -768,6 +777,7 @@ public class SkyDriveFileStorage extends JavaFileStorageBase {
{
//this may happen if an un-cancelled login progress is already in progress.
//however, the activity might have been destroyed, so try again with another auth client next time
logDebug("IllegalStateException: Recreating AuthClient");
mAuthClient = new LiveAuthClient(mAppContext, mClientId);
finishWithError(activity, e);
}

View File

@ -19,17 +19,13 @@
-->
<resources>
<!-- key_height + key_bottom_gap = popup_key_height -->
<dimen name="key_height">0.250in</dimen>
<dimen name="key_bottom_gap">0.020in</dimen>
<dimen name="popup_key_height">0.270in</dimen>
<dimen name="keyboard_bottom_padding">0.0in</dimen>
<dimen name="candidate_strip_height">38dip</dimen>
<dimen name="candidate_strip_fading_edge_length">63dip</dimen>
<dimen name="spacebar_vertical_correction">2dip</dimen>
<!-- Amount of allowance for selecting keys in a mini popup keyboard by sliding finger. -->
<!-- popup_key_height x 1.7 -->
<dimen name="mini_keyboard_slide_allowance">0.459in</dimen>
<!-- popup_key_height x 1.0 -->
<dimen name="mini_keyboard_vertical_correction">-0.270in</dimen>
<dimen name="key_height">42.329987dip</dimen>
<dimen name="key_bottom_gap">2.0dip</dimen>
<dimen name="popup_key_height">43.19998dip</dimen>
<dimen name="keyboard_bottom_padding">0.0dip</dimen>
<dimen name="candidate_strip_height">38.0dip</dimen>
<dimen name="candidate_strip_fading_edge_length">63.0dip</dimen>
<dimen name="spacebar_vertical_correction">2.0dip</dimen>
<dimen name="mini_keyboard_slide_allowance">73.44dip</dimen>
<dimen name="mini_keyboard_vertical_correction">-43.19998dip</dimen>
</resources>

View File

@ -19,12 +19,12 @@
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="alternates_for_a">àáâãäåæ</string>
<string name="alternates_for_e">èéêë</string>
<string name="alternates_for_i">ìíîï</string>
<string name="alternates_for_o">òóôõöœø</string>
<string name="alternates_for_u">ùúûü</string>
<string name="alternates_for_e">3èéêë</string>
<string name="alternates_for_i">8ìíîï</string>
<string name="alternates_for_o">9òóôõöœø</string>
<string name="alternates_for_u">7ùúûü</string>
<string name="alternates_for_s">§ß</string>
<string name="alternates_for_n">ñ</string>
<string name="alternates_for_c">ç</string>
<string name="alternates_for_y">ýÿ</string>
<string name="alternates_for_y">6ýÿ</string>
</resources>

View File

@ -19,12 +19,12 @@
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="alternates_for_a">àáâãäåæ</string>
<string name="alternates_for_e">èéêë</string>
<string name="alternates_for_i">ìíîï</string>
<string name="alternates_for_o">òóôõöœø</string>
<string name="alternates_for_u">ùúûü</string>
<string name="alternates_for_e">3èéêë</string>
<string name="alternates_for_i">8ìíîï</string>
<string name="alternates_for_o">9òóôõöœø</string>
<string name="alternates_for_u">7ùúûü</string>
<string name="alternates_for_s">§ß</string>
<string name="alternates_for_n">ñ</string>
<string name="alternates_for_c">ç</string>
<string name="alternates_for_y">ýÿ</string>
<string name="alternates_for_y">6ýÿ</string>
</resources>

View File

@ -19,32 +19,23 @@
-->
<resources>
<!-- key_height + key_bottom_gap = popup_key_height -->
<dimen name="key_height">0.290in</dimen>
<dimen name="key_bottom_gap">0.035in</dimen>
<dimen name="popup_key_height">0.325in</dimen>
<dimen name="keyboard_bottom_padding">0.06in</dimen>
<dimen name="bubble_pointer_offset">22dip</dimen>
<dimen name="candidate_strip_height">42dip</dimen>
<dimen name="candidate_strip_fading_edge_length">63dip</dimen>
<dimen name="spacebar_vertical_correction">4dip</dimen>
<!-- If the screen height in landscape is larger than the below value, then the keyboard
will not go into extract (fullscreen) mode. -->
<dimen name="max_height_for_fullscreen">2.5in</dimen>
<dimen name="key_text_size">0.13in</dimen>
<dimen name="key_label_text_size">0.083in</dimen>
<dimen name="key_preview_text_size_large">40sp</dimen>
<dimen name="key_preview_offset">0.000in</dimen>
<!-- key_preview_text_size_large x 2 -->
<dimen name="key_preview_height">80sp</dimen>
<!-- Amount of allowance for selecting keys in a mini popup keyboard by sliding finger. -->
<!-- popup_key_height x 1.7 -->
<dimen name="mini_keyboard_slide_allowance">0.553in</dimen>
<!-- popup_key_height x 1.0 -->
<dimen name="mini_keyboard_vertical_correction">-0.325in</dimen>
<dimen name="key_hysteresis_distance">0.05in</dimen>
<!-- We use "inch", not "dip" because this value tries dealing with physical distance related
to user's finger. -->
<dimen name="keyboard_vertical_correction">-0.05in</dimen>
<dimen name="candidate_min_touchable_width">0.3in</dimen>
<dimen name="key_height">49.109985dip</dimen>
<dimen name="key_bottom_gap">5.0dip</dimen>
<dimen name="popup_key_height">52.0dip</dimen>
<dimen name="keyboard_bottom_padding">9.599976dip</dimen>
<dimen name="bubble_pointer_offset">22.0dip</dimen>
<dimen name="candidate_strip_height">42.0dip</dimen>
<dimen name="candidate_strip_fading_edge_length">63.0dip</dimen>
<dimen name="spacebar_vertical_correction">4.0dip</dimen>
<dimen name="max_height_for_fullscreen">423.32812dip</dimen>
<dimen name="key_text_size">22.00998sp</dimen>
<dimen name="key_label_text_size">14.049988sp</dimen>
<dimen name="key_preview_text_size_large">40.0sp</dimen>
<dimen name="key_preview_offset">0.0dip</dimen>
<dimen name="key_preview_height">80.0sp</dimen>
<dimen name="mini_keyboard_slide_allowance">88.47998dip</dimen>
<dimen name="mini_keyboard_vertical_correction">-52.0dip</dimen>
<dimen name="key_hysteresis_distance">8.0dip</dimen>
<dimen name="keyboard_vertical_correction">-8.0dip</dimen>
<dimen name="candidate_min_touchable_width">48.0dip</dimen>
</resources>

View File

@ -9,7 +9,7 @@ namespace keepass2android
/// <summary>
/// Makes attachments of PwEntries accessible when they are stored in the app cache
/// </summary>
[ContentProvider(new[]{"keepass2android."+AppNames.PackagePart+".provider"})]
[ContentProvider(new[]{"keepass2android."+AppNames.PackagePart+".provider"},Exported = true)]
public class AttachmentContentProvider : ContentProvider {
public const string AttachmentCacheSubDir = "AttachmentCache";

View File

@ -22,6 +22,7 @@ namespace keepass2android
AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
builder.SetTitle(ctx.GetString(Resource.String.ChangeLog_title));
String[] changeLog = {
ctx.GetString(Resource.String.ChangeLog_0_9_3_r5),
ctx.GetString(Resource.String.ChangeLog_0_9_3),
ctx.GetString(Resource.String.ChangeLog_0_9_2),
ctx.GetString(Resource.String.ChangeLog_0_9_1),

View File

@ -6,6 +6,7 @@ using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Preferences;
using Android.Runtime;
using Android.Views;
using Android.Widget;
@ -16,14 +17,76 @@ namespace keepass2android
[Activity(Label = AppNames.AppName, Theme = "@style/Base")]
public class DonateReminder : Activity
{
class Reminder
{
public DateTime From, To;
public int ResourceToShow;
public string Key;
}
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.donate);
foreach (Reminder r in GetReminders())
{
if ((DateTime.Now > r.From)
&& (DateTime.Now < r.To))
{
SetContentView(r.ResourceToShow);
}
}
FindViewById(Resource.Id.ok_donate).Click += (sender, args) => { Util.GotoDonateUrl(this);Finish(); };
FindViewById(Resource.Id.no_donate).Click += (sender, args) => { Finish(); };
}
static IEnumerable<Reminder> GetReminders()
{
yield return new Reminder
{
From = new DateTime(2014, 09, 20),
To = new DateTime(2014, 10, 06),
Key = "DonationOktoberfest2014"
,ResourceToShow = Resource.Layout.donate
};
int thisYear = DateTime.Now.Year;
yield return new Reminder
{
From = new DateTime(thisYear, 05, 10),
To = new DateTime(thisYear, 05, 11),
Key = "DonationBirthday" + thisYear,
ResourceToShow = Resource.Layout.donate_bday
};
yield return new Reminder
{
From = new DateTime(thisYear, 05, 11),
To = new DateTime(thisYear, 05, 16),
Key = "DonationBirthday" + thisYear,
ResourceToShow = Resource.Layout.donate_bdaymissed
};
}
public static void ShowDonateReminderIfAppropriate(Activity context)
{
foreach (Reminder r in GetReminders())
{
if ((DateTime.Now >= r.From )
&& (DateTime.Now < r.To))
{
ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(context);
if (prefs.GetBoolean(r.Key, false) == false)
{
ISharedPreferencesEditor edit = prefs.Edit();
edit.PutBoolean(r.Key, true);
EditorCompat.Apply(edit);
context.StartActivity(new Intent(context, typeof(DonateReminder)));
}
}
}
}
}
}

View File

@ -242,13 +242,15 @@ namespace keepass2android
};
// Respect mask password setting
if (State.ShowPassword) {
EditText pass = (EditText) FindViewById(Resource.Id.entry_password);
EditText conf = (EditText) FindViewById(Resource.Id.entry_confpassword);
pass.InputType = InputTypes.ClassText | InputTypes.TextVariationVisiblePassword;
conf.InputType = InputTypes.ClassText | InputTypes.TextVariationVisiblePassword;
}
MakePasswordVisibleOrHidden();
ImageButton btnTogglePassword = (ImageButton)FindViewById(Resource.Id.toggle_password);
btnTogglePassword.Click += (sender, e) =>
{
State.ShowPassword = !State.ShowPassword;
MakePasswordVisibleOrHidden();
};
Button addButton = (Button) FindViewById(Resource.Id.add_advanced);
addButton.Visibility = ViewStates.Visible;
@ -283,6 +285,22 @@ namespace keepass2android
}
private void MakePasswordVisibleOrHidden()
{
TextView password = (TextView) FindViewById(Resource.Id.entry_password);
TextView confpassword = (TextView) FindViewById(Resource.Id.entry_confpassword);
if (State.ShowPassword)
{
password.InputType = InputTypes.ClassText | InputTypes.TextVariationVisiblePassword;
confpassword.Visibility = ViewStates.Gone;
}
else
{
password.InputType = InputTypes.ClassText | InputTypes.TextVariationPassword;
confpassword.Visibility = ViewStates.Visible;
}
}
void SaveEntry()
{
Database db = App.Kp2a.GetDb();
@ -685,13 +703,6 @@ namespace keepass2android
inflater.Inflate(Resource.Menu.entry_edit, menu);
IMenuItem togglePassword = menu.FindItem(Resource.Id.menu_toggle_pass);
if ( State.ShowPassword ) {
togglePassword.SetTitle(Resource.String.menu_hide_password);
} else {
togglePassword.SetTitle(Resource.String.show_password);
}
return true;
}
@ -705,16 +716,6 @@ namespace keepass2android
return false;
}
return true;
case Resource.Id.menu_toggle_pass:
if ( State.ShowPassword ) {
item.SetTitle(Resource.String.show_password);
State.ShowPassword = false;
} else {
item.SetTitle(Resource.String.menu_hide_password);
State.ShowPassword = true;
}
SetPasswordStyle();
return true;
case Resource.Id.menu_cancel_edit:
Finish();
@ -748,19 +749,6 @@ namespace keepass2android
return base.OnOptionsItemSelected(item);
}
private void SetPasswordStyle() {
TextView password = (TextView) FindViewById(Resource.Id.entry_password);
TextView confpassword = (TextView) FindViewById(Resource.Id.entry_confpassword);
if ( State.ShowPassword ) {
password.InputType = InputTypes.ClassText | InputTypes.TextVariationVisiblePassword;
confpassword.InputType = InputTypes.ClassText | InputTypes.TextVariationVisiblePassword;
} else {
password.InputType = InputTypes.ClassText | InputTypes.TextVariationPassword;
confpassword.InputType = InputTypes.ClassText | InputTypes.TextVariationPassword;
}
}
void UpdateExpires()
{
@ -862,7 +850,6 @@ namespace keepass2android
String password = State.Entry.Strings.ReadSafe(PwDefs.PasswordField);
PopulateText(Resource.Id.entry_password, password);
PopulateText(Resource.Id.entry_confpassword, password);
SetPasswordStyle();
PopulateText(Resource.Id.entry_comment, State.Entry.Strings.ReadSafe (PwDefs.NotesField));
@ -913,13 +900,18 @@ namespace keepass2android
return false;
}
// Validate password
String pass = Util.GetEditText(this, Resource.Id.entry_password);
String conf = Util.GetEditText(this, Resource.Id.entry_confpassword);
if ( ! pass.Equals(conf) ) {
Toast.MakeText(this, Resource.String.error_pass_match, ToastLength.Long).Show();
return false;
if (!State.ShowPassword)
{
// Validate password
String pass = Util.GetEditText(this, Resource.Id.entry_password);
String conf = Util.GetEditText(this, Resource.Id.entry_confpassword);
if (!pass.Equals(conf))
{
Toast.MakeText(this, Resource.String.error_pass_match, ToastLength.Long).Show();
return false;
}
}
// Validate expiry date
DateTime newExpiry = new DateTime();

View File

@ -102,6 +102,12 @@ namespace keepass2android
Finish();
}
if (resultCode == KeePass.ExitReloadDb)
{
AppTask.SetActivityResult(this, KeePass.ExitReloadDb);
Finish();
}
}
private ISharedPreferences _prefs;
@ -414,6 +420,10 @@ namespace keepass2android
if (!String.IsNullOrEmpty(message))
Toast.MakeText(this, message, ToastLength.Long).Show();
// Tell the adapter to refresh it's list
BaseAdapter adapter = (BaseAdapter)ListAdapter;
adapter.NotifyDataSetChanged();
if (App.Kp2a.GetDb().OtpAuxFileIoc != null)
{
var task2 = new SyncOtpAuxFile(App.Kp2a.GetDb().OtpAuxFileIoc);

View File

@ -73,21 +73,32 @@ namespace keepass2android
base.OnStart();
Kp2aLog.Log("KeePass.OnStart");
if (GetCurrentRuntimeValue().StartsWith("ART"))
ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(this);
/*if (GetCurrentRuntimeValue().StartsWith("ART"))
{
new AlertDialog.Builder(this)
if (!prefs.GetBoolean("ART_WARNING", false))
{
ISharedPreferencesEditor edit = prefs.Edit();
edit.PutBoolean("ART_WARNING", true);
EditorCompat.Apply(edit);
new AlertDialog.Builder(this)
.SetTitle("Warning")
.SetMessage(
//"It looks like you are running ART (Android Runtime). Please note: At the time of this app's release, Google says ART is experimental. And indeed, the early releases of ART (e.g. in Android 4.4, 4.4.1 and 4.4.2) contain a bug which causes crashes in Mono for Android apps including Keepass2Android. This bug was fixed after the 4.4.2 release so if you have a later Android release, you might be able to use this app. If not, please switch to Dalvik. Please do not downrate Keepass2Android for this problem, it's not our bug :-). Thanks! See our website (keepass2android.codeplex.com) for more information on this issue.")
"It looks like you are running ART (Android Runtime). Please note: At the time of this app's release, Google says ART is experimental. And indeed, the early releases of ART (e.g. in Android 4.4, 4.4.1 and 4.4.2) contain a bug which causes crashes in Mono for Android apps including Keepass2Android. We have incorporated a workaround which allows to use the basic features, but you will probably experience crashes at some time. Switch to Dalvik for a stable version. Please do not downrate Keepass2Android for this problem, it's not our bug :-). Thanks! See our website (keepass2android.codeplex.com) for more information on this issue.")
"It looks like you are running ART (Android Runtime). Please note: At the time of this app's release, this app does not run completely stable with ART. I am waiting for more fixes regarding ART from the makers of Mono for Android. As ART is still not yet meant for every-day use, please do not down rate KP2A for this. Thanks.")
.SetPositiveButton("OK", (sender, args) => LaunchNextActivity())
.Create()
.Show();
return;
}
ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(this);
return;
}
}*/
bool showChangeLog = false;
try
{

View File

@ -134,6 +134,7 @@ namespace keepass2android
private ActivityDesign _design;
private bool _performingLoad;
public PasswordActivity (IntPtr javaReference, JniHandleOwnership transfer)
: base(javaReference, transfer)
@ -767,6 +768,7 @@ namespace keepass2android
private void PerformLoadDatabase()
{
//no need to check for validity of password because if this method is called, the Ok button was enabled (i.e. there was a valid password)
CompositeKey compositeKey = new CompositeKey();
compositeKey.AddUserKey(new KcpPassword(_password));
@ -849,7 +851,7 @@ namespace keepass2android
Handler handler = new Handler();
OnFinish onFinish = new AfterLoad(handler, this);
_performingLoad = true;
LoadDb task = (KeyProviderType == KeyProviders.Otp) ?
new SaveOtpAuxFileAndLoadDb(App.Kp2a, _ioConnection, _loadDbTask, compositeKey, _keyFileOrProvider, onFinish, this)
:
@ -924,20 +926,9 @@ namespace keepass2android
long usageCount = prefs.GetLong(GetString(Resource.String.UsageCount_key), 0);
if ((DateTime.Now > new DateTime(2013, 09, 21))
&& (DateTime.Now < new DateTime(2013, 10, 07))
&& (usageCount > 5)
)
if (usageCount > 5)
{
const string donationOkt2013Key = "HasAskedForDonationOktoberfest2013";
if (prefs.GetBoolean(donationOkt2013Key, false) == false)
{
ISharedPreferencesEditor edit = prefs.Edit();
edit.PutBoolean(donationOkt2013Key, true);
EditorCompat.Apply(edit);
StartActivity(new Intent(this, typeof(DonateReminder)));
}
DonateReminder.ShowDonateReminderIfAppropriate(this);
}
}
@ -1085,7 +1076,9 @@ namespace keepass2android
// OnResume is run every time the activity comes to the foreground. This code should only run when the activity is started (OnStart), but must
// be run in OnResume rather than OnStart so that it always occurrs after OnActivityResult (when re-creating a killed activity, OnStart occurs before OnActivityResult)
if (_starting && !IsFinishing) //use !IsFinishing to make sure we're not starting another activity when we're already finishing (e.g. due to TaskComplete in OnActivityResult)
//use !IsFinishing to make sure we're not starting another activity when we're already finishing (e.g. due to TaskComplete in OnActivityResult)
//use !performingLoad to make sure we're not already loading the database (after ActivityResult from File-Prepare-Activity; this would cause _loadDbTask to exist when we reload later!)
if (_starting && !IsFinishing && !_performingLoad)
{
_starting = false;
if (App.Kp2a.DatabaseIsUnlocked)
@ -1227,10 +1220,10 @@ namespace keepass2android
GC.Collect(); // Ensure temporary memory used while loading is collected
}
else
{
DisplayMessage(_act);
}
DisplayMessage(_act);
_act._performingLoad = false;
}
}

View File

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="39" android:versionName="0.9.3-release-3" package="keepass2android.keepass2android_debug" android:installLocation="auto">
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" />
<permission android:description="@string/permission_desc" android:icon="@drawable/ic_launcher" android:label="KP2A internal file browsing" android:name="keepass2android.keepass2android.permission.KP2aInternalFileBrowsing" android:protectionLevel="signature" />
<application android:label="keepass2android" android:icon="@drawable/ic_launcher">
<activity android:name="com.dropbox.client2.android.AuthActivity" android:launchMode="singleTask" android:configChanges="orientation|keyboard">
<intent-filter>
<data android:scheme="db-i8shu7v1hgh7ynt" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<data android:scheme="db-ax0268uydp1ya57" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<provider android:name="group.pals.android.lib.ui.filechooser.providers.localfile.LocalFileProvider" android:authorities="keepass2android.keepass2android_debug.android-filechooser.localfile" android:exported="false" />
<provider android:name="group.pals.android.lib.ui.filechooser.providers.history.HistoryProvider" android:authorities="keepass2android.keepass2android_debug.android-filechooser.history" android:exported="false" />
<activity android:name="group.pals.android.lib.ui.filechooser.FileChooserActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenSize" android:screenOrientation="user" android:theme="@style/Afc.Theme.Light">
<intent-filter>
<action android:name="android.intent.action.GET_CONTENT" />
<data android:mimeType="*/*" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.OPENABLE" />
</intent-filter>
</activity>
<!--<service android:name="keepass2android.softkeyboard.KP2AKeyboard" android:permission="android.permission.BIND_INPUT_METHOD">
<intent-filter>
<action android:name="android.view.InputMethod" />
</intent-filter>
<meta-data android:name="android.view.im" android:resource="@xml/method" />
</service>
<activity android:name="keepass2android.softkeyboard.LatinIMESettings" android:label="@string/english_ime_settings">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
<intent-filter>
<action android:name="keepass2android.softkeyboard.LatinIMESettings" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name="keepass2android.softkeyboard.InputLanguageSelection"
android:label="@string/language_selection_title">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<action android:name="keepass2android.softkeyboard.INPUT_LANGUAGE_SELECTION"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
-->
<activity android:configChanges="keyboardHidden|orientation" android:label="@string/app_name" android:theme="@style/Base" android:name="keepass2android.PasswordActivity">
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="file" />
<data android:mimeType="*/*" />
<data android:host="*" />
<data android:pathPattern=".*\\.kdbp" />
<data android:pathPattern=".*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\.kdbx" />
<data android:pathPattern=".*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="keepass2android.keepass2android.permission.KP2aInternalFileBrowsing" />
</manifest>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="39" android:versionName="0.9.3-release-3" package="keepass2android.keepass2android" android:installLocation="auto">
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="41" android:versionName="0.9.3-r5" package="keepass2android.keepass2android" android:installLocation="auto">
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" />
<permission android:description="@string/permission_desc" android:icon="@drawable/ic_launcher" android:label="KP2A internal file browsing" android:name="keepass2android.keepass2android.permission.KP2aInternalFileBrowsing" android:protectionLevel="signature" />
<application android:label="keepass2android" android:icon="@drawable/ic_launcher">

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="31"
android:versionName="0.9.2"
android:versionCode="39"
android:versionName="0.9.3"
package="keepass2android.keepass2android_nonet"
android:installLocation="auto">
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="14" />
@ -16,6 +16,29 @@
<category android:name="android.intent.category.OPENABLE" />
</intent-filter>
</activity>
<service android:name="keepass2android.softkeyboard.KP2AKeyboard" android:permission="android.permission.BIND_INPUT_METHOD">
<intent-filter>
<action android:name="android.view.InputMethod" />
</intent-filter>
<meta-data android:name="android.view.im" android:resource="@xml/method" />
</service>
<activity android:name="keepass2android.softkeyboard.LatinIMESettings" android:label="@string/english_ime_settings">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
<intent-filter>
<action android:name="keepass2android.softkeyboard.LatinIMESettings" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name="keepass2android.softkeyboard.InputLanguageSelection"
android:label="@string/language_selection_title">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<action android:name="keepass2android.softkeyboard.INPUT_LANGUAGE_SELECTION"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:configChanges="keyboardHidden|orientation" android:label="@string/app_name_nonet" android:theme="@style/Base" android:name="keepass2android.PasswordActivity" >
<intent-filter android:label="@string/app_name">
@ -47,7 +70,7 @@
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

View File

@ -57,49 +57,57 @@
android:layout_height="wrap_content"
android:layout_below="@id/entry_url"
android:text="@string/entry_password" />
<Button
android:id="@+id/generate_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_below="@id/entry_password_label"
android:text="@string/ellipsis" />
<EditText
android:id="@+id/entry_password"
style="@style/TextAppearance_EditEntry_Value"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignTop="@id/generate_button"
android:layout_toLeftOf="@id/generate_button"
android:hint="@string/hint_pass"
android:inputType="textPassword"
android:singleLine="true"
android:typeface="monospace" />
<!-- Confirm Password -->
<TextView
android:id="@+id/entry_confpassword_label"
style="@style/TextAppearance_EditEntry_LabelSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/entry_password"
android:text="@string/entry_confpassword" />
<EditText
android:id="@+id/entry_confpassword"
style="@style/TextAppearance_EditEntry_Value"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/entry_confpassword_label"
android:hint="@string/hint_conf_pass"
android:inputType="textPassword"
android:singleLine="true"
android:typeface="monospace" />
<RelativeLayout
android:id="@+id/password_section"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/entry_password_label">
<Button
android:id="@+id/generate_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="@string/ellipsis" />
<ImageButton
android:id="@+id/toggle_password"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_menu_view"
android:layout_alignTop="@id/generate_button"
android:layout_toLeftOf="@id/generate_button"
/>
<EditText
android:id="@+id/entry_password"
style="@style/TextAppearance_EditEntry_Value"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignTop="@id/generate_button"
android:layout_toLeftOf="@id/toggle_password"
android:hint="@string/hint_pass"
android:inputType="textPassword"
android:singleLine="true"
android:typeface="monospace" />
<!-- Confirm Password -->
<EditText
android:id="@+id/entry_confpassword"
style="@style/TextAppearance_EditEntry_Value"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/entry_password"
android:hint="@string/hint_conf_pass"
android:inputType="textPassword"
android:singleLine="true"
android:typeface="monospace" />
</RelativeLayout>
<!-- Comment -->
<TextView
android:id="@+id/entry_comment_label"
style="@style/TextAppearance_EditEntry_LabelSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/entry_confpassword"
android:layout_below="@id/password_section"
android:text="@string/entry_comment" />
<EditText
android:id="@+id/entry_comment"

View File

@ -0,0 +1,45 @@
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
>
<TextView
android:id="@+id/donate_question"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="@string/donate_bday_question" />
<ImageView
android:id="@+id/imgoktfest"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/donate_question"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:src="@drawable/donate_cake" />
<Button
android:text="@string/ok_donate"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/imgoktfest"
android:id="@+id/ok_donate"
/>
<Button
android:text="@string/no_thanks"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/ok_donate"
android:id="@+id/no_donate"
/>
</RelativeLayout>
</ScrollView>

View File

@ -0,0 +1,45 @@
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
>
<TextView
android:id="@+id/donate_question"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="@string/donate_missedbday_question" />
<ImageView
android:id="@+id/imgoktfest"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/donate_question"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:src="@drawable/donate_cake" />
<Button
android:text="@string/ok_donate"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/imgoktfest"
android:id="@+id/ok_donate"
/>
<Button
android:text="@string/no_thanks"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/ok_donate"
android:id="@+id/no_donate"
/>
</RelativeLayout>
</ScrollView>

View File

@ -95,45 +95,56 @@
android:layout_below="@id/entry_url"
style="@style/EntryFieldHeader"
android:text="@string/entry_password" />
<Button
android:id="@+id/generate_button"
android:layout_below="@id/entry_password_label"
android:layout_width="wrap_content"
android:text="@string/ellipsis"
android:layout_height="wrap_content"
android:layout_alignParentRight="true" />
<EditText
android:id="@+id/entry_password"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"
android:typeface="monospace"
android:singleLine="true"
android:layout_toLeftOf="@id/generate_button"
android:hint="@string/hint_pass"
android:layout_alignTop="@id/generate_button" />
<!-- Confirm Password -->
<TextView
android:id="@+id/entry_confpassword_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/entry_password"
android:text="@string/entry_confpassword" />
<EditText
android:id="@+id/entry_confpassword"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"
android:typeface="monospace"
android:singleLine="true"
android:layout_below="@id/entry_confpassword_label"
android:hint="@string/hint_conf_pass" />
<RelativeLayout
android:id="@+id/password_section"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/entry_password_label">
<Button
android:id="@+id/generate_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="@string/ellipsis" />
<ImageButton
android:id="@+id/toggle_password"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_menu_view"
android:layout_alignTop="@id/generate_button"
android:layout_toLeftOf="@id/generate_button"
/>
<EditText
android:id="@+id/entry_password"
style="@style/TextAppearance_EditEntry_Value"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignTop="@id/generate_button"
android:layout_toLeftOf="@id/toggle_password"
android:hint="@string/hint_pass"
android:inputType="textPassword"
android:singleLine="true"
android:typeface="monospace" />
<!-- Confirm Password -->
<EditText
android:id="@+id/entry_confpassword"
style="@style/TextAppearance_EditEntry_Value"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/entry_password"
android:hint="@string/hint_conf_pass"
android:inputType="textPassword"
android:singleLine="true"
android:typeface="monospace" />
</RelativeLayout>
<!-- Comment -->
<TextView
android:id="@+id/entry_comment_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/entry_confpassword"
android:layout_below="@id/password_section"
style="@style/EntryFieldHeader"
android:text="@string/entry_comment" />
<EditText

View File

@ -16,11 +16,6 @@
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/menu_toggle_pass"
android:title="@string/show_password"
android:icon="@android:drawable/ic_menu_view"
android:showAsAction="ifRoom"
/>
<item android:id="@+id/menu_donate"
android:title="@string/menu_donate"
android:showAsAction="ifRoom"

View File

@ -17,10 +17,6 @@
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/menu_toggle_pass"
android:icon="@android:drawable/ic_menu_view"
android:title="@string/show_password"
/>
<item android:id="@+id/menu_cancel_edit"
android:title="@string/entry_cancel"
/>

View File

@ -339,6 +339,8 @@
<string name="CannotMoveGroupHere">Cannot move group to this group.</string>
<string name="donate_question">Today, it\'s Oktoberfest! If you like Keepass2Android: wouldn\'t today be a good day to buy me a beer?</string>
<string name="donate_bday_question">May 10th? It\'s my birthday! If you like this app, why not send me some birthday greetings along with a little birthday gift? This would really make me happy! :-)</string>
<string name="donate_missedbday_question">Oh, you missed my birthday on May 10th! If you like this app, why not send me some birthday greetings and a little birthday gift? It is not yet too late to make me happy! :-)</string>
<string name="ok_donate">Tell me more!</string>
<string name="no_thanks">No, I don\'t like it that much</string>
@ -412,6 +414,16 @@
<string name="ErrorUpdatingChalAuxFile">Error updating OTP auxiliary file!</string>
<string name="loading">Loading…</string>
<string name="enable_plugin_title">Enable plug-in?</string>
<string name="enable_plugin_question">Keepass2Android detected a plug-in with name: %1$s from package name: %2$s. Do you want to enable this plug-in? It will have access to the data stored in your Keepass databases.</string>
<string name="plugins">Plug-ins</string>
<string name="plugin_packagename">Package name:</string>
<string name="plugin_description">Description (not verified):</string>
<string name="plugin_author">Author (not verified):</string>
<string name="plugin_enabled">Enabled</string>
<string name="plugins_text">Click plug-in to enable/disable</string>
<string name="get_regular_version">Get more storage types</string>
@ -421,6 +433,12 @@
<string name="export_fileformats_title">Select file format</string>
<string name="ChangeLog_title">Change log</string>
<string name="ChangeLog_0_9_3_r5">
<b>Version 0.9.3 r5</b>\n
* Incorporated fixes from Xamarin: Keepass2Android now compatible with ART on Android 4.4.2. Finally!\n
* Bug fixes: bugs in synchronization (refresh display, correct check for changes on http), bugs on Android 2.x devices, bugs in Google Drive and SkyDrive storage implementations, clear clipboard on close database, bug opening attachments, display problems with keyboard\n
</string>
<string name="ChangeLog_0_9_3">
<b>Version 0.9.3</b>\n

View File

@ -22,7 +22,8 @@
<item name="OpenFileDrawable">@drawable/collections_collection</item>
<item name="CreateDbDrawable">@drawable/collections_new_label</item>
<item name="OpenUrlDrawable">@drawable/location_web_site</item>
<item name="ic_action_search_drawable">@drawable/ic_action_search_holodark</item>
<item name="ic_launcher_folder_small">@drawable/ic_launcher_folder_small</item>
</style>
<style name="NoTitleBar"></style>
<style name="Dialog" parent="android:Theme.Dialog"></style>

View File

@ -60,11 +60,20 @@ namespace keepass2android
/// </summary>
public static class AppNames
{
#if DEBUG
public const string AppName = "Keepass2Android Debug";
#else
public const string AppName = "@string/app_name";
#endif
public const int AppNameResource = Resource.String.app_name;
public const string AppNameShort = "@string/short_app_name";
public const string AppLauncherTitle = "@string/app_name";
#if DEBUG
public const string PackagePart = "keepass2android_debug";
#else
public const string PackagePart = "keepass2android";
#endif
public const int LauncherIcon = Resource.Drawable.ic_launcher;
public const string Searchable = "@xml/searchable";
}

View File

@ -30,7 +30,7 @@
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;EXCLUDE_TWOFISH;EXCLUDE_KEYBOARD;EXCLUDE_FILECHOOSER;EXCLUDE_JAVAFILESTORAGE;EXCLUDE_KEYTRANSFORM</DefineConstants>
<DefineConstants>DEBUG;EXCLUDE_TWOFISH;INCLUDE_KEYBOARD;INCLUDE_FILECHOOSER;INCLUDE_JAVAFILESTORAGE;INCLUDE_KEYTRANSFORM</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>False</ConsolePause>
@ -180,9 +180,6 @@
<AndroidAsset Include="Assets\DejaVuSansMono.ttf" />
<AndroidAsset Include="Assets\LICENSE_dejavu" />
<None Include="Resources\AboutResources.txt" />
<None Include="Properties\AndroidManifest.xml">
<SubType>Designer</SubType>
</None>
<None Include="filelist.txt">
<Visible>False</Visible>
</None>
@ -375,7 +372,9 @@
<AndroidResource Include="Resources\values\strings.xml">
<SubType>Designer</SubType>
</AndroidResource>
<AndroidResource Include="Resources\menu-v11\entry.xml" />
<AndroidResource Include="Resources\menu-v11\entry.xml">
<SubType>Designer</SubType>
</AndroidResource>
<AndroidResource Include="Resources\menu-v11\password.xml" />
<AndroidResource Include="Resources\menu-v11\entry_edit.xml" />
<AndroidResource Include="Resources\menu-v11\group.xml" />
@ -760,12 +759,21 @@
<ItemGroup>
<AndroidResource Include="Resources\drawable\transparent.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\layout\donate_bday.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\layout\donate_bdaymissed.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\layout\donate.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\oktoberfest.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\donate_cake.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-hdpi-v11\ic_unlocked_gray.png" />
</ItemGroup>
@ -907,7 +915,9 @@
<AndroidResource Include="Resources\drawable-hdpi\location_web_site_holodark.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\values-v14\styles_dark.xml" />
<AndroidResource Include="Resources\values-v14\styles_dark.xml">
<SubType>Designer</SubType>
</AndroidResource>
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\values-v14\styles_light.xml">
@ -929,4 +939,22 @@
<ItemGroup>
<AndroidResource Include="Resources\values-bg-rBG\strings.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\ic_launcher_gray_bday.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-hdpi-v11\ic_launcher_gray_bday.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-v11\ic_launcher_gray_bday.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xhdpi-v11\ic_launcher_gray_bday.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxhdpi-v11\ic_launcher_gray_bday.png" />
</ItemGroup>
<ItemGroup>
<TransformFile Include="Properties\AndroidManifest.xml" />
</ItemGroup>
</Project>

View File

@ -139,6 +139,11 @@ namespace keepass2android
_numElementsToWaitFor= 0;
ClearKeyboard(true);
}
if (_clearClipboardTask != null)
{
Kp2aLog.Log("Clearing clipboard due to stop CopyToClipboardService");
_clearClipboardTask.Run();
}
Kp2aLog.Log("Destroyed Show-Notification-Receiver.");
@ -350,10 +355,11 @@ namespace keepass2android
String sClipClear = prefs.GetString(GetString(Resource.String.clipboard_timeout_key), GetString(Resource.String.clipboard_timeout_default));
long clipClearTime = long.Parse(sClipClear);
_clearClipboardTask = new ClearClipboardTask(this, text, _uiThreadCallback);
if ( clipClearTime > 0 ) {
_numElementsToWaitFor++;
_timer.Schedule(new ClearClipboardTask(this, text, _uiThreadCallback), clipClearTime);
_timer.Schedule(_clearClipboardTask, clipClearTime);
}
}
@ -385,6 +391,7 @@ namespace keepass2android
// Setup to allow the toast to happen in the foreground
readonly Handler _uiThreadCallback = new Handler();
private ClearClipboardTask _clearClipboardTask;
private Notification GetNotification(String intentText, int descResId, int drawableResId, String entryName) {
String desc = GetString(descResId);

View File

@ -199,7 +199,7 @@ namespace keepass2android
if (String.IsNullOrEmpty(name))
{
//todo: if paranoid ("don't remember recent files") return "***"
name = UrlUtil.StripExtension(UrlUtil.GetFileName(db.IOConnectionInfo.Path));
name = App.Kp2a.GetFileStorage(db.IOConnectionInfo).GetFilenameWithoutPathAndExt(db.IOConnectionInfo);
}
return name;