2 * Copyright (C) 2013 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com
.android
.server
.firewall
;
19 import android
.content
.ComponentName
;
20 import android
.content
.Intent
;
21 import android
.net
.Uri
;
22 import android
.os
.PatternMatcher
;
23 import org
.xmlpull
.v1
.XmlPullParser
;
24 import org
.xmlpull
.v1
.XmlPullParserException
;
26 import java
.io
.IOException
;
27 import java
.util
.regex
.Pattern
;
29 abstract class StringFilter
implements Filter
{
30 private static final String ATTR_EQUALS
= "equals";
31 private static final String ATTR_STARTS_WITH
= "startsWith";
32 private static final String ATTR_CONTAINS
= "contains";
33 private static final String ATTR_PATTERN
= "pattern";
34 private static final String ATTR_REGEX
= "regex";
35 private static final String ATTR_IS_NULL
= "isNull";
37 private final ValueProvider mValueProvider
;
39 private StringFilter(ValueProvider valueProvider
) {
40 this.mValueProvider
= valueProvider
;
44 * Constructs a new StringFilter based on the string filter attribute on the current
45 * element, and the given StringValueMatcher.
47 * The current node should contain exactly 1 string filter attribute. E.g. equals,
48 * contains, etc. Otherwise, an XmlPullParserException will be thrown.
50 * @param parser An XmlPullParser object positioned at an element that should
51 * contain a string filter attribute
52 * @return This StringFilter object
54 public static StringFilter
readFromXml(ValueProvider valueProvider
, XmlPullParser parser
)
55 throws IOException
, XmlPullParserException
{
56 StringFilter filter
= null;
58 for (int i
=0; i
<parser
.getAttributeCount(); i
++) {
59 StringFilter newFilter
= getFilter(valueProvider
, parser
, i
);
60 if (newFilter
!= null) {
62 throw new XmlPullParserException("Multiple string filter attributes found");
69 // if there are no string filter attributes, we default to isNull="false" so that an
70 // empty filter is equivalent to an existence check
71 filter
= new IsNullFilter(valueProvider
, false);
77 private static StringFilter
getFilter(ValueProvider valueProvider
, XmlPullParser parser
,
79 String attributeName
= parser
.getAttributeName(attributeIndex
);
81 switch (attributeName
.charAt(0)) {
83 if (!attributeName
.equals(ATTR_EQUALS
)) {
86 return new EqualsFilter(valueProvider
, parser
.getAttributeValue(attributeIndex
));
88 if (!attributeName
.equals(ATTR_IS_NULL
)) {
91 return new IsNullFilter(valueProvider
, parser
.getAttributeValue(attributeIndex
));
93 if (!attributeName
.equals(ATTR_STARTS_WITH
)) {
96 return new StartsWithFilter(valueProvider
,
97 parser
.getAttributeValue(attributeIndex
));
99 if (!attributeName
.equals(ATTR_CONTAINS
)) {
102 return new ContainsFilter(valueProvider
, parser
.getAttributeValue(attributeIndex
));
104 if (!attributeName
.equals(ATTR_PATTERN
)) {
107 return new PatternStringFilter(valueProvider
,
108 parser
.getAttributeValue(attributeIndex
));
110 if (!attributeName
.equals(ATTR_REGEX
)) {
113 return new RegexFilter(valueProvider
, parser
.getAttributeValue(attributeIndex
));
118 protected abstract boolean matchesValue(String value
);
121 public boolean matches(IntentFirewall ifw
, ComponentName resolvedComponent
, Intent intent
,
122 int callerUid
, int callerPid
, String resolvedType
, int receivingUid
) {
123 String value
= mValueProvider
.getValue(resolvedComponent
, intent
, resolvedType
);
124 return matchesValue(value
);
127 private static abstract class ValueProvider
extends FilterFactory
{
128 protected ValueProvider(String tag
) {
132 public Filter
newFilter(XmlPullParser parser
)
133 throws IOException
, XmlPullParserException
{
134 return StringFilter
.readFromXml(this, parser
);
137 public abstract String
getValue(ComponentName resolvedComponent
, Intent intent
,
138 String resolvedType
);
141 private static class EqualsFilter
extends StringFilter
{
142 private final String mFilterValue
;
144 public EqualsFilter(ValueProvider valueProvider
, String attrValue
) {
145 super(valueProvider
);
146 mFilterValue
= attrValue
;
150 public boolean matchesValue(String value
) {
151 return value
!= null && value
.equals(mFilterValue
);
155 private static class ContainsFilter
extends StringFilter
{
156 private final String mFilterValue
;
158 public ContainsFilter(ValueProvider valueProvider
, String attrValue
) {
159 super(valueProvider
);
160 mFilterValue
= attrValue
;
164 public boolean matchesValue(String value
) {
165 return value
!= null && value
.contains(mFilterValue
);
169 private static class StartsWithFilter
extends StringFilter
{
170 private final String mFilterValue
;
172 public StartsWithFilter(ValueProvider valueProvider
, String attrValue
) {
173 super(valueProvider
);
174 mFilterValue
= attrValue
;
178 public boolean matchesValue(String value
) {
179 return value
!= null && value
.startsWith(mFilterValue
);
183 private static class PatternStringFilter
extends StringFilter
{
184 private final PatternMatcher mPattern
;
186 public PatternStringFilter(ValueProvider valueProvider
, String attrValue
) {
187 super(valueProvider
);
188 mPattern
= new PatternMatcher(attrValue
, PatternMatcher
.PATTERN_SIMPLE_GLOB
);
192 public boolean matchesValue(String value
) {
193 return value
!= null && mPattern
.match(value
);
197 private static class RegexFilter
extends StringFilter
{
198 private final Pattern mPattern
;
200 public RegexFilter(ValueProvider valueProvider
, String attrValue
) {
201 super(valueProvider
);
202 this.mPattern
= Pattern
.compile(attrValue
);
206 public boolean matchesValue(String value
) {
207 return value
!= null && mPattern
.matcher(value
).matches();
211 private static class IsNullFilter
extends StringFilter
{
212 private final boolean mIsNull
;
214 public IsNullFilter(ValueProvider valueProvider
, String attrValue
) {
215 super(valueProvider
);
216 mIsNull
= Boolean
.parseBoolean(attrValue
);
219 public IsNullFilter(ValueProvider valueProvider
, boolean isNull
) {
220 super(valueProvider
);
225 public boolean matchesValue(String value
) {
226 return (value
== null) == mIsNull
;
230 public static final ValueProvider COMPONENT
= new ValueProvider("component") {
232 public String
getValue(ComponentName resolvedComponent
, Intent intent
,
233 String resolvedType
) {
234 if (resolvedComponent
!= null) {
235 return resolvedComponent
.flattenToString();
241 public static final ValueProvider COMPONENT_NAME
= new ValueProvider("component-name") {
243 public String
getValue(ComponentName resolvedComponent
, Intent intent
,
244 String resolvedType
) {
245 if (resolvedComponent
!= null) {
246 return resolvedComponent
.getClassName();
252 public static final ValueProvider COMPONENT_PACKAGE
= new ValueProvider("component-package") {
254 public String
getValue(ComponentName resolvedComponent
, Intent intent
,
255 String resolvedType
) {
256 if (resolvedComponent
!= null) {
257 return resolvedComponent
.getPackageName();
263 public static final FilterFactory ACTION
= new ValueProvider("action") {
265 public String
getValue(ComponentName resolvedComponent
, Intent intent
,
266 String resolvedType
) {
267 return intent
.getAction();
271 public static final ValueProvider DATA
= new ValueProvider("data") {
273 public String
getValue(ComponentName resolvedComponent
, Intent intent
,
274 String resolvedType
) {
275 Uri data
= intent
.getData();
277 return data
.toString();
283 public static final ValueProvider MIME_TYPE
= new ValueProvider("mime-type") {
285 public String
getValue(ComponentName resolvedComponent
, Intent intent
,
286 String resolvedType
) {
291 public static final ValueProvider SCHEME
= new ValueProvider("scheme") {
293 public String
getValue(ComponentName resolvedComponent
, Intent intent
,
294 String resolvedType
) {
295 Uri data
= intent
.getData();
297 return data
.getScheme();
303 public static final ValueProvider SSP
= new ValueProvider("scheme-specific-part") {
305 public String
getValue(ComponentName resolvedComponent
, Intent intent
,
306 String resolvedType
) {
307 Uri data
= intent
.getData();
309 return data
.getSchemeSpecificPart();
315 public static final ValueProvider HOST
= new ValueProvider("host") {
317 public String
getValue(ComponentName resolvedComponent
, Intent intent
,
318 String resolvedType
) {
319 Uri data
= intent
.getData();
321 return data
.getHost();
327 public static final ValueProvider PATH
= new ValueProvider("path") {
329 public String
getValue(ComponentName resolvedComponent
, Intent intent
,
330 String resolvedType
) {
331 Uri data
= intent
.getData();
333 return data
.getPath();