- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
使用此代码,用户可以将我的数据库、共享首选项和其他内部应用程序数据压缩为备份文件。该文件如下所示:
用户还可以选择通过从文件管理器中选择 zip 文件来恢复备份文件。这是出现的“问题”:
虽然恢复有效,但我如何通过恢复一些不是由我的应用程序创建的“随机”zip 文件来阻止用户。
我的一些解决方案是:
最佳答案
首先,将检查文件(而不是数据库)header对于 Magic header 字符串。即它是否是一个有效的 SQLiteDatabase。
直接打开文件,读取前16个字节,必须是SQLite format 3\000
或53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00
十六进制。
其次,然后您可以检查应该与数据库版本匹配的 user_version(偏移量 60 为 4 个字节)(从而防止恢复过时的版本)。如果使用 SQLiteOpenHelper 访问数据库,则根据编译和生成分发时使用的版本号维护此值。
Adding some "hidden" META data which can't be seen or edited. (not sure if that is possible).
第三,您可以再次使用 header ,但这次应用程序 ID 位于偏移量 68(4 字节),这将不会被使用。这可以以与版本号类似的方式使用,但您必须实现它的维护(设置/更新)。
前两个要求很少,可以防止大多数意外情况。
第三个是应用程序 ID,可提供更多保护,防止使用具有有效版本号的有效 SQLite 数据库。
没有人可以防止故意滥用(为什么这样的 Intent 会受到质疑)。但是,它可能会导致异常。
如果前 3 个不足,那么您可以打开数据库并查询 sqlite_master 以查看模式是否符合预期。
或许考虑一下 Room 使用的元数据。
Room 根据@Entity 注释类预期的模式散列和存储在 room_master_table 中的数据库中的散列来执行模式检查。这等同于您的元数据方法。
例如编译 Room 项目时,在生成的 java 中它会有代码,在 createAllTables
方法中,如:-
_db.execSQL("CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)");
_db.execSQL("INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'c9583474ce546ff5ead43c63fe049bc8')");
现在,如果数据库不存在,则存储散列。如果数据库确实存在,那么它会检查存储在 room_master_table 中的散列是否匹配。如果不是,则如果编码了适当的迁移并且版本号已更改,则调用适当的迁移,然后如果模式与 has 存储匹配,否则会引发异常。如果散列不匹配并且没有适当的迁移,那么将引发异常(需要迁移)或者如果对 fallbackToDestrictiveMigration 进行编码,则数据库将从头开始创建。
因此房间数据库(按照上述)将包括:-
First 的替代方法是利用/覆盖 DatabaseErrorHandler's onCorruption方法。
这里有一个方法(虽然很冗长)使用这种技术并另外检查是否有任何表格(但不彻底):-
/**************************************************************************
*
* @return false if the backup file is invalid.
*
* determine by creating a differently name database (prefixed with IC),
* openeing it with it's own helper (does nothing) and then trying to
* check if there are tables in the database.
* No tables reflects that file is invalid type.
*
* Note! if an attempt to open an invalid database file then SQLite deletes the file.
*/
private boolean dataBaseIntegrityCheck() {
String methodname = new Object() {
}.getClass().getEnclosingMethod().getName();
LogMsg.LogMsg(LogMsg.LOGTYPE_INFORMATIONAL, LOGTAG, "Invoked", this, methodname);
@SuppressWarnings("UnusedAssignment") final String THIS_METHOD = "dataBaseIntegrityCheck";
//String sqlstr_mstr = "SELECT name FROM sqlite_master WHERE type = 'table' AND name!='android_metadata' ORDER by name;";
Cursor iccsr;
boolean rv = true;
//Note no use having the handler as it actually introduces problems as SQLite assumes that
// the handler will restore the database.
// No need to comment out as handler can be disabled by not not passing it as a parameter
// of the DBHelper
@SuppressWarnings("UnusedAssignment") DatabaseErrorHandler myerrorhandler = new DatabaseErrorHandler() {
@Override
public void onCorruption(SQLiteDatabase sqLiteDatabase) {
}
};
try {
FileInputStream bkp = new FileInputStream(backupfilename);
OutputStream ic = new FileOutputStream(icdbfilename);
while ((copylength = bkp.read(buffer)) > 0) {
ic.write(buffer, 0, copylength);
}
ic.close();
bkp.close();
icfile = new File(icdbfilename);
//Note SQLite will actually check for corruption and if so delete the file
//
IntegrityCheckDBHelper icdbh = new IntegrityCheckDBHelper(this, null, null, 1, null);
SQLiteDatabase icdb = icdbh.getReadableDatabase();
iccsr = icdb.query("sqlite_master",
new String[]{"name"},
"type=? AND name!=?",
new String[]{"table", "android_metadata"},
null, null,
"name"
);
//Check to see if there are any tables, if wrong file type shouldn't be any
//iccsr = icdb.rawQuery(sqlstr_mstr,null);
if (iccsr.getCount() < 1) {
errlist.add("Integrity Check extract from sqlite_master returned nothing - Propsoed file is corrupt or not a database file.");
rv = false;
}
iccsr.close();
icdb.close();
} catch (IOException e) {
e.printStackTrace();
errlist.add("Integrity Check Failed Error Message was " + e.getMessage());
}
if (!rv) {
AlertDialog.Builder notokdialog = new AlertDialog.Builder(this);
notokdialog.setTitle("Invalid Restore File.");
notokdialog.setCancelable(true);
String msg = "File " + backupfilename + " is an invalid file." +
"\n\nThe Restore cannot continue and will be canclled. " +
"\n\nPlease Use a Valid Database Backup File!";
notokdialog.setMessage(msg);
notokdialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
}).show();
}
// Delete the Integrity Check File (Database copy)
//noinspection ResultOfMethodCallIgnored
icfile.delete();
return rv;
}
关于android - 验证备份 ZIP 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71643038/
我有这个命令: 7z e -oD:\Data\ODS_Source\* D:\Data\DATA_DROP\Source.zip 这导致 D:\Data\ODS_Source\Source\. 我需要
我正在尝试让 Ionic zip 将 zip 文件内的文件夹提取到指定的根目录中。我的问题是里面的zip文件是“zipfile.zip\some_folder\”。我想将“some_folder”中的
我试图让 Ionic zip 将 zip 文件中的文件夹提取到指定的根目录中。我的问题是里面的 zip 文件是“zipfile.zip\some_folder\”。我想将“some_folder”中的
题目 监听服务器端口,得到题目如下: 源码解析 主函数 主函数中是题目界面的逻辑,对应于用户的选择做出相应的操作,其中需要注意的是选项2,解压操作需要获得root权
我有许多需要分发给用户的zip文件,其中约有130个。每个zip文件都包含许多相似的文本,html,xml和jpg文件。压缩文件总计146兆字节;解压缩后,其内容总计551mb。 我想将所有这些文件以
我正在使用 javascript zip.js图书馆。我到处搜索,但找不到将多个文件添加到 zip 的示例。 这是我的代码,但它生成了一个“损坏的”zip。 var len = results.row
在 C# 中,我使用的是 DotNetZip我有一个名为“innerZip.zip”的 zip,其中包含一些数据,和另一个名为“outerZip.zip”的 zip,其中包含 innerZip。我为什
当我使用 library(xlsx) 中的 write.xlsx 时,控制台中会出现以下内容: Note: zip::zip() is deprecated, please use zip::zipr
如果我因为问“非编程”问题而被拒绝,我不会太惊讶,但也许有人知道...... 我正在使用 WinXP 的内置“发送到压缩(zipped)文件夹”功能压缩我的 subversion 沙箱的内容,并惊讶地
我在 Elixir 中有一个二进制字符串,它由压缩字节组成,我想放气并从中提取“真实数据”: iex(93)> data > 我不确定如何解压缩这些数据。到目前为止,我已经: 浏览了 Official
有没有一种方法可以创建一个 zip 文件并强制它在命令行中包含数据描述符部分? 最佳答案 在 Github ( https://github.com/adamhathcock/sharpcompres
我已经有 PBDT.csj and RDK.csj使用此 ( https://www.blackberry.com/SignedKeys/codesigning.html ) 链接进行代码签名处理后的
我研究了几天,发现我们可以将一个包含一些内容的文件添加到 zip 文件中,然后再次压缩它。然后注释将被添加到 zip 文件中,但我不知道该文件到底是什么,所以任何人都知道向 zip(压缩)文件添加注释
我想知道如何找到 zip 文件的压缩级别。 7z 和 winzip 制作的 Zip 文件具有不同的级别评级,因此我想将其中的一些映射到其他工具中的相应级别。 store level 或 level 0
到目前为止,对于Zip文件的Mime类型,我已经看到: 应用程序/八位字节流 multipart / x-zip 应用程序/ zip 应用程序/ zip压缩的 应用程序/ x-zip压缩的 我想我的问
我已经在 google 上搜索、在 wiki 上搜索并阅读了 ZIP 的 RFC,但找不到有关 ZIP 中使用的确切算法的任何信息。 我找到了有关 ZIP == TAR + GZIP 的信息 但是,我
我有这些自解压 zip 文件,我正试图在 2008/7 机器上远程解压这些文件。但它们是以 .exe 的方式出现的,它需要用户双击并选择提取位置。 在 WinZip 支持网站上,他们说要使用/auto
这是我在这里的第一个问题,请耐心等待。 我的目标是在 C# 中创建一个基本的 .zip 存档。我已经尝试使用 .NET 的内置 GZipStream 类并设法实现了这一点,但是我遇到了一个问题,我无法
能否为压缩文件中的压缩文件创建 java.nio.file.FileSystem? 如果是这样,URI 是什么样的? 如果没有,我想我将不得不退回到使用 ZipInputStream。 我正在尝试递归
我想在 here 安装 scala我很关心下载哪一个:zip 还是 tgz。它们之间有什么区别,用例是什么? 最佳答案 它们是不同的archive formats .使用它们是因为它可以节省带宽并且因
我是一名优秀的程序员,十分优秀!