1 /*
2  * Copyright (C) 2018 The Android Open Source Project
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.android.settings.wifi.dpp;
18 
19 import android.annotation.NonNull;
20 import android.net.wifi.UriParserResults;
21 import android.net.wifi.WifiConfiguration;
22 import android.net.wifi.WifiUriParser;
23 import android.text.TextUtils;
24 import android.util.Log;
25 
26 /**
27  * Supports to parse 2 types of QR code
28  *
29  *     1. Standard Wi-Fi DPP bootstrapping information or
30  *     2. ZXing reader library's Wi-Fi Network config format described in
31  *     https://github.com/zxing/zxing/wiki/Barcode-Contents#wi-fi-network-config-android-ios-11
32  *
33  * ZXing reader library's Wi-Fi Network config format example:
34  *
35  *     WIFI:T:WPA;S:mynetwork;P:mypass;;
36  *
37  * parameter Example    Description
38  * T         WPA        Authentication type; can be WEP or WPA, or 'nopass' for no password. Or,
39  *                      omit for no password.
40  * S         mynetwork  Network SSID. Required. Enclose in double quotes if it is an ASCII name,
41  *                      but could be interpreted as hex (i.e. "ABCD")
42  * P         mypass     Password, ignored if T is "nopass" (in which case it may be omitted).
43  *                      Enclose in double quotes if it is an ASCII name, but could be interpreted as
44  *                      hex (i.e. "ABCD")
45  * H         true       Optional. True if the network SSID is hidden.
46  *
47  */
48 public class WifiQrCode {
49     static final String SCHEME_DPP = "DPP";
50     static final String SCHEME_ZXING_WIFI_NETWORK_CONFIG = "WIFI";
51     static final String PREFIX_DPP = "DPP:";
52     static final String PREFIX_ZXING_WIFI_NETWORK_CONFIG = "WIFI:";
53 
54     static final String PREFIX_DPP_PUBLIC_KEY = "K:";
55     static final String PREFIX_DPP_INFORMATION = "I:";
56 
57     static final String PREFIX_ZXING_SECURITY = "T:";
58     static final String PREFIX_ZXING_SSID = "S:";
59     static final String PREFIX_ZXING_PASSWORD = "P:";
60     static final String PREFIX_ZXING_HIDDEN_SSID = "H:";
61 
62     static final String DELIMITER_QR_CODE = ";";
63 
64     // Ignores password if security is SECURITY_NO_PASSWORD or absent
65     static final String SECURITY_NO_PASSWORD = "nopass"; //open network or OWE
66     static final String SECURITY_WEP = "WEP";
67     static final String SECURITY_WPA_PSK = "WPA";
68     static final String SECURITY_SAE = "SAE";
69 
70     private String mQrCode;
71     @NonNull
72     private UriParserResults mUriParserResults;
73 
WifiQrCode(String qrCode)74     public WifiQrCode(String qrCode) throws IllegalArgumentException {
75         if (TextUtils.isEmpty(qrCode)) {
76             throw new IllegalArgumentException("Empty QR code");
77         }
78 
79         mQrCode = qrCode;
80         try {
81             mUriParserResults = WifiUriParser.parseUri(mQrCode);
82             Log.i("WifiQrCode", "mUriParserResults = " + mUriParserResults);
83         } catch (IllegalArgumentException ie) {
84             throw new IllegalArgumentException("Invalid scheme");
85         }
86     }
87 
getQrCode()88     String getQrCode() {
89         return mQrCode;
90     }
91 
92     /**
93      * Uses to check type of QR code
94      *
95      * SCHEME_DPP for standard Wi-Fi device provision protocol; SCHEME_ZXING_WIFI_NETWORK_CONFIG
96      * for ZXing reader library' Wi-Fi Network config format
97      */
getScheme()98     public int getScheme() {
99         return mUriParserResults.getUriScheme();
100     }
101 
102     /** Available when {@code getScheme()} returns SCHEME_DPP */
getPublicKey()103     String getPublicKey() {
104         return mUriParserResults.getPublicKey();
105     }
106 
107     /** May be available when {@code getScheme()} returns SCHEME_DPP */
getInformation()108     public String getInformation() {
109         return mUriParserResults.getInformation();
110     }
111 
112     /** Available when {@code getScheme()} returns SCHEME_ZXING_WIFI_NETWORK_CONFIG */
getWifiConfiguration()113     WifiConfiguration getWifiConfiguration() {
114         return mUriParserResults.getWifiConfiguration();
115     }
116 
getValidWifiDppQrCodeOrNull(String qrCode)117     static WifiQrCode getValidWifiDppQrCodeOrNull(String qrCode) {
118         WifiQrCode wifiQrCode;
119         try {
120             wifiQrCode = new WifiQrCode(qrCode);
121         } catch(IllegalArgumentException e) {
122             return null;
123         }
124 
125         if (SCHEME_DPP.equals(wifiQrCode.getScheme())) {
126             return wifiQrCode;
127         }
128 
129         return null;
130     }
131 }
132