    001// License: GPL. For details, see LICENSE file.
    002package org.openstreetmap.josm.plugins.streetside.oauth;
    003
    004
    005import java.io.IOException;
    006import java.io.InputStreamReader;
    007import java.io.OutputStreamWriter;
    008import java.io.PrintWriter;
    009import java.net.BindException;
    010import java.net.ServerSocket;
    011import java.net.Socket;
    012import java.util.Scanner;
    013import java.util.regex.Matcher;
    014import java.util.regex.Pattern;
    015
    016import org.apache.log4j.Logger;
    017import org.openstreetmap.josm.Main;
    018import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties;
    019import org.openstreetmap.josm.tools.I18n;
    020
    021/**
    022* Listens to the OAuth port (8763) in order to get the access token and sends
    023* back a simple reply.
    024*
    025* @author nokutu
    026*
    027*/
    028public class OAuthPortListener extends Thread {
    029public static final int PORT = 8763;
    030
    031final static Logger logger = Logger.getLogger(OAuthPortListener.class);
    032
    033protected static final String RESPONSE = String.format(
    034   "<!DOCTYPE html><html><head><meta charset=\"utf8\"><title>%s</title></head><body>%s</body></html>",
    035   I18n.tr("Streetside login"),
    036   I18n.tr("Login successful, return to JOSM.")
    037);
    038private final StreetsideLoginListener callback;
    039
    040public OAuthPortListener(StreetsideLoginListener loginCallback) {
    041 callback = loginCallback;
    042}
    043
    044@Override
    045public void run() {
    046 try (
    047     ServerSocket serverSocket = new ServerSocket(PORT);
    048     Socket clientSocket = serverSocket.accept();
    049     PrintWriter out = new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream(), "UTF-8"), true);
    050     Scanner in = new Scanner(new InputStreamReader(clientSocket.getInputStream(), "UTF-8"))
    051 ) {
    052   String s;
    053   String accessToken = null;
    054   while (in.hasNextLine()) {
    055     s = in.nextLine();
    056     Matcher tokenMatcher = Pattern.compile("^.*&access_token=([^&]+)&.*$").matcher('&'+s+'&');
    057     if (tokenMatcher.matches()) {
    058       accessToken = tokenMatcher.group(1);
    059       break;
    060     } else if (s.contains("keep-alive")) {
    061       break;
    062     }
    063   }
    064
    065   writeContent(out);
    066   out.flush();
    067
    068   StreetsideUser.reset();
    069
    070   logger.info(I18n.tr("Successful login with Streetside, the access token is: {0}", accessToken));
    071   // Saves the access token in preferences.
    072   StreetsideUser.setTokenValid(true);
    073   if (Main.main != null) {
    074     StreetsideProperties.ACCESS_TOKEN.put(accessToken);
    075     String username = StreetsideUser.getUsername();
    076     logger.info(I18n.tr("The username is: {0}", username));
    077     if (callback != null) {
    078       callback.onLogin(username);
    079     }
    080   }
    081 } catch (BindException e) {
    082   logger.warn(e);
    083 } catch (IOException e) {
    084   logger.error(e);
    085 }
    086}
    087
    088private static void writeContent(PrintWriter out) {
    089 out.println("HTTP/1.1 200 OK");
    090 out.println("Content-Length: " + RESPONSE.length());
    091 out.println("Content-Type: text/html" + "\r\n\r\n");
    092 out.println(RESPONSE);
    093}
    094}