fix additional_repos.xml handling to be properly parsed

additional_repos.xml has 7 <item> elements per repo, while default_repos.xml
has 8.  The difference is that additional_repos.xml does not have the
"priority" <item> since it is not allowed to override anything that is set
in default_repos.xml.

see spec in !705
This commit is contained in:
Hans-Christoph Steiner 2018-10-16 17:08:32 +02:00
parent 7eb53518aa
commit b9b7dab2c4

View File

@ -42,17 +42,18 @@ import org.fdroid.fdroid.data.Schema.CatJoinTable;
import org.fdroid.fdroid.data.Schema.InstalledAppTable; import org.fdroid.fdroid.data.Schema.InstalledAppTable;
import org.fdroid.fdroid.data.Schema.PackageTable; import org.fdroid.fdroid.data.Schema.PackageTable;
import org.fdroid.fdroid.data.Schema.RepoTable; import org.fdroid.fdroid.data.Schema.RepoTable;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.File;
import java.io.IOException;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
import org.xmlpull.v1.XmlPullParserException;
/** /**
* This is basically a singleton used to represent the database at the core * This is basically a singleton used to represent the database at the core
@ -282,8 +283,11 @@ public class DBHelper extends SQLiteOpenHelper {
} }
/** /**
* Load additional repos first, then internal repos. This way, internal repos will be shown after the OEM-added * Load additional repos first, then internal repos. This way, internal
* ones on the Manage Repos screen. * repos will be shown after the OEM-added ones on the Manage Repos
* screen. This throws a hard {@code Exception} on parse errors since
* this file is built into the APK. So it should fail as hard and fast
* as possible so the developer catches the problem.
*/ */
public static List<String> loadDefaultRepos(Context context) throws IllegalArgumentException { public static List<String> loadDefaultRepos(Context context) throws IllegalArgumentException {
String packageName = context.getPackageName(); String packageName = context.getPackageName();
@ -292,8 +296,8 @@ public class DBHelper extends SQLiteOpenHelper {
defaultRepos.addAll(internalRepos); defaultRepos.addAll(internalRepos);
if (defaultRepos.size() % REPO_XML_ARG_COUNT != 0) { if (defaultRepos.size() % REPO_XML_ARG_COUNT != 0) {
throw new IllegalArgumentException( throw new IllegalArgumentException("default_repos.xml has wrong item count: " +
"At least one of the internally or externally loaded default repos does not have " + REPO_XML_ARG_COUNT + " entries."); defaultRepos.size() + " % REPO_XML_ARG_COUNT(" + REPO_XML_ARG_COUNT + ") != 0");
} }
return defaultRepos; return defaultRepos;
@ -311,24 +315,16 @@ public class DBHelper extends SQLiteOpenHelper {
private static List<String> loadAdditionalRepos(String packageName) { private static List<String> loadAdditionalRepos(String packageName) {
List<String> externalRepos = new LinkedList<>(); List<String> externalRepos = new LinkedList<>();
for (String root : Arrays.asList("/system", "/vendor", "/odm", "/oem")) { for (String root : Arrays.asList("/system", "/vendor", "/odm", "/oem")) {
String additionalReposPath = root + "/etc/" + packageName + "/additional_repos.xml"; File defaultReposFile = new File(root + "/etc/" + packageName + "/additional_repos.xml");
try { try {
File defaultReposFile = new File(additionalReposPath); if (defaultReposFile.isFile()) {
if (defaultReposFile.exists() && defaultReposFile.isFile()) {
externalRepos.addAll(DBHelper.parseXmlRepos(defaultReposFile)); externalRepos.addAll(DBHelper.parseXmlRepos(defaultReposFile));
} }
} catch (Exception e) { } catch (Exception e) {
Utils.debugLog(TAG, "Error loading " + additionalReposPath); Log.e(TAG, "Error loading " + defaultReposFile + ": " + e.getMessage());
Utils.debugLog(TAG, "Exception: " + e.getMessage());
continue;
} }
} }
final int PRIORITY_INDEX = 5;
for (int i = PRIORITY_INDEX; i < externalRepos.size(); i += REPO_XML_ARG_COUNT) {
externalRepos.add(i, "0");
}
return externalRepos; return externalRepos;
} }
@ -342,8 +338,7 @@ public class DBHelper extends SQLiteOpenHelper {
*/ */
public static List<String> parseXmlRepos(File defaultReposFile) throws IOException, XmlPullParserException { public static List<String> parseXmlRepos(File defaultReposFile) throws IOException, XmlPullParserException {
List<String> defaultRepos = new LinkedList<>(); List<String> defaultRepos = new LinkedList<>();
InputStream xmlInputStream = null; InputStream xmlInputStream = new FileInputStream(additionalReposFile);
xmlInputStream = new FileInputStream(defaultReposFile);
XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true); factory.setNamespaceAware(true);
XmlPullParser parser = factory.newPullParser(); XmlPullParser parser = factory.newPullParser();
@ -364,15 +359,26 @@ public class DBHelper extends SQLiteOpenHelper {
break; break;
case XmlPullParser.TEXT: case XmlPullParser.TEXT:
if (isItem) { if (isItem) {
defaultRepos.add(new String(parser.getText())); // This is a piece of real information in the xml file defaultRepos.add(parser.getText());
} }
break; break;
} }
eventType = parser.next(); eventType = parser.next();
} }
xmlInputStream.close(); xmlInputStream.close();
return defaultRepos;
final int PRIORITY_INDEX = 5;
for (int i = PRIORITY_INDEX; i < defaultRepos.size(); i += REPO_XML_ARG_COUNT) {
defaultRepos.add(i, "0");
}
if (defaultRepos.size() % REPO_XML_ARG_COUNT == 0) {
return defaultRepos;
}
Log.e(TAG, "Ignoring " + additionalReposFile + ", wrong number of items: "
+ defaultRepos.size() + " % " + (REPO_XML_ARG_COUNT - 1) + " != 0");
return new LinkedList<>();
} }
@Override @Override