/* * Symphony - A modern community (forum/SNS/blog) platform written in Java. * Copyright (C) 2012-2017, b3log.org & hacpai.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.b3log.symphony.util; import org.apache.commons.lang.StringUtils; import org.b3log.latke.logging.Level; import org.b3log.latke.logging.Logger; import org.b3log.symphony.model.Common; import org.json.JSONObject; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.SocketTimeoutException; import java.net.URL; /** * Geography utilities. * * @author <a href="http://88250.b3log.org">Liang Ding</a> * @version 1.2.2.1, Apr 11, 2016 * @since 1.3.0 */ public final class Geos { /** * Logger. */ private static final Logger LOGGER = Logger.getLogger(Geos.class.getName()); /** * Gets country, province and city of the specified IP. * * @param ip the specified IP * @return address info, for example <pre> * { * "country": "", * "province": "", * "city": "" * } * </pre>, returns {@code null} if not found */ public static JSONObject getAddress(final String ip) { final String ak = Symphonys.get("baidu.lbs.ak"); if (StringUtils.isBlank(ak) || !Networks.isIPv4(ip)) { return null; } HttpURLConnection conn = null; try { final URL url = new URL("http://api.map.baidu.com/location/ip?ip=" + ip + "&ak=" + ak); conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(1000); conn.setReadTimeout(1000); final BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(conn.getInputStream(), "UTF-8")); String line = null; final StringBuilder sb = new StringBuilder(); while (null != (line = bufferedReader.readLine())) { sb.append(line); } final JSONObject data = new JSONObject(sb.toString()); if (0 != data.optInt("status")) { return getAddressSina(ip); // Try it via Sina API } final String content = data.optString("address"); final String country = content.split("\\|")[0]; if (!"CN".equals(country) && !"HK".equals(country)) { LOGGER.log(Level.WARN, "Found other country via Baidu [" + country + ", " + ip + "]"); return null; } final String province = content.split("\\|")[1]; String city = content.split("\\|")[2]; if ("None".equals(province) || "None".equals(city)) { return getAddressSina(ip); // Try it via Sina API } city = StringUtils.replace(city, "市", ""); final JSONObject ret = new JSONObject(); ret.put(Common.COUNTRY, "中国"); ret.put(Common.PROVINCE, province); ret.put(Common.CITY, city); return ret; } catch (final SocketTimeoutException e) { LOGGER.log(Level.ERROR, "Get location from Baidu timeout [ip=" + ip + "]"); return null; } catch (final Exception e) { LOGGER.log(Level.ERROR, "Can't get location from Baidu [ip=" + ip + "]", e); return null; } finally { if (null != conn) { try { conn.disconnect(); } catch (final Exception e) { LOGGER.log(Level.ERROR, "Close HTTP connection error", e); } } } } /** * Gets province, city of the specified IP by Sina API. * * @param ip the specified IP * @return address info, for example <pre> * { * "province": "", * "city": "" * } * </pre>, returns {@code null} if not found */ private static JSONObject getAddressSina(final String ip) { HttpURLConnection conn = null; try { final URL url = new URL("http://int.dpool.sina.com.cn/iplookup/iplookup.php?ip=" + ip + "&format=json"); conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(1000); conn.setReadTimeout(1000); final BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(conn.getInputStream(), "UTF-8")); String line = null; final StringBuilder sb = new StringBuilder(); while (null != (line = bufferedReader.readLine())) { sb.append(line); } final JSONObject data = new JSONObject(sb.toString()); if (1 != data.optInt("ret")) { return null; } final String country = data.optString("country"); final String province = data.optString("province"); String city = data.optString("city"); city = StringUtils.replace(city, "市", ""); final JSONObject ret = new JSONObject(); ret.put(Common.COUNTRY, country); ret.put(Common.PROVINCE, province); ret.put(Common.CITY, city); return ret; } catch (final SocketTimeoutException e) { LOGGER.log(Level.ERROR, "Get location from Sina timeout [ip=" + ip + "]"); return null; } catch (final Exception e) { LOGGER.log(Level.ERROR, "Can't get location from Sina [ip=" + ip + "]", e); return null; } finally { if (null != conn) { try { conn.disconnect(); } catch (final Exception e) { LOGGER.log(Level.ERROR, "Close HTTP connection error", e); } } } } /** * Private constructor. */ private Geos() { } }