mirror of
https://github.com/revanced/ARSCLib.git
synced 2025-05-06 00:34:27 +02:00
create namespace validator
This commit is contained in:
parent
2b9a65df73
commit
caa721b90f
@ -17,6 +17,7 @@ package com.reandroid.lib.apk;
|
|||||||
|
|
||||||
import com.reandroid.archive.InputSource;
|
import com.reandroid.archive.InputSource;
|
||||||
import com.reandroid.lib.apk.xmldecoder.XMLBagDecoder;
|
import com.reandroid.lib.apk.xmldecoder.XMLBagDecoder;
|
||||||
|
import com.reandroid.lib.apk.xmldecoder.XMLNamespaceValidator;
|
||||||
import com.reandroid.lib.arsc.chunk.PackageBlock;
|
import com.reandroid.lib.arsc.chunk.PackageBlock;
|
||||||
import com.reandroid.lib.arsc.chunk.TableBlock;
|
import com.reandroid.lib.arsc.chunk.TableBlock;
|
||||||
import com.reandroid.lib.arsc.chunk.TypeBlock;
|
import com.reandroid.lib.arsc.chunk.TypeBlock;
|
||||||
@ -117,6 +118,8 @@ import java.util.*;
|
|||||||
File file=new File(resDir, path);
|
File file=new File(resDir, path);
|
||||||
|
|
||||||
logVerbose("Decoding: "+path);
|
logVerbose("Decoding: "+path);
|
||||||
|
XMLNamespaceValidator namespaceValidator=new XMLNamespaceValidator(resXmlBlock);
|
||||||
|
namespaceValidator.validate();
|
||||||
XMLDocument xmlDocument=resXmlBlock.decodeToXml(entryStore, packageBlock.getId());
|
XMLDocument xmlDocument=resXmlBlock.decodeToXml(entryStore, packageBlock.getId());
|
||||||
xmlDocument.save(file, true);
|
xmlDocument.save(file, true);
|
||||||
|
|
||||||
|
@ -0,0 +1,139 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 github.com/REAndroid
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.reandroid.lib.apk.xmldecoder;
|
||||||
|
|
||||||
|
import com.reandroid.lib.arsc.chunk.xml.*;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class XMLNamespaceValidator {
|
||||||
|
private static final String URI_ANDROID="http://schemas.android.com/apk/res/android";
|
||||||
|
private static final String URI_APP="http://schemas.android.com/apk/res-auto";
|
||||||
|
private static final String PREFIX_ANDROID ="android";
|
||||||
|
private static final String PREFIX_APP="app";
|
||||||
|
private final ResXmlBlock xmlBlock;
|
||||||
|
private List<ResXmlAttribute> mAttributeList;
|
||||||
|
private ResXmlElement mRootElement;
|
||||||
|
private ResXmlStartNamespace mNsAndroid;
|
||||||
|
private ResXmlStartNamespace mNsApp;
|
||||||
|
public XMLNamespaceValidator(ResXmlBlock xmlBlock){
|
||||||
|
this.xmlBlock=xmlBlock;
|
||||||
|
}
|
||||||
|
public void validate(){
|
||||||
|
if(getRootElement()==null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for(ResXmlAttribute attribute:getAttributes()){
|
||||||
|
validate(attribute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void validate(ResXmlAttribute attribute){
|
||||||
|
int resourceId=attribute.getNameResourceID();
|
||||||
|
if(resourceId==0){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int pkgId=toPackageId(resourceId);
|
||||||
|
if(isAndroid(pkgId)){
|
||||||
|
setAndroidNamespace(attribute);
|
||||||
|
}else {
|
||||||
|
setAppNamespace(attribute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void setAppNamespace(ResXmlAttribute attribute){
|
||||||
|
if(isValidAppNamespace(attribute)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ResXmlStartNamespace ns = getOrCreateApp();
|
||||||
|
attribute.setNamespaceReference(ns.getUriReference());
|
||||||
|
}
|
||||||
|
private boolean isValidAppNamespace(ResXmlAttribute attribute){
|
||||||
|
String uri = attribute.getUri();
|
||||||
|
String prefix = attribute.getNamePrefix();
|
||||||
|
if(URI_ANDROID.equals(uri) || PREFIX_ANDROID.equals(prefix)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(isEmpty(uri) || isEmpty(prefix)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
private void setAndroidNamespace(ResXmlAttribute attribute){
|
||||||
|
if(URI_ANDROID.equals(attribute.getUri())
|
||||||
|
&& PREFIX_ANDROID.equals(attribute.getNamePrefix())){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ResXmlStartNamespace ns = getOrCreateAndroid();
|
||||||
|
attribute.setNamespaceReference(ns.getUriReference());
|
||||||
|
}
|
||||||
|
private ResXmlStartNamespace getOrCreateApp(){
|
||||||
|
if(mNsApp !=null){
|
||||||
|
return mNsApp;
|
||||||
|
}
|
||||||
|
ResXmlElement root=getRootElement();
|
||||||
|
ResXmlStartNamespace ns = root.getOrCreateNamespace(URI_APP, PREFIX_APP);
|
||||||
|
String prefix=ns.getPrefix();
|
||||||
|
if(PREFIX_ANDROID.equals(prefix) || isEmpty(prefix)){
|
||||||
|
ns.setPrefix(PREFIX_APP);
|
||||||
|
}
|
||||||
|
mNsApp = ns;
|
||||||
|
return mNsApp;
|
||||||
|
}
|
||||||
|
private ResXmlStartNamespace getOrCreateAndroid(){
|
||||||
|
if(mNsAndroid !=null){
|
||||||
|
return mNsAndroid;
|
||||||
|
}
|
||||||
|
ResXmlElement root=getRootElement();
|
||||||
|
ResXmlStartNamespace ns = root.getOrCreateNamespace(URI_ANDROID, PREFIX_ANDROID);
|
||||||
|
if(!PREFIX_ANDROID.equals(ns.getPrefix())){
|
||||||
|
ns.setPrefix(PREFIX_ANDROID);
|
||||||
|
}
|
||||||
|
mNsAndroid =ns;
|
||||||
|
return mNsAndroid;
|
||||||
|
}
|
||||||
|
private ResXmlElement getRootElement() {
|
||||||
|
if(mRootElement==null){
|
||||||
|
mRootElement = xmlBlock.getResXmlElement();
|
||||||
|
}
|
||||||
|
return mRootElement;
|
||||||
|
}
|
||||||
|
private List<ResXmlAttribute> getAttributes(){
|
||||||
|
if(mAttributeList==null){
|
||||||
|
mAttributeList=listAttributes(xmlBlock.getResXmlElement());
|
||||||
|
}
|
||||||
|
return mAttributeList;
|
||||||
|
}
|
||||||
|
private List<ResXmlAttribute> listAttributes(ResXmlElement element){
|
||||||
|
List<ResXmlAttribute> results = new ArrayList<>(element.listAttributes());
|
||||||
|
for(ResXmlElement child:element.listElements()){
|
||||||
|
results.addAll(listAttributes(child));
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
private boolean isAndroid(int pkgId){
|
||||||
|
return pkgId==1;
|
||||||
|
}
|
||||||
|
private int toPackageId(int resId){
|
||||||
|
return (resId >> 24 & 0xFF);
|
||||||
|
}
|
||||||
|
private static boolean isEmpty(String str){
|
||||||
|
if(str==null){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
str=str.trim();
|
||||||
|
return str.length()==0;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user