mirror of
https://github.com/moparisthebest/keepass2android
synced 2024-11-26 11:12:15 -05:00
Merge https://git01.codeplex.com/forks/alexvallat/keepass2androidperfopt into AlexVallat/Keepass2AndroidPerfOpt
This commit is contained in:
commit
d90407fd2d
@ -40,8 +40,14 @@ namespace KeePassLib.Collections
|
|||||||
IDeepCloneable<ProtectedBinaryDictionary>,
|
IDeepCloneable<ProtectedBinaryDictionary>,
|
||||||
IEnumerable<KeyValuePair<string, ProtectedBinary>>
|
IEnumerable<KeyValuePair<string, ProtectedBinary>>
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
private SortedDictionary<string, ProtectedBinary> m_vBinaries =
|
private SortedDictionary<string, ProtectedBinary> m_vBinaries =
|
||||||
new SortedDictionary<string, ProtectedBinary>();
|
new SortedDictionary<string, ProtectedBinary>();
|
||||||
|
*/
|
||||||
|
|
||||||
|
private Dictionary<string, ProtectedBinary> m_vBinaries =
|
||||||
|
new Dictionary<string, ProtectedBinary>();
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the number of binaries in this entry.
|
/// Get the number of binaries in this entry.
|
||||||
|
@ -40,8 +40,9 @@ namespace KeePassLib.Collections
|
|||||||
IDeepCloneable<ProtectedStringDictionary>,
|
IDeepCloneable<ProtectedStringDictionary>,
|
||||||
IEnumerable<KeyValuePair<string, ProtectedString>>
|
IEnumerable<KeyValuePair<string, ProtectedString>>
|
||||||
{
|
{
|
||||||
private SortedDictionary<string, ProtectedString> m_vStrings =
|
/*private SortedDictionary<string, ProtectedString> m_vStrings =
|
||||||
new SortedDictionary<string, ProtectedString>();
|
new SortedDictionary<string, ProtectedString>();*/
|
||||||
|
private Dictionary<string, ProtectedString> m_vStrings = new Dictionary<string, ProtectedString>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the number of strings in this entry.
|
/// Get the number of strings in this entry.
|
||||||
|
@ -101,5 +101,19 @@ namespace KeePassLib.Interfaces
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="bModified">Update last modification time.</param>
|
/// <param name="bModified">Update last modification time.</param>
|
||||||
void Touch(bool bModified);
|
void Touch(bool bModified);
|
||||||
|
|
||||||
|
#region Set times lazily
|
||||||
|
// Passing xml datetime string to be parsed only on demand
|
||||||
|
|
||||||
|
void SetLazyLastModificationTime(string xmlDateTime);
|
||||||
|
|
||||||
|
void SetLazyCreationTime(string xmlDateTime);
|
||||||
|
|
||||||
|
void SetLazyLastAccessTime(string xmlDateTime);
|
||||||
|
|
||||||
|
void SetLazyExpiryTime(string xmlDateTime);
|
||||||
|
|
||||||
|
void SetLazyLocationChanged(string xmlDateTime);
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
<DebugType>full</DebugType>
|
<DebugType>full</DebugType>
|
||||||
<Optimize>False</Optimize>
|
<Optimize>False</Optimize>
|
||||||
<OutputPath>bin\Debug</OutputPath>
|
<OutputPath>bin\Debug</OutputPath>
|
||||||
<DefineConstants>DEBUG;</DefineConstants>
|
<DefineConstants>TRACE;DEBUG;</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<ConsolePause>False</ConsolePause>
|
<ConsolePause>False</ConsolePause>
|
||||||
|
@ -40,6 +40,7 @@ namespace KeePassLib
|
|||||||
private PwUuid m_uuid = PwUuid.Zero;
|
private PwUuid m_uuid = PwUuid.Zero;
|
||||||
private PwGroup m_pParentGroup = null;
|
private PwGroup m_pParentGroup = null;
|
||||||
private DateTime m_tParentGroupLastMod = PwDefs.DtDefaultNow;
|
private DateTime m_tParentGroupLastMod = PwDefs.DtDefaultNow;
|
||||||
|
private string m_tParentGroupLastModLazy;
|
||||||
|
|
||||||
private ProtectedStringDictionary m_listStrings = new ProtectedStringDictionary();
|
private ProtectedStringDictionary m_listStrings = new ProtectedStringDictionary();
|
||||||
private ProtectedBinaryDictionary m_listBinaries = new ProtectedBinaryDictionary();
|
private ProtectedBinaryDictionary m_listBinaries = new ProtectedBinaryDictionary();
|
||||||
@ -56,6 +57,12 @@ namespace KeePassLib
|
|||||||
private DateTime m_tLastMod = PwDefs.DtDefaultNow;
|
private DateTime m_tLastMod = PwDefs.DtDefaultNow;
|
||||||
private DateTime m_tLastAccess = PwDefs.DtDefaultNow;
|
private DateTime m_tLastAccess = PwDefs.DtDefaultNow;
|
||||||
private DateTime m_tExpire = PwDefs.DtDefaultNow;
|
private DateTime m_tExpire = PwDefs.DtDefaultNow;
|
||||||
|
|
||||||
|
private string m_tCreationLazy;
|
||||||
|
private string m_tLastModLazy;
|
||||||
|
private string m_tLastAccessLazy;
|
||||||
|
private string m_tExpireLazy;
|
||||||
|
|
||||||
private bool m_bExpires = false;
|
private bool m_bExpires = false;
|
||||||
private ulong m_uUsageCount = 0;
|
private ulong m_uUsageCount = 0;
|
||||||
|
|
||||||
@ -92,8 +99,13 @@ namespace KeePassLib
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTime LocationChanged
|
public DateTime LocationChanged
|
||||||
{
|
{
|
||||||
get { return m_tParentGroupLastMod; }
|
get { return GetLazyTime(ref m_tParentGroupLastModLazy, ref m_tParentGroupLastMod); }
|
||||||
set { m_tParentGroupLastMod = value; }
|
set { m_tParentGroupLastMod = value; m_tParentGroupLastModLazy = null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetLazyLocationChanged(string xmlDateTime)
|
||||||
|
{
|
||||||
|
m_tParentGroupLastModLazy = xmlDateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -195,8 +207,13 @@ namespace KeePassLib
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTime CreationTime
|
public DateTime CreationTime
|
||||||
{
|
{
|
||||||
get { return m_tCreation; }
|
get { return GetLazyTime(ref m_tCreationLazy, ref m_tCreation); }
|
||||||
set { m_tCreation = value; }
|
set { m_tCreation = value; m_tCreationLazy = null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetLazyCreationTime(string xmlDateTime)
|
||||||
|
{
|
||||||
|
m_tCreationLazy = xmlDateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -204,8 +221,13 @@ namespace KeePassLib
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTime LastAccessTime
|
public DateTime LastAccessTime
|
||||||
{
|
{
|
||||||
get { return m_tLastAccess; }
|
get { return GetLazyTime(ref m_tLastAccessLazy, ref m_tLastAccess); }
|
||||||
set { m_tLastAccess = value; }
|
set { m_tLastAccess = value; m_tLastAccessLazy = null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetLazyLastAccessTime(string xmlDateTime)
|
||||||
|
{
|
||||||
|
m_tLastAccessLazy = xmlDateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -213,8 +235,13 @@ namespace KeePassLib
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTime LastModificationTime
|
public DateTime LastModificationTime
|
||||||
{
|
{
|
||||||
get { return m_tLastMod; }
|
get { return GetLazyTime(ref m_tLastModLazy, ref m_tLastMod); }
|
||||||
set { m_tLastMod = value; }
|
set { m_tLastMod = value; m_tLastModLazy = null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetLazyLastModificationTime(string xmlDateTime)
|
||||||
|
{
|
||||||
|
m_tLastModLazy = xmlDateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -223,8 +250,13 @@ namespace KeePassLib
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTime ExpiryTime
|
public DateTime ExpiryTime
|
||||||
{
|
{
|
||||||
get { return m_tExpire; }
|
get { return GetLazyTime(ref m_tExpireLazy, ref m_tExpire); }
|
||||||
set { m_tExpire = value; }
|
set { m_tExpire = value; m_tExpireLazy = null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetLazyExpiryTime(string xmlDateTime)
|
||||||
|
{
|
||||||
|
m_tExpireLazy = xmlDateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -333,6 +365,7 @@ namespace KeePassLib
|
|||||||
peNew.m_uuid = m_uuid; // PwUuid is immutable
|
peNew.m_uuid = m_uuid; // PwUuid is immutable
|
||||||
peNew.m_pParentGroup = m_pParentGroup;
|
peNew.m_pParentGroup = m_pParentGroup;
|
||||||
peNew.m_tParentGroupLastMod = m_tParentGroupLastMod;
|
peNew.m_tParentGroupLastMod = m_tParentGroupLastMod;
|
||||||
|
peNew.m_tParentGroupLastModLazy = m_tParentGroupLastModLazy;
|
||||||
|
|
||||||
peNew.m_listStrings = m_listStrings.CloneDeep();
|
peNew.m_listStrings = m_listStrings.CloneDeep();
|
||||||
peNew.m_listBinaries = m_listBinaries.CloneDeep();
|
peNew.m_listBinaries = m_listBinaries.CloneDeep();
|
||||||
@ -352,6 +385,11 @@ namespace KeePassLib
|
|||||||
peNew.m_bExpires = m_bExpires;
|
peNew.m_bExpires = m_bExpires;
|
||||||
peNew.m_uUsageCount = m_uUsageCount;
|
peNew.m_uUsageCount = m_uUsageCount;
|
||||||
|
|
||||||
|
peNew.m_tCreationLazy = m_tCreationLazy;
|
||||||
|
peNew.m_tLastModLazy = m_tLastModLazy;
|
||||||
|
peNew.m_tLastAccessLazy = m_tLastAccessLazy;
|
||||||
|
peNew.m_tExpireLazy = m_tExpireLazy;
|
||||||
|
|
||||||
peNew.m_strOverrideUrl = m_strOverrideUrl;
|
peNew.m_strOverrideUrl = m_strOverrideUrl;
|
||||||
|
|
||||||
peNew.m_vTags = new List<string>(m_vTags);
|
peNew.m_vTags = new List<string>(m_vTags);
|
||||||
@ -365,6 +403,7 @@ namespace KeePassLib
|
|||||||
|
|
||||||
peNew.m_uuid = m_uuid; // PwUuid is immutable
|
peNew.m_uuid = m_uuid; // PwUuid is immutable
|
||||||
peNew.m_tParentGroupLastMod = m_tParentGroupLastMod;
|
peNew.m_tParentGroupLastMod = m_tParentGroupLastMod;
|
||||||
|
peNew.m_tParentGroupLastModLazy = m_tParentGroupLastModLazy;
|
||||||
// Do not assign m_pParentGroup
|
// Do not assign m_pParentGroup
|
||||||
|
|
||||||
return peNew;
|
return peNew;
|
||||||
@ -417,7 +456,7 @@ namespace KeePassLib
|
|||||||
if((pwOpt & PwCompareOptions.IgnoreParentGroup) == PwCompareOptions.None)
|
if((pwOpt & PwCompareOptions.IgnoreParentGroup) == PwCompareOptions.None)
|
||||||
{
|
{
|
||||||
if(m_pParentGroup != pe.m_pParentGroup) return false;
|
if(m_pParentGroup != pe.m_pParentGroup) return false;
|
||||||
if(!bIgnoreLastMod && (m_tParentGroupLastMod != pe.m_tParentGroupLastMod))
|
if(!bIgnoreLastMod && (LocationChanged != pe.LocationChanged))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,10 +500,10 @@ namespace KeePassLib
|
|||||||
if(m_clrForeground != pe.m_clrForeground) return false;
|
if(m_clrForeground != pe.m_clrForeground) return false;
|
||||||
if(m_clrBackground != pe.m_clrBackground) return false;
|
if(m_clrBackground != pe.m_clrBackground) return false;
|
||||||
|
|
||||||
if(m_tCreation != pe.m_tCreation) return false;
|
if(CreationTime != pe.CreationTime) return false;
|
||||||
if(!bIgnoreLastMod && (m_tLastMod != pe.m_tLastMod)) return false;
|
if(!bIgnoreLastMod && (LastModificationTime != pe.LastModificationTime)) return false;
|
||||||
if(!bIgnoreLastAccess && (m_tLastAccess != pe.m_tLastAccess)) return false;
|
if(!bIgnoreLastAccess && (LastAccessTime != pe.LastAccessTime)) return false;
|
||||||
if(m_tExpire != pe.m_tExpire) return false;
|
if(ExpiryTime != pe.ExpiryTime) return false;
|
||||||
if(m_bExpires != pe.m_bExpires) return false;
|
if(m_bExpires != pe.m_bExpires) return false;
|
||||||
if(!bIgnoreLastAccess && (m_uUsageCount != pe.m_uUsageCount)) return false;
|
if(!bIgnoreLastAccess && (m_uUsageCount != pe.m_uUsageCount)) return false;
|
||||||
|
|
||||||
@ -494,14 +533,14 @@ namespace KeePassLib
|
|||||||
{
|
{
|
||||||
Debug.Assert(peTemplate != null); if(peTemplate == null) throw new ArgumentNullException("peTemplate");
|
Debug.Assert(peTemplate != null); if(peTemplate == null) throw new ArgumentNullException("peTemplate");
|
||||||
|
|
||||||
if(bOnlyIfNewer && (peTemplate.m_tLastMod < m_tLastMod)) return;
|
if(bOnlyIfNewer && (peTemplate.LastModificationTime < LastModificationTime)) return;
|
||||||
|
|
||||||
// Template UUID should be the same as the current one
|
// Template UUID should be the same as the current one
|
||||||
Debug.Assert(m_uuid.EqualsValue(peTemplate.m_uuid));
|
Debug.Assert(m_uuid.EqualsValue(peTemplate.m_uuid));
|
||||||
m_uuid = peTemplate.m_uuid;
|
m_uuid = peTemplate.m_uuid;
|
||||||
|
|
||||||
if(bAssignLocationChanged)
|
if(bAssignLocationChanged)
|
||||||
m_tParentGroupLastMod = peTemplate.m_tParentGroupLastMod;
|
m_tParentGroupLastMod = peTemplate.LocationChanged;
|
||||||
|
|
||||||
m_listStrings = peTemplate.m_listStrings;
|
m_listStrings = peTemplate.m_listStrings;
|
||||||
m_listBinaries = peTemplate.m_listBinaries;
|
m_listBinaries = peTemplate.m_listBinaries;
|
||||||
@ -514,10 +553,10 @@ namespace KeePassLib
|
|||||||
m_clrForeground = peTemplate.m_clrForeground;
|
m_clrForeground = peTemplate.m_clrForeground;
|
||||||
m_clrBackground = peTemplate.m_clrBackground;
|
m_clrBackground = peTemplate.m_clrBackground;
|
||||||
|
|
||||||
m_tCreation = peTemplate.m_tCreation;
|
m_tCreation = peTemplate.CreationTime;
|
||||||
m_tLastMod = peTemplate.m_tLastMod;
|
m_tLastMod = peTemplate.LastModificationTime;
|
||||||
m_tLastAccess = peTemplate.m_tLastAccess;
|
m_tLastAccess = peTemplate.LastAccessTime;
|
||||||
m_tExpire = peTemplate.m_tExpire;
|
m_tExpire = peTemplate.ExpiryTime;
|
||||||
m_bExpires = peTemplate.m_bExpires;
|
m_bExpires = peTemplate.m_bExpires;
|
||||||
m_uUsageCount = peTemplate.m_uUsageCount;
|
m_uUsageCount = peTemplate.m_uUsageCount;
|
||||||
|
|
||||||
@ -844,6 +883,16 @@ namespace KeePassLib
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DateTime GetLazyTime(ref string lazyTime, ref DateTime dateTime)
|
||||||
|
{
|
||||||
|
if (lazyTime != null)
|
||||||
|
{
|
||||||
|
dateTime = TimeUtil.DeserializeUtcOrDefault(lazyTime, dateTime);
|
||||||
|
lazyTime = null;
|
||||||
|
}
|
||||||
|
return dateTime;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class PwEntryComparer : IComparer<PwEntry>
|
public sealed class PwEntryComparer : IComparer<PwEntry>
|
||||||
|
@ -35,6 +35,11 @@ namespace KeePassLib
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class PwGroup : ITimeLogger, IStructureItem, IDeepCloneable<PwGroup>
|
public sealed class PwGroup : ITimeLogger, IStructureItem, IDeepCloneable<PwGroup>
|
||||||
{
|
{
|
||||||
|
private const int SearchContextStringMaxLength = 50; // Note, doesn't include elipsis, if added
|
||||||
|
public const string SearchContextUuid = "Uuid";
|
||||||
|
public const string SearchContextParentGroup = "Parent Group";
|
||||||
|
public const string SearchContextTags = "Tags";
|
||||||
|
|
||||||
public const bool DefaultAutoTypeEnabled = true;
|
public const bool DefaultAutoTypeEnabled = true;
|
||||||
public const bool DefaultSearchingEnabled = true;
|
public const bool DefaultSearchingEnabled = true;
|
||||||
|
|
||||||
@ -42,6 +47,7 @@ namespace KeePassLib
|
|||||||
private PwObjectList<PwEntry> m_listEntries = new PwObjectList<PwEntry>();
|
private PwObjectList<PwEntry> m_listEntries = new PwObjectList<PwEntry>();
|
||||||
private PwGroup m_pParentGroup = null;
|
private PwGroup m_pParentGroup = null;
|
||||||
private DateTime m_tParentGroupLastMod = PwDefs.DtDefaultNow;
|
private DateTime m_tParentGroupLastMod = PwDefs.DtDefaultNow;
|
||||||
|
private string m_tParentGroupLastModLazy;
|
||||||
|
|
||||||
private PwUuid m_uuid = PwUuid.Zero;
|
private PwUuid m_uuid = PwUuid.Zero;
|
||||||
private string m_strName = string.Empty;
|
private string m_strName = string.Empty;
|
||||||
@ -54,6 +60,12 @@ namespace KeePassLib
|
|||||||
private DateTime m_tLastMod = PwDefs.DtDefaultNow;
|
private DateTime m_tLastMod = PwDefs.DtDefaultNow;
|
||||||
private DateTime m_tLastAccess = PwDefs.DtDefaultNow;
|
private DateTime m_tLastAccess = PwDefs.DtDefaultNow;
|
||||||
private DateTime m_tExpire = PwDefs.DtDefaultNow;
|
private DateTime m_tExpire = PwDefs.DtDefaultNow;
|
||||||
|
|
||||||
|
private string m_tCreationLazy;
|
||||||
|
private string m_tLastModLazy;
|
||||||
|
private string m_tLastAccessLazy;
|
||||||
|
private string m_tExpireLazy;
|
||||||
|
|
||||||
private bool m_bExpires = false;
|
private bool m_bExpires = false;
|
||||||
private ulong m_uUsageCount = 0;
|
private ulong m_uUsageCount = 0;
|
||||||
|
|
||||||
@ -146,8 +158,13 @@ namespace KeePassLib
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTime LocationChanged
|
public DateTime LocationChanged
|
||||||
{
|
{
|
||||||
get { return m_tParentGroupLastMod; }
|
get { return GetLazyTime(ref m_tParentGroupLastModLazy, ref m_tParentGroupLastMod); }
|
||||||
set { m_tParentGroupLastMod = value; }
|
set { m_tParentGroupLastMod = value; m_tParentGroupLastModLazy = null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetLazyLocationChanged(string xmlDateTime)
|
||||||
|
{
|
||||||
|
m_tParentGroupLastModLazy = xmlDateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -165,17 +182,13 @@ namespace KeePassLib
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTime CreationTime
|
public DateTime CreationTime
|
||||||
{
|
{
|
||||||
get { return m_tCreation; }
|
get { return GetLazyTime(ref m_tCreationLazy, ref m_tCreation); }
|
||||||
set { m_tCreation = value; }
|
set { m_tCreation = value; m_tCreationLazy = null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public void SetLazyCreationTime(string xmlDateTime)
|
||||||
/// The date/time when this group was last modified.
|
|
||||||
/// </summary>
|
|
||||||
public DateTime LastModificationTime
|
|
||||||
{
|
{
|
||||||
get { return m_tLastMod; }
|
m_tCreationLazy = xmlDateTime;
|
||||||
set { m_tLastMod = value; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -183,17 +196,42 @@ namespace KeePassLib
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTime LastAccessTime
|
public DateTime LastAccessTime
|
||||||
{
|
{
|
||||||
get { return m_tLastAccess; }
|
get { return GetLazyTime(ref m_tLastAccessLazy, ref m_tLastAccess); }
|
||||||
set { m_tLastAccess = value; }
|
set { m_tLastAccess = value; m_tLastAccessLazy = null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetLazyLastAccessTime(string xmlDateTime)
|
||||||
|
{
|
||||||
|
m_tLastAccessLazy = xmlDateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The date/time when this group expires.
|
/// The date/time when this group was last modified.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime LastModificationTime
|
||||||
|
{
|
||||||
|
get { return GetLazyTime(ref m_tLastModLazy, ref m_tLastMod); }
|
||||||
|
set { m_tLastMod = value; m_tLastModLazy = null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetLazyLastModificationTime(string xmlDateTime)
|
||||||
|
{
|
||||||
|
m_tLastModLazy = xmlDateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The date/time when this group expires. Use the <c>Expires</c> property
|
||||||
|
/// to specify if the group does actually expire or not.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTime ExpiryTime
|
public DateTime ExpiryTime
|
||||||
{
|
{
|
||||||
get { return m_tExpire; }
|
get { return GetLazyTime(ref m_tExpireLazy, ref m_tExpire); }
|
||||||
set { m_tExpire = value; }
|
set { m_tExpire = value; m_tExpireLazy = null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetLazyExpiryTime(string xmlDateTime)
|
||||||
|
{
|
||||||
|
m_tExpireLazy = xmlDateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -344,6 +382,7 @@ namespace KeePassLib
|
|||||||
pg.m_listEntries = m_listEntries.CloneDeep();
|
pg.m_listEntries = m_listEntries.CloneDeep();
|
||||||
pg.m_pParentGroup = m_pParentGroup;
|
pg.m_pParentGroup = m_pParentGroup;
|
||||||
pg.m_tParentGroupLastMod = m_tParentGroupLastMod;
|
pg.m_tParentGroupLastMod = m_tParentGroupLastMod;
|
||||||
|
pg.m_tParentGroupLastModLazy = m_tParentGroupLastModLazy;
|
||||||
|
|
||||||
pg.m_strName = m_strName;
|
pg.m_strName = m_strName;
|
||||||
pg.m_strNotes = m_strNotes;
|
pg.m_strNotes = m_strNotes;
|
||||||
@ -358,6 +397,11 @@ namespace KeePassLib
|
|||||||
pg.m_bExpires = m_bExpires;
|
pg.m_bExpires = m_bExpires;
|
||||||
pg.m_uUsageCount = m_uUsageCount;
|
pg.m_uUsageCount = m_uUsageCount;
|
||||||
|
|
||||||
|
pg.m_tCreationLazy = m_tCreationLazy;
|
||||||
|
pg.m_tLastModLazy = m_tLastModLazy;
|
||||||
|
pg.m_tLastAccessLazy = m_tLastAccessLazy;
|
||||||
|
pg.m_tExpireLazy = m_tExpireLazy;
|
||||||
|
|
||||||
pg.m_bIsExpanded = m_bIsExpanded;
|
pg.m_bIsExpanded = m_bIsExpanded;
|
||||||
pg.m_bVirtual = m_bVirtual;
|
pg.m_bVirtual = m_bVirtual;
|
||||||
|
|
||||||
@ -398,7 +442,7 @@ namespace KeePassLib
|
|||||||
{
|
{
|
||||||
Debug.Assert(pgTemplate != null); if(pgTemplate == null) throw new ArgumentNullException("pgTemplate");
|
Debug.Assert(pgTemplate != null); if(pgTemplate == null) throw new ArgumentNullException("pgTemplate");
|
||||||
|
|
||||||
if(bOnlyIfNewer && (pgTemplate.m_tLastMod < m_tLastMod)) return;
|
if(bOnlyIfNewer && (pgTemplate.LastModificationTime < LastModificationTime)) return;
|
||||||
|
|
||||||
// Template UUID should be the same as the current one
|
// Template UUID should be the same as the current one
|
||||||
Debug.Assert(m_uuid.EqualsValue(pgTemplate.m_uuid));
|
Debug.Assert(m_uuid.EqualsValue(pgTemplate.m_uuid));
|
||||||
@ -413,10 +457,10 @@ namespace KeePassLib
|
|||||||
m_pwIcon = pgTemplate.m_pwIcon;
|
m_pwIcon = pgTemplate.m_pwIcon;
|
||||||
m_pwCustomIconID = pgTemplate.m_pwCustomIconID;
|
m_pwCustomIconID = pgTemplate.m_pwCustomIconID;
|
||||||
|
|
||||||
m_tCreation = pgTemplate.m_tCreation;
|
m_tCreation = pgTemplate.CreationTime;
|
||||||
m_tLastMod = pgTemplate.m_tLastMod;
|
m_tLastMod = pgTemplate.LastModificationTime;
|
||||||
m_tLastAccess = pgTemplate.m_tLastAccess;
|
m_tLastAccess = pgTemplate.LastAccessTime;
|
||||||
m_tExpire = pgTemplate.m_tExpire;
|
m_tExpire = pgTemplate.ExpiryTime;
|
||||||
m_bExpires = pgTemplate.m_bExpires;
|
m_bExpires = pgTemplate.m_bExpires;
|
||||||
m_uUsageCount = pgTemplate.m_uUsageCount;
|
m_uUsageCount = pgTemplate.m_uUsageCount;
|
||||||
|
|
||||||
@ -673,6 +717,18 @@ namespace KeePassLib
|
|||||||
/// be stored.</param>
|
/// be stored.</param>
|
||||||
public void SearchEntries(SearchParameters sp, PwObjectList<PwEntry> listStorage,
|
public void SearchEntries(SearchParameters sp, PwObjectList<PwEntry> listStorage,
|
||||||
IStatusLogger slStatus)
|
IStatusLogger slStatus)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Search this group and all subgroups for entries.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sp">Specifies the search method.</param>
|
||||||
|
/// <param name="listStorage">Entry list in which the search results will
|
||||||
|
/// be stored.</param>
|
||||||
|
/// <param name="resultContexts">Dictionary that will be populated with text fragments indicating the context of why each entry (keyed by Uuid) was returned</param>
|
||||||
|
public void SearchEntries(SearchParameters sp, PwObjectList<PwEntry> listStorage, IDictionary<PwUuid, String> resultContexts,
|
||||||
|
IStatusLogger slStatus)
|
||||||
{
|
{
|
||||||
if(sp == null) { Debug.Assert(false); return; }
|
if(sp == null) { Debug.Assert(false); return; }
|
||||||
if(listStorage == null) { Debug.Assert(false); return; }
|
if(listStorage == null) { Debug.Assert(false); return; }
|
||||||
@ -683,7 +739,7 @@ namespace KeePassLib
|
|||||||
if((lTerms.Count <= 1) || sp.RegularExpression)
|
if((lTerms.Count <= 1) || sp.RegularExpression)
|
||||||
{
|
{
|
||||||
if(slStatus != null) uTotalEntries = GetEntriesCount(true);
|
if(slStatus != null) uTotalEntries = GetEntriesCount(true);
|
||||||
SearchEntriesSingle(sp, listStorage, slStatus, ref uCurEntries,
|
SearchEntriesSingle(sp, listStorage, resultContexts , slStatus, ref uCurEntries,
|
||||||
uTotalEntries);
|
uTotalEntries);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -715,7 +771,7 @@ namespace KeePassLib
|
|||||||
bNegate = (sp.SearchString.Length > 0);
|
bNegate = (sp.SearchString.Length > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!pg.SearchEntriesSingle(sp, pgNew.Entries, slStatus,
|
if(!pg.SearchEntriesSingle(sp, pgNew.Entries, resultContexts, slStatus,
|
||||||
ref uCurEntries, uTotalEntries))
|
ref uCurEntries, uTotalEntries))
|
||||||
{
|
{
|
||||||
pg = null;
|
pg = null;
|
||||||
@ -740,7 +796,7 @@ namespace KeePassLib
|
|||||||
}
|
}
|
||||||
|
|
||||||
private bool SearchEntriesSingle(SearchParameters spIn,
|
private bool SearchEntriesSingle(SearchParameters spIn,
|
||||||
PwObjectList<PwEntry> listStorage, IStatusLogger slStatus,
|
PwObjectList<PwEntry> listStorage, IDictionary<PwUuid, String> resultContexts, IStatusLogger slStatus,
|
||||||
ref ulong uCurEntries, ulong uTotalEntries)
|
ref ulong uCurEntries, ulong uTotalEntries)
|
||||||
{
|
{
|
||||||
SearchParameters sp = spIn.Clone();
|
SearchParameters sp = spIn.Clone();
|
||||||
@ -823,42 +879,42 @@ namespace KeePassLib
|
|||||||
if(strKey == PwDefs.TitleField)
|
if(strKey == PwDefs.TitleField)
|
||||||
{
|
{
|
||||||
if(bTitle) SearchEvalAdd(sp, kvp.Value.ReadString(),
|
if(bTitle) SearchEvalAdd(sp, kvp.Value.ReadString(),
|
||||||
rx, pe, listStorage);
|
rx, pe, listStorage, resultContexts, strKey);
|
||||||
}
|
}
|
||||||
else if(strKey == PwDefs.UserNameField)
|
else if(strKey == PwDefs.UserNameField)
|
||||||
{
|
{
|
||||||
if(bUserName) SearchEvalAdd(sp, kvp.Value.ReadString(),
|
if(bUserName) SearchEvalAdd(sp, kvp.Value.ReadString(),
|
||||||
rx, pe, listStorage);
|
rx, pe, listStorage, resultContexts, strKey);
|
||||||
}
|
}
|
||||||
else if(strKey == PwDefs.PasswordField)
|
else if(strKey == PwDefs.PasswordField)
|
||||||
{
|
{
|
||||||
if(bPassword) SearchEvalAdd(sp, kvp.Value.ReadString(),
|
if(bPassword) SearchEvalAdd(sp, kvp.Value.ReadString(),
|
||||||
rx, pe, listStorage);
|
rx, pe, listStorage, resultContexts, strKey);
|
||||||
}
|
}
|
||||||
else if(strKey == PwDefs.UrlField)
|
else if(strKey == PwDefs.UrlField)
|
||||||
{
|
{
|
||||||
if(bUrl) SearchEvalAdd(sp, kvp.Value.ReadString(),
|
if(bUrl) SearchEvalAdd(sp, kvp.Value.ReadString(),
|
||||||
rx, pe, listStorage);
|
rx, pe, listStorage, resultContexts, strKey);
|
||||||
}
|
}
|
||||||
else if(strKey == PwDefs.NotesField)
|
else if(strKey == PwDefs.NotesField)
|
||||||
{
|
{
|
||||||
if(bNotes) SearchEvalAdd(sp, kvp.Value.ReadString(),
|
if(bNotes) SearchEvalAdd(sp, kvp.Value.ReadString(),
|
||||||
rx, pe, listStorage);
|
rx, pe, listStorage, resultContexts, strKey);
|
||||||
}
|
}
|
||||||
else if(bOther)
|
else if(bOther)
|
||||||
SearchEvalAdd(sp, kvp.Value.ReadString(),
|
SearchEvalAdd(sp, kvp.Value.ReadString(),
|
||||||
rx, pe, listStorage);
|
rx, pe, listStorage, resultContexts, strKey);
|
||||||
|
|
||||||
// An entry can match only once => break if we have added it
|
// An entry can match only once => break if we have added it
|
||||||
if(listStorage.UCount > uInitialResults) break;
|
if(listStorage.UCount > uInitialResults) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bUuids && (listStorage.UCount == uInitialResults))
|
if(bUuids && (listStorage.UCount == uInitialResults))
|
||||||
SearchEvalAdd(sp, pe.Uuid.ToHexString(), rx, pe, listStorage);
|
SearchEvalAdd(sp, pe.Uuid.ToHexString(), rx, pe, listStorage, resultContexts, SearchContextUuid);
|
||||||
|
|
||||||
if(bGroupName && (listStorage.UCount == uInitialResults) &&
|
if(bGroupName && (listStorage.UCount == uInitialResults) &&
|
||||||
(pe.ParentGroup != null))
|
(pe.ParentGroup != null))
|
||||||
SearchEvalAdd(sp, pe.ParentGroup.Name, rx, pe, listStorage);
|
SearchEvalAdd(sp, pe.ParentGroup.Name, rx, pe, listStorage, resultContexts, SearchContextParentGroup);
|
||||||
|
|
||||||
if(bTags)
|
if(bTags)
|
||||||
{
|
{
|
||||||
@ -866,7 +922,7 @@ namespace KeePassLib
|
|||||||
{
|
{
|
||||||
if(listStorage.UCount != uInitialResults) break; // Match
|
if(listStorage.UCount != uInitialResults) break; // Match
|
||||||
|
|
||||||
SearchEvalAdd(sp, strTag, rx, pe, listStorage);
|
SearchEvalAdd(sp, strTag, rx, pe, listStorage, resultContexts, SearchContextTags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -880,14 +936,22 @@ namespace KeePassLib
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void SearchEvalAdd(SearchParameters sp, string strDataField,
|
private static void SearchEvalAdd(SearchParameters sp, string strDataField,
|
||||||
Regex rx, PwEntry pe, PwObjectList<PwEntry> lResults)
|
Regex rx, PwEntry pe, PwObjectList<PwEntry> lResults, IDictionary<PwUuid, String> resultContexts, string contextFieldName)
|
||||||
{
|
{
|
||||||
bool bMatch = false;
|
bool bMatch = false;
|
||||||
|
int matchPos;
|
||||||
|
|
||||||
if (rx == null)
|
if (rx == null)
|
||||||
bMatch = (strDataField.IndexOf(sp.SearchString,
|
{
|
||||||
sp.ComparisonMode) >= 0);
|
matchPos = strDataField.IndexOf(sp.SearchString, sp.ComparisonMode);
|
||||||
else bMatch = rx.IsMatch(strDataField);
|
bMatch = matchPos >= 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var match = rx.Match(strDataField);
|
||||||
|
bMatch = match.Success;
|
||||||
|
matchPos = match.Index;
|
||||||
|
}
|
||||||
|
|
||||||
if(!bMatch && (sp.DataTransformationFn != null))
|
if(!bMatch && (sp.DataTransformationFn != null))
|
||||||
{
|
{
|
||||||
@ -895,13 +959,36 @@ namespace KeePassLib
|
|||||||
if(!object.ReferenceEquals(strCmp, strDataField))
|
if(!object.ReferenceEquals(strCmp, strDataField))
|
||||||
{
|
{
|
||||||
if (rx == null)
|
if (rx == null)
|
||||||
bMatch = (strCmp.IndexOf(sp.SearchString,
|
{
|
||||||
sp.ComparisonMode) >= 0);
|
matchPos = strCmp.IndexOf(sp.SearchString, sp.ComparisonMode);
|
||||||
else bMatch = rx.IsMatch(strCmp);
|
bMatch = matchPos >= 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var match = rx.Match(strCmp);
|
||||||
|
bMatch = match.Success;
|
||||||
|
matchPos = match.Index;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bMatch) lResults.Add(pe);
|
if (bMatch)
|
||||||
|
{
|
||||||
|
lResults.Add(pe);
|
||||||
|
|
||||||
|
if (resultContexts != null)
|
||||||
|
{
|
||||||
|
// Trim the value if necessary
|
||||||
|
var contextString = strDataField;
|
||||||
|
if (contextString.Length > SearchContextStringMaxLength)
|
||||||
|
{
|
||||||
|
// Start 10% before actual data, and don't run over
|
||||||
|
var startPos = Math.Min(matchPos - (SearchContextStringMaxLength / 10), contextString.Length - SearchContextStringMaxLength);
|
||||||
|
contextString = "… " + contextString.Substring(startPos, SearchContextStringMaxLength) + ((startPos + SearchContextStringMaxLength < contextString.Length) ? " …" : null);
|
||||||
|
}
|
||||||
|
resultContexts[pe.Uuid] = contextFieldName + ": " + contextString;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<string> BuildEntryTagsList()
|
public List<string> BuildEntryTagsList()
|
||||||
@ -1422,6 +1509,16 @@ namespace KeePassLib
|
|||||||
}
|
}
|
||||||
m_listGroups.Clear();
|
m_listGroups.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DateTime GetLazyTime(ref string lazyTime, ref DateTime dateTime)
|
||||||
|
{
|
||||||
|
if (lazyTime != null)
|
||||||
|
{
|
||||||
|
dateTime = TimeUtil.DeserializeUtcOrDefault(lazyTime, m_tLastMod);
|
||||||
|
lazyTime = null;
|
||||||
|
}
|
||||||
|
return dateTime;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class PwGroupComparer : IComparer<PwGroup>
|
public sealed class PwGroupComparer : IComparer<PwGroup>
|
||||||
|
@ -497,19 +497,19 @@ namespace KeePassLib.Serialization
|
|||||||
Debug.Assert(tl != null);
|
Debug.Assert(tl != null);
|
||||||
|
|
||||||
if(xr.Name == ElemLastModTime)
|
if(xr.Name == ElemLastModTime)
|
||||||
tl.LastModificationTime = ReadTime(xr);
|
tl.SetLazyLastModificationTime(ReadString(xr));
|
||||||
else if(xr.Name == ElemCreationTime)
|
else if(xr.Name == ElemCreationTime)
|
||||||
tl.CreationTime = ReadTime(xr);
|
tl.SetLazyCreationTime(ReadString(xr));
|
||||||
else if(xr.Name == ElemLastAccessTime)
|
else if(xr.Name == ElemLastAccessTime)
|
||||||
tl.LastAccessTime = ReadTime(xr);
|
tl.SetLazyLastAccessTime(ReadString(xr));
|
||||||
else if(xr.Name == ElemExpiryTime)
|
else if(xr.Name == ElemExpiryTime)
|
||||||
tl.ExpiryTime = ReadTime(xr);
|
tl.SetLazyExpiryTime(ReadString(xr));
|
||||||
else if(xr.Name == ElemExpires)
|
else if(xr.Name == ElemExpires)
|
||||||
tl.Expires = ReadBool(xr, false);
|
tl.Expires = ReadBool(xr, false);
|
||||||
else if(xr.Name == ElemUsageCount)
|
else if(xr.Name == ElemUsageCount)
|
||||||
tl.UsageCount = ReadULong(xr, 0);
|
tl.UsageCount = ReadULong(xr, 0);
|
||||||
else if(xr.Name == ElemLocationChanged)
|
else if(xr.Name == ElemLocationChanged)
|
||||||
tl.LocationChanged = ReadTime(xr);
|
tl.SetLazyLocationChanged(ReadString(xr));
|
||||||
else ReadUnknown(xr);
|
else ReadUnknown(xr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -167,6 +167,22 @@ namespace KeePassLib.Utility
|
|||||||
return bResult;
|
return bResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deserializes a UTC XML DateTime to a local time, or returns defaultValue if it could not be parsed
|
||||||
|
/// </summary>
|
||||||
|
public static DateTime DeserializeUtcOrDefault(string xmlDateTimeString, DateTime defaultValue)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return System.Xml.XmlConvert.ToDateTime(xmlDateTimeString, System.Xml.XmlDateTimeSerializationMode.Local);
|
||||||
|
}
|
||||||
|
catch(FormatException)
|
||||||
|
{
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private static DateTime? m_dtUnixRoot = null;
|
private static DateTime? m_dtUnixRoot = null;
|
||||||
public static DateTime ConvertUnixTime(double dtUnix)
|
public static DateTime ConvertUnixTime(double dtUnix)
|
||||||
{
|
{
|
||||||
|
@ -15,8 +15,9 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
|
|||||||
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
|
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
using System;
|
using System;
|
||||||
using KeePassLib;
|
using System.Collections.Generic;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using KeePassLib;
|
||||||
using KeePassLib.Collections;
|
using KeePassLib.Collections;
|
||||||
using KeePassLib.Interfaces;
|
using KeePassLib.Interfaces;
|
||||||
using KeePassLib.Utility;
|
using KeePassLib.Utility;
|
||||||
@ -40,9 +41,9 @@ namespace keepass2android
|
|||||||
{
|
{
|
||||||
SearchParameters sp = new SearchParameters {SearchString = str};
|
SearchParameters sp = new SearchParameters {SearchString = str};
|
||||||
|
|
||||||
return Search(database, sp);
|
return Search(database, sp, null);
|
||||||
}
|
}
|
||||||
public PwGroup Search(Database database, SearchParameters sp)
|
public PwGroup Search(Database database, SearchParameters sp, IDictionary<PwUuid, String> resultContexts)
|
||||||
{
|
{
|
||||||
|
|
||||||
if(sp.RegularExpression) // Validate regular expression
|
if(sp.RegularExpression) // Validate regular expression
|
||||||
@ -56,7 +57,7 @@ namespace keepass2android
|
|||||||
PwObjectList<PwEntry> listResults = pgResults.Entries;
|
PwObjectList<PwEntry> listResults = pgResults.Entries;
|
||||||
|
|
||||||
|
|
||||||
database.Root.SearchEntries(sp, listResults, new NullStatusLogger());
|
database.Root.SearchEntries(sp, listResults, resultContexts, new NullStatusLogger());
|
||||||
|
|
||||||
|
|
||||||
return pgResults;
|
return pgResults;
|
||||||
|
@ -160,9 +160,9 @@ namespace keepass2android
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public PwGroup Search(SearchParameters searchParams)
|
public PwGroup Search(SearchParameters searchParams, IDictionary<PwUuid, String> resultContexts)
|
||||||
{
|
{
|
||||||
return SearchHelper.Search(this, searchParams);
|
return SearchHelper.Search(this, searchParams, resultContexts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
using Android.App;
|
using Android.App;
|
||||||
using Android.Content;
|
using Android.Content;
|
||||||
@ -178,17 +179,13 @@ namespace keepass2android
|
|||||||
extraGroup.RemoveAllViews();
|
extraGroup.RemoveAllViews();
|
||||||
}
|
}
|
||||||
bool hasExtraFields = false;
|
bool hasExtraFields = false;
|
||||||
foreach (KeyValuePair<string, ProtectedString> pair in Entry.Strings)
|
foreach (var view in from pair in Entry.Strings where !PwDefs.IsStandardField(pair.Key) orderby pair.Key
|
||||||
{
|
select CreateEditSection(pair.Key, pair.Value.ReadString()))
|
||||||
String key = pair.Key;
|
|
||||||
if (!PwDefs.IsStandardField(key))
|
|
||||||
{
|
{
|
||||||
//View view = new EntrySection(this, null, key, pair.Value.ReadString());
|
//View view = new EntrySection(this, null, key, pair.Value.ReadString());
|
||||||
View view = CreateEditSection(key, pair.Value.ReadString());
|
|
||||||
extraGroup.AddView(view);
|
extraGroup.AddView(view);
|
||||||
hasExtraFields = true;
|
hasExtraFields = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
FindViewById(Resource.Id.entry_extra_strings_label).Visibility = hasExtraFields ? ViewStates.Visible : ViewStates.Gone;
|
FindViewById(Resource.Id.entry_extra_strings_label).Visibility = hasExtraFields ? ViewStates.Visible : ViewStates.Gone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ namespace keepass2android
|
|||||||
entryId = new PwUuid(MemUtil.HexStringToByteArray(uuidBytes));
|
entryId = new PwUuid(MemUtil.HexStringToByteArray(uuidBytes));
|
||||||
|
|
||||||
State.ParentGroup = null;
|
State.ParentGroup = null;
|
||||||
if (entryId == PwUuid.Zero)
|
if (entryId.EqualsValue(PwUuid.Zero))
|
||||||
{
|
{
|
||||||
String groupId = i.GetStringExtra(KeyParent);
|
String groupId = i.GetStringExtra(KeyParent);
|
||||||
|
|
||||||
|
@ -195,6 +195,11 @@ namespace keepass2android
|
|||||||
MenuInflater inflater = MenuInflater;
|
MenuInflater inflater = MenuInflater;
|
||||||
inflater.Inflate(Resource.Menu.group, menu);
|
inflater.Inflate(Resource.Menu.group, menu);
|
||||||
|
|
||||||
|
var searchManager = (SearchManager)GetSystemService(Context.SearchService);
|
||||||
|
var searchView = (SearchView)menu.FindItem(Resource.Id.menu_search).ActionView;
|
||||||
|
|
||||||
|
searchView.SetSearchableInfo(searchManager.GetSearchableInfo(ComponentName));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,6 +245,7 @@ namespace keepass2android
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
case Resource.Id.menu_search:
|
case Resource.Id.menu_search:
|
||||||
|
case Resource.Id.menu_search_advanced:
|
||||||
OnSearchRequested();
|
OnSearchRequested();
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -20,6 +20,12 @@
|
|||||||
android:icon="@android:drawable/ic_menu_search"
|
android:icon="@android:drawable/ic_menu_search"
|
||||||
android:title="@string/menu_search"
|
android:title="@string/menu_search"
|
||||||
android:showAsAction="ifRoom"
|
android:showAsAction="ifRoom"
|
||||||
|
android:actionViewClass="android.widget.SearchView"
|
||||||
|
/>
|
||||||
|
<item android:id="@+id/menu_search_advanced"
|
||||||
|
android:icon="@android:drawable/ic_menu_search"
|
||||||
|
android:title="@string/menu_search_advanced"
|
||||||
|
android:showAsAction="never"
|
||||||
/>
|
/>
|
||||||
<item android:id="@+id/menu_lock"
|
<item android:id="@+id/menu_lock"
|
||||||
android:icon="@android:drawable/ic_lock_lock"
|
android:icon="@android:drawable/ic_lock_lock"
|
||||||
|
@ -27,6 +27,13 @@
|
|||||||
<item android:id="@+id/menu_search"
|
<item android:id="@+id/menu_search"
|
||||||
android:icon="@android:drawable/ic_menu_search"
|
android:icon="@android:drawable/ic_menu_search"
|
||||||
android:title="@string/menu_search"
|
android:title="@string/menu_search"
|
||||||
|
android:showAsAction="ifRoom"
|
||||||
|
android:actionViewClass="android.widget.SearchView"
|
||||||
|
/>
|
||||||
|
<item android:id="@+id/menu_search_advanced"
|
||||||
|
android:icon="@android:drawable/ic_menu_search"
|
||||||
|
android:title="@string/menu_search_advanced"
|
||||||
|
android:showAsAction="never"
|
||||||
/>
|
/>
|
||||||
<item android:id="@+id/menu_app_settings"
|
<item android:id="@+id/menu_app_settings"
|
||||||
android:icon="@android:drawable/ic_menu_preferences"
|
android:icon="@android:drawable/ic_menu_preferences"
|
||||||
|
@ -129,6 +129,7 @@
|
|||||||
<string name="menu_open">Open</string>
|
<string name="menu_open">Open</string>
|
||||||
<string name="menu_rename">Rename</string>
|
<string name="menu_rename">Rename</string>
|
||||||
<string name="menu_search">Search</string>
|
<string name="menu_search">Search</string>
|
||||||
|
<string name="menu_search_advanced">Advanced Search</string>
|
||||||
<string name="menu_url">Go to URL</string>
|
<string name="menu_url">Go to URL</string>
|
||||||
<string name="minus">Minus</string>
|
<string name="minus">Minus</string>
|
||||||
<string name="never">Never</string>
|
<string name="never">Never</string>
|
||||||
|
@ -21,4 +21,9 @@
|
|||||||
android:label="@string/search_label"
|
android:label="@string/search_label"
|
||||||
android:hint="@string/search_hint"
|
android:hint="@string/search_hint"
|
||||||
android:searchMode="showSearchLabelAsBadge"
|
android:searchMode="showSearchLabelAsBadge"
|
||||||
|
android:searchSuggestAuthority="keepass2android.search.SearchProvider"
|
||||||
|
android:searchSuggestSelection=" ?"
|
||||||
|
android:searchSuggestThreshold="2"
|
||||||
|
android:searchSuggestIntentAction="android.intent.action.VIEW"
|
||||||
|
android:searchSuggestIntentData="content://keepass2android.EntryActivity"
|
||||||
/>
|
/>
|
@ -53,7 +53,7 @@ namespace keepass2android
|
|||||||
|
|
||||||
public Drawable GetIconDrawable (Resources res, PwDatabase db, PwIcon icon, PwUuid customIconId)
|
public Drawable GetIconDrawable (Resources res, PwDatabase db, PwIcon icon, PwUuid customIconId)
|
||||||
{
|
{
|
||||||
if (customIconId != PwUuid.Zero) {
|
if (!customIconId.EqualsValue(PwUuid.Zero)) {
|
||||||
return GetIconDrawable (res, db, customIconId);
|
return GetIconDrawable (res, db, customIconId);
|
||||||
}
|
}
|
||||||
return GetIconDrawable (res, icon);
|
return GetIconDrawable (res, icon);
|
||||||
@ -85,7 +85,7 @@ namespace keepass2android
|
|||||||
public Drawable GetIconDrawable (Resources res, PwDatabase db, PwUuid icon)
|
public Drawable GetIconDrawable (Resources res, PwDatabase db, PwUuid icon)
|
||||||
{
|
{
|
||||||
InitBlank (res);
|
InitBlank (res);
|
||||||
if (icon == PwUuid.Zero) {
|
if (icon.EqualsValue(PwUuid.Zero)) {
|
||||||
return _blank;
|
return _blank;
|
||||||
}
|
}
|
||||||
Drawable draw;
|
Drawable draw;
|
||||||
|
@ -85,6 +85,7 @@
|
|||||||
<Compile Include="app\App.cs" />
|
<Compile Include="app\App.cs" />
|
||||||
<Compile Include="fileselect\FileSelectActivity.cs" />
|
<Compile Include="fileselect\FileSelectActivity.cs" />
|
||||||
<Compile Include="fileselect\FileDbHelper.cs" />
|
<Compile Include="fileselect\FileDbHelper.cs" />
|
||||||
|
<Compile Include="search\SearchProvider.cs" />
|
||||||
<Compile Include="Utils\Util.cs" />
|
<Compile Include="Utils\Util.cs" />
|
||||||
<Compile Include="intents\Intents.cs" />
|
<Compile Include="intents\Intents.cs" />
|
||||||
<Compile Include="fileselect\BrowserDialog.cs" />
|
<Compile Include="fileselect\BrowserDialog.cs" />
|
||||||
|
307
src/keepass2android/search/SearchProvider.cs
Normal file
307
src/keepass2android/search/SearchProvider.cs
Normal file
@ -0,0 +1,307 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file is based on Keepassdroid, Copyright Brian Pellin.
|
||||||
|
|
||||||
|
Keepass2Android 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.
|
||||||
|
|
||||||
|
Keepass2Android 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 Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using Android.App;
|
||||||
|
using Android.Content;
|
||||||
|
using Android.Content.Res;
|
||||||
|
using Android.Database;
|
||||||
|
using Android.Graphics;
|
||||||
|
using Android.Graphics.Drawables;
|
||||||
|
using Android.OS;
|
||||||
|
using Android.Runtime;
|
||||||
|
|
||||||
|
using KeePassLib;
|
||||||
|
using KeePassLib.Utility;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace keepass2android.search
|
||||||
|
{
|
||||||
|
[ContentProvider(new [] { SearchProvider.Authority })]
|
||||||
|
public class SearchProvider : ContentProvider
|
||||||
|
{
|
||||||
|
private enum UriMatches
|
||||||
|
{
|
||||||
|
NoMatch = UriMatcher.NoMatch,
|
||||||
|
GetIcon,
|
||||||
|
GetSuggestions
|
||||||
|
}
|
||||||
|
public const string Authority = "keepass2android.search.SearchProvider";
|
||||||
|
|
||||||
|
private const string GetIconPathQuery = "get_icon";
|
||||||
|
private const string IconIdParameter = "IconId";
|
||||||
|
private const string CustomIconUuidParameter = "CustomIconUuid";
|
||||||
|
|
||||||
|
private Database _db;
|
||||||
|
|
||||||
|
private static UriMatcher UriMatcher = BuildUriMatcher();
|
||||||
|
|
||||||
|
static UriMatcher BuildUriMatcher()
|
||||||
|
{
|
||||||
|
var matcher = new UriMatcher(UriMatcher.NoMatch);
|
||||||
|
|
||||||
|
// to get definitions...
|
||||||
|
matcher.AddURI(Authority, GetIconPathQuery, (int)UriMatches.GetIcon);
|
||||||
|
matcher.AddURI(Authority, SearchManager.SuggestUriPathQuery, (int)UriMatches.GetSuggestions);
|
||||||
|
|
||||||
|
return matcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool OnCreate()
|
||||||
|
{
|
||||||
|
_db = App.Kp2a.GetDb();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Android.Database.ICursor Query(Android.Net.Uri uri, string[] projection, string selection, string[] selectionArgs, string sortOrder)
|
||||||
|
{
|
||||||
|
if (_db.Open) // Can't show suggestions if the database is locked!
|
||||||
|
{
|
||||||
|
switch ((UriMatches)UriMatcher.Match(uri))
|
||||||
|
{
|
||||||
|
case UriMatches.GetSuggestions:
|
||||||
|
var searchString = selectionArgs[0];
|
||||||
|
if (!String.IsNullOrEmpty(searchString))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var resultsContexts = new Dictionary<PwUuid, String>();
|
||||||
|
var result = _db.Search(new SearchParameters { SearchString = searchString }, resultsContexts );
|
||||||
|
return new GroupCursor(result, resultsContexts);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine("Failed to search for suggestions: " + e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case UriMatches.GetIcon:
|
||||||
|
return null; // This will be handled by OpenAssetFile
|
||||||
|
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
//throw new ArgumentException("Unknown Uri: " + uri, "uri");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override ParcelFileDescriptor OpenFile(Android.Net.Uri uri, string mode)
|
||||||
|
{
|
||||||
|
switch ((UriMatches)UriMatcher.Match(uri))
|
||||||
|
{
|
||||||
|
case UriMatches.GetIcon:
|
||||||
|
var iconId = (PwIcon)Enum.Parse(typeof(PwIcon), uri.GetQueryParameter(IconIdParameter));
|
||||||
|
var customIconUuid = new PwUuid(MemUtil.HexStringToByteArray(uri.GetQueryParameter(CustomIconUuidParameter)));
|
||||||
|
|
||||||
|
var iconDrawable = _db.DrawableFactory.GetIconDrawable(App.Context.Resources, _db.KpDatabase, iconId, customIconUuid) as BitmapDrawable;
|
||||||
|
if (iconDrawable != null)
|
||||||
|
{
|
||||||
|
var pipe = ParcelFileDescriptor.CreatePipe();
|
||||||
|
var outStream = new OutputStreamInvoker(new ParcelFileDescriptor.AutoCloseOutputStream(pipe[1]));
|
||||||
|
|
||||||
|
ThreadPool.QueueUserWorkItem(state =>
|
||||||
|
{
|
||||||
|
iconDrawable.Bitmap.Compress(Bitmap.CompressFormat.Png, 100, outStream);
|
||||||
|
outStream.Close();
|
||||||
|
});
|
||||||
|
|
||||||
|
return pipe[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Couldn't get an icon for some reason.
|
||||||
|
return null;
|
||||||
|
default:
|
||||||
|
throw new ArgumentException("Unknown Uri: " + uri, "uri");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetType(Android.Net.Uri uri)
|
||||||
|
{
|
||||||
|
switch ((UriMatches)UriMatcher.Match(uri))
|
||||||
|
{
|
||||||
|
case UriMatches.GetSuggestions:
|
||||||
|
return SearchManager.SuggestMimeType;
|
||||||
|
case UriMatches.GetIcon:
|
||||||
|
return "image/png";
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new ArgumentException("Unknown Uri: " + uri, "uri");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Unimplemented
|
||||||
|
public override int Delete(Android.Net.Uri uri, string selection, string[] selectionArgs)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
public override Android.Net.Uri Insert(Android.Net.Uri uri, ContentValues values)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
public override int Update(Android.Net.Uri uri, ContentValues values, string selection, string[] selectionArgs)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
private class GroupCursor : AbstractCursor
|
||||||
|
{
|
||||||
|
private static readonly string[] ColumnNames = new[] { Android.Provider.BaseColumns.Id,
|
||||||
|
SearchManager.SuggestColumnText1,
|
||||||
|
SearchManager.SuggestColumnText2,
|
||||||
|
SearchManager.SuggestColumnIcon1,
|
||||||
|
SearchManager.SuggestColumnIntentDataId,
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly PwGroup mGroup;
|
||||||
|
private readonly IDictionary<PwUuid, String> mResultContexts;
|
||||||
|
|
||||||
|
public GroupCursor(PwGroup group, IDictionary<PwUuid, String> resultContexts)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.Assert(!group.Groups.Any(), "Expecting a flat list of groups");
|
||||||
|
|
||||||
|
mGroup = group;
|
||||||
|
mResultContexts = resultContexts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int Count
|
||||||
|
{
|
||||||
|
get { return (int)Math.Min(mGroup.GetEntriesCount(false), int.MaxValue); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string[] GetColumnNames()
|
||||||
|
{
|
||||||
|
return ColumnNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override FieldType GetType(int column)
|
||||||
|
{
|
||||||
|
switch (column)
|
||||||
|
{
|
||||||
|
case 0: // _ID
|
||||||
|
return FieldType.Integer;
|
||||||
|
default:
|
||||||
|
return base.GetType(column); // Ends up as string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private PwEntry CurrentEntry
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mGroup.Entries.GetAt((uint)MPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override long GetLong(int column)
|
||||||
|
{
|
||||||
|
switch (column)
|
||||||
|
{
|
||||||
|
case 0: // _ID
|
||||||
|
return MPos;
|
||||||
|
default:
|
||||||
|
throw new FormatException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetString(int column)
|
||||||
|
{
|
||||||
|
switch (column)
|
||||||
|
{
|
||||||
|
case 0: // _ID
|
||||||
|
return MPos.ToString();
|
||||||
|
case 1: // SuggestColumnText1
|
||||||
|
return CurrentEntry.Strings.ReadSafe(PwDefs.TitleField);
|
||||||
|
case 2: // SuggestColumnText2
|
||||||
|
string context;
|
||||||
|
if (mResultContexts.TryGetValue(CurrentEntry.Uuid, out context))
|
||||||
|
{
|
||||||
|
context = Internationalise(context);
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
case 3: // SuggestColumnIcon1
|
||||||
|
var builder = new Android.Net.Uri.Builder();
|
||||||
|
builder.Scheme(ContentResolver.SchemeContent);
|
||||||
|
builder.Authority(Authority);
|
||||||
|
builder.Path(GetIconPathQuery);
|
||||||
|
builder.AppendQueryParameter(IconIdParameter, CurrentEntry.IconId.ToString());
|
||||||
|
builder.AppendQueryParameter(CustomIconUuidParameter, CurrentEntry.CustomIconUuid.ToHexString());
|
||||||
|
return builder.Build().ToString();
|
||||||
|
case 4: // SuggestColumnIntentDataId
|
||||||
|
return CurrentEntry.Uuid.ToHexString();
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Internationalise(string context)
|
||||||
|
{
|
||||||
|
// Some context names can be internationalised.
|
||||||
|
var splitPos = context.IndexOf(':');
|
||||||
|
var rawName = context.Substring(0, splitPos);
|
||||||
|
int intlResourceId = 0;
|
||||||
|
switch (rawName)
|
||||||
|
{
|
||||||
|
case PwDefs.TitleField:
|
||||||
|
// We will already be showing Title, so ignore it entirely so it doesn't double-appear
|
||||||
|
return null;
|
||||||
|
case PwDefs.UserNameField:
|
||||||
|
intlResourceId = Resource.String.entry_user_name;
|
||||||
|
break;
|
||||||
|
case PwDefs.UrlField:
|
||||||
|
intlResourceId = Resource.String.entry_url;
|
||||||
|
break;
|
||||||
|
case PwDefs.NotesField:
|
||||||
|
intlResourceId = Resource.String.entry_comment;
|
||||||
|
break;
|
||||||
|
case PwGroup.SearchContextTags:
|
||||||
|
intlResourceId = Resource.String.entry_tags;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Other fields aren't part of the default SearchParameters, so we won't ever get them as context anyway
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (intlResourceId > 0)
|
||||||
|
{
|
||||||
|
return App.Context.GetString(intlResourceId) + context.Substring(splitPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool IsNull(int column)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Data types appearing in no columns
|
||||||
|
public override int GetInt(int column) { throw new FormatException(); }
|
||||||
|
public override double GetDouble(int column) { throw new FormatException(); }
|
||||||
|
public override float GetFloat(int column) { throw new FormatException(); }
|
||||||
|
public override short GetShort(int column) { throw new FormatException(); }
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -22,13 +22,14 @@ using Android.OS;
|
|||||||
using Android.Widget;
|
using Android.Widget;
|
||||||
using keepass2android.view;
|
using keepass2android.view;
|
||||||
using KeePassLib;
|
using KeePassLib;
|
||||||
|
using Android.Support.V4.App;
|
||||||
|
|
||||||
namespace keepass2android.search
|
namespace keepass2android.search
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Activity to show search results
|
/// Activity to show search results
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Activity (Label = "@string/app_name", Theme="@style/NoTitleBar")]
|
[Activity (Label = "@string/app_name", Theme="@style/NoTitleBar", LaunchMode=Android.Content.PM.LaunchMode.SingleTop)]
|
||||||
[MetaData("android.app.searchable",Resource="@xml/searchable")]
|
[MetaData("android.app.searchable",Resource="@xml/searchable")]
|
||||||
[IntentFilter(new[]{Intent.ActionSearch}, Categories=new[]{Intent.CategoryDefault})]
|
[IntentFilter(new[]{Intent.ActionSearch}, Categories=new[]{Intent.CategoryDefault})]
|
||||||
public class SearchResults : GroupBaseActivity
|
public class SearchResults : GroupBaseActivity
|
||||||
@ -45,23 +46,43 @@ namespace keepass2android.search
|
|||||||
|
|
||||||
SetResult(KeePass.ExitNormal);
|
SetResult(KeePass.ExitNormal);
|
||||||
|
|
||||||
|
ProcessIntent(Intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnNewIntent(Intent intent)
|
||||||
|
{
|
||||||
|
ProcessIntent(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessIntent(Intent intent)
|
||||||
|
{
|
||||||
_db = App.Kp2a.GetDb();
|
_db = App.Kp2a.GetDb();
|
||||||
|
|
||||||
|
|
||||||
// Likely the app has been killed exit the activity
|
// Likely the app has been killed exit the activity
|
||||||
if ( ! _db.Open ) {
|
if ( ! _db.Open ) {
|
||||||
Finish();
|
Finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
Query(getSearch(Intent));
|
if (intent.Action == Intent.ActionView)
|
||||||
|
{
|
||||||
|
var entryIntent = new Intent(this, typeof(EntryActivity));
|
||||||
|
entryIntent.PutExtra(EntryActivity.KeyEntry, intent.Data.LastPathSegment);
|
||||||
|
|
||||||
|
Finish(); // Close this activity so that the entry activity is navigated to from the main activity, not this one.
|
||||||
|
StartActivity(entryIntent);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Action may either by ActionSearch (from search widget) or null (if called from SearchActivity directly)
|
||||||
|
Query(getSearch(intent));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void Query (SearchParameters searchParams)
|
private void Query (SearchParameters searchParams)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
Group = _db.Search (searchParams);
|
Group = _db.Search (searchParams, null);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Toast.MakeText(this,e.Message, ToastLength.Long).Show();
|
Toast.MakeText(this,e.Message, ToastLength.Long).Show();
|
||||||
Finish();
|
Finish();
|
||||||
|
Loading…
Reference in New Issue
Block a user