Subversion Repositories SmartDukaan

Rev

Rev 37393 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 37393 Rev 37402
Line 5... Line 5...
5
import org.apache.logging.log4j.LogManager;
5
import org.apache.logging.log4j.LogManager;
6
import org.apache.logging.log4j.Logger;
6
import org.apache.logging.log4j.Logger;
7
import org.springframework.beans.factory.annotation.Autowired;
7
import org.springframework.beans.factory.annotation.Autowired;
8
import org.springframework.stereotype.Service;
8
import org.springframework.stereotype.Service;
9
 
9
 
-
 
10
import org.springframework.beans.factory.annotation.Value;
-
 
11
 
10
import java.io.File;
12
import java.io.File;
-
 
13
import java.io.OutputStream;
-
 
14
import java.net.HttpURLConnection;
-
 
15
import java.net.URL;
-
 
16
import java.nio.charset.StandardCharsets;
11
import java.util.Base64;
17
import java.util.Base64;
12
import java.util.HashMap;
18
import java.util.HashMap;
13
import java.util.regex.Pattern;
19
import java.util.regex.Pattern;
14
 
20
 
15
@Service
21
@Service
Line 20... Line 26...
20
	private static final Logger LOGGER = LogManager.getLogger(CaptchaService.class);
26
	private static final Logger LOGGER = LogManager.getLogger(CaptchaService.class);
21
 
27
 
22
	/** The 31 classes the solver model can emit: 123456789ABCDEFGHKMNPQRSTUVWXYZ */
28
	/** The 31 classes the solver model can emit: 123456789ABCDEFGHKMNPQRSTUVWXYZ */
23
	private static final Pattern CAPTCHA_CODE = Pattern.compile("^[1-9A-HK-NP-Z]{4}$");
29
	private static final Pattern CAPTCHA_CODE = Pattern.compile("^[1-9A-HK-NP-Z]{4}$");
24
 
30
 
-
 
31
	private static final String VERDICT_URL = "http://45.79.121.178/verdict";
-
 
32
 
-
 
33
	/** Falls back to a property when CAPTCHA_VERDICT_TOKEN is not in the environment. */
-
 
34
	@Value("${captcha.verdict.token:}")
-
 
35
	private String verdictTokenProperty;
-
 
36
 
25
	/**
37
	/**
26
	 * @return the 4-character captcha code, or null if the solver did not return
38
	 * @return the 4-character captcha code, or null if the solver did not return
27
	 *         a usable one. Callers must skip the IMEI when this is null rather
39
	 *         a usable one. Callers must skip the IMEI when this is null rather
28
	 *         than submitting the value to Vivo.
40
	 *         than submitting the value to Vivo.
29
	 */
41
	 */
30
	public String getCaptchaCode(String filePath) throws Exception {
42
	public String getCaptchaCode(String filePath) throws Exception {
31
		byte[] fileContent = FileUtils.readFileToByteArray(new File(filePath));
43
		return getCaptchaCode(FileUtils.readFileToByteArray(new File(filePath)));
-
 
44
	}
-
 
45
 
-
 
46
	public String getCaptchaCode(byte[] fileContent) throws Exception {
32
		String encodedString = Base64.getEncoder().encodeToString(fileContent);
47
		String encodedString = Base64.getEncoder().encodeToString(fileContent);
33
		Base64Image base64Image = new Base64Image();
48
		Base64Image base64Image = new Base64Image();
34
		base64Image.setImage(encodedString);
49
		base64Image.setImage(encodedString);
35
 
50
 
36
		String response = restClient.postJson("http://45.79.121.178/uploader", base64Image, new HashMap<>());
51
		String response = restClient.postJson("http://45.79.121.178/uploader", base64Image, new HashMap<>());
Line 44... Line 59...
44
			return null;
59
			return null;
45
		}
60
		}
46
		return response.trim();
61
		return response.trim();
47
	}
62
	}
48
 
63
 
-
 
64
	/**
-
 
65
	 * Tell the solver whether Vivo accepted this code, so samples can be split
-
 
66
	 * into training data: accepted means the prediction was right (a free label),
-
 
67
	 * rejected means it was wrong (and needs a human to label it).
-
 
68
	 *
-
 
69
	 * Strictly best-effort. This is data collection - it must never slow down or
-
 
70
	 * break IMEI activation, so it has hard timeouts and swallows everything.
-
 
71
	 */
-
 
72
	public void reportVerdict(byte[] image, String code, boolean accepted) {
-
 
73
		String token = verdictToken();
-
 
74
		if (token == null || token.isEmpty()) {
-
 
75
			return;
-
 
76
		}
-
 
77
		HttpURLConnection conn = null;
-
 
78
		try {
-
 
79
			String body = "{\"image\":\"" + Base64.getEncoder().encodeToString(image)
-
 
80
					+ "\",\"code\":\"" + code + "\",\"accepted\":" + accepted + "}";
-
 
81
			conn = (HttpURLConnection) new URL(VERDICT_URL).openConnection();
-
 
82
			conn.setRequestMethod("POST");
-
 
83
			conn.setConnectTimeout(2000);
-
 
84
			conn.setReadTimeout(3000);
-
 
85
			conn.setDoOutput(true);
-
 
86
			conn.setRequestProperty("Content-Type", "application/json");
-
 
87
			conn.setRequestProperty("X-Verdict-Token", token);
-
 
88
			try (OutputStream os = conn.getOutputStream()) {
-
 
89
				os.write(body.getBytes(StandardCharsets.UTF_8));
-
 
90
			}
-
 
91
			int rc = conn.getResponseCode();
-
 
92
			if (rc != 200) {
-
 
93
				LOGGER.warn("verdict report returned HTTP {}", rc);
-
 
94
			}
-
 
95
		} catch (Exception e) {
-
 
96
			LOGGER.debug("verdict report failed (non-fatal)", e);
-
 
97
		} finally {
-
 
98
			if (conn != null) {
-
 
99
				conn.disconnect();
-
 
100
			}
-
 
101
		}
-
 
102
	}
-
 
103
 
-
 
104
	/** Environment wins, so the secret need not be committed to the properties file. */
-
 
105
	private String verdictToken() {
-
 
106
		String env = System.getenv("CAPTCHA_VERDICT_TOKEN");
-
 
107
		return (env != null && !env.isEmpty()) ? env : verdictTokenProperty;
-
 
108
	}
-
 
109
 
49
	class Base64Image {
110
	class Base64Image {
50
		private String image;
111
		private String image;
51
 
112
 
52
		public String getImage() {
113
		public String getImage() {
53
			return image;
114
			return image;