Support SMTP URLs
[zxing.git] / core / src / com / google / zxing / client / result / URIParsedResult.java
1 /*
2  * Copyright 2007 ZXing authors
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 package com.google.zxing.client.result;
18
19 /**
20  * @author Sean Owen
21  */
22 public final class URIParsedResult extends ParsedResult {
23
24   private final String uri;
25   private final String title;
26
27   public URIParsedResult(String uri, String title) {
28     super(ParsedResultType.URI);
29     this.uri = massageURI(uri);
30     this.title = title;
31   }
32
33   public String getURI() {
34     return uri;
35   }
36
37   public String getTitle() {
38     return title;
39   }
40
41   /**
42    * @return true if the URI contains suspicious patterns that may suggest it intends to
43    *  mislead the user about its true nature. At the moment this looks for the presence
44    *  of user/password syntax in the host/authority portion of a URI which may be used
45    *  in attempts to make the URI's host appear to be other than it is. Example:
46    *  http://yourbank.com@phisher.com  This URI connects to phisher.com but may appear
47    *  to connect to yourbank.com at first glance.
48    */
49   public boolean isPossiblyMaliciousURI() {
50     return containsUser();
51   }
52
53   private boolean containsUser() {
54     // This method is likely not 100% RFC compliant yet
55     int hostStart = uri.indexOf(':'); // we should always have scheme at this point
56     hostStart++;
57     // Skip slashes preceding host
58     int uriLength = uri.length();
59     while (hostStart < uriLength && uri.charAt(hostStart) == '/') {
60       hostStart++;
61     }
62     int hostEnd = uri.indexOf('/', hostStart);
63     if (hostEnd < 0) {
64       hostEnd = uriLength;
65     }
66     int at = uri.indexOf('@', hostStart);
67     return at >= hostStart && at < hostEnd;
68   }
69
70   public String getDisplayResult() {
71     StringBuffer result = new StringBuffer(30);
72     maybeAppend(title, result);
73     maybeAppend(uri, result);
74     return result.toString();
75   }
76
77   /**
78    * Transforms a string that represents a URI into something more proper, by adding or canonicalizing
79    * the protocol.
80    */
81   private static String massageURI(String uri) {
82     int protocolEnd = uri.indexOf(':');
83     if (protocolEnd < 0) {
84       // No protocol, assume http
85       uri = "http://" + uri;
86     } else if (isColonFollowedByPortNumber(uri, protocolEnd)) {
87       // Found a colon, but it looks like it is after the host, so the protocol is still missing
88       uri = "http://" + uri;
89     } else {
90       // Lowercase protocol to avoid problems
91       uri = uri.substring(0, protocolEnd).toLowerCase() + uri.substring(protocolEnd);
92     }
93     return uri;
94   }
95
96   private static boolean isColonFollowedByPortNumber(String uri, int protocolEnd) {
97     int nextSlash = uri.indexOf('/', protocolEnd + 1);
98     if (nextSlash < 0) {
99       nextSlash = uri.length();
100     }
101     if (nextSlash <= protocolEnd + 1) {
102       return false;
103     }
104     for (int x = protocolEnd + 1; x < nextSlash; x++) {
105       if (uri.charAt(x) < '0' || uri.charAt(x) > '9') {
106         return false;
107       }
108     }
109     return true;
110   }
111
112
113 }