2013-11-20 13:14:57 -05:00
|
|
|
using System.IO;
|
|
|
|
using System.Xml.Serialization;
|
|
|
|
using KeePassLib.Serialization;
|
|
|
|
using OtpKeyProv;
|
|
|
|
using keepass2android.Io;
|
|
|
|
|
|
|
|
namespace keepass2android.addons.OtpKeyProv
|
|
|
|
{
|
|
|
|
/// <summary>
|
|
|
|
/// Class which provides caching for OtpInfo-files. This is an extension to CachingFileStorage required to handle conflicts directly when loading.
|
|
|
|
/// </summary>
|
|
|
|
class OtpAuxCachingFileStorage: CachingFileStorage
|
|
|
|
{
|
|
|
|
private readonly IOtpAuxCacheSupervisor _cacheSupervisor;
|
|
|
|
|
|
|
|
internal interface IOtpAuxCacheSupervisor: ICacheSupervisor
|
|
|
|
{
|
|
|
|
/// <summary>
|
|
|
|
/// called when there was a conflict which was resolved by using the remote file.
|
|
|
|
/// </summary>
|
|
|
|
void ResolvedCacheConflictByUsingRemote(IOConnectionInfo ioc);
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// called when there was a conflict which was resolved by using the local file.
|
|
|
|
/// </summary>
|
|
|
|
void ResolvedCacheConflictByUsingLocal(IOConnectionInfo ioc);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public OtpAuxCachingFileStorage(IFileStorage cachedStorage, string cacheDir, IOtpAuxCacheSupervisor cacheSupervisor)
|
|
|
|
: base(cachedStorage, cacheDir, cacheSupervisor)
|
|
|
|
{
|
|
|
|
_cacheSupervisor = cacheSupervisor;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override Stream OpenFileForReadWithConflict(IOConnectionInfo ioc, string cachedFilePath)
|
|
|
|
{
|
|
|
|
OtpInfo remoteOtpInfo, localOtpInfo;
|
|
|
|
//load both files
|
2013-11-22 15:47:13 -05:00
|
|
|
XmlSerializer xs = new XmlSerializer(typeof(OtpInfo));
|
|
|
|
using (var cacheStream = File.OpenRead(cachedFilePath))
|
|
|
|
{
|
|
|
|
localOtpInfo = (OtpInfo) xs.Deserialize(cacheStream);
|
|
|
|
}
|
2013-11-20 13:14:57 -05:00
|
|
|
using (Stream remoteStream = _cachedStorage.OpenFileForRead(ioc))
|
|
|
|
{
|
2013-11-22 15:47:13 -05:00
|
|
|
remoteOtpInfo = (OtpInfo)xs.Deserialize(remoteStream);
|
2013-11-20 13:14:57 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
//see which OtpInfo has the bigger Counter value and use this one:
|
|
|
|
if (localOtpInfo.Counter > remoteOtpInfo.Counter)
|
|
|
|
{
|
|
|
|
//overwrite the remote file
|
|
|
|
UpdateRemoteFile(File.OpenRead(cachedFilePath),
|
|
|
|
ioc,
|
|
|
|
App.Kp2a.GetBooleanPreference(PreferenceKey.UseFileTransactions),
|
|
|
|
GetBaseVersionHash(ioc)
|
|
|
|
);
|
|
|
|
|
|
|
|
_cacheSupervisor.ResolvedCacheConflictByUsingRemote(ioc);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//overwrite the local file:
|
|
|
|
UpdateCacheFromRemote(ioc, cachedFilePath);
|
|
|
|
_cacheSupervisor.ResolvedCacheConflictByUsingLocal(ioc);
|
|
|
|
}
|
|
|
|
|
|
|
|
//now return the local file in any way:
|
|
|
|
return File.OpenRead(cachedFilePath);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|