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