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}