Add login dialog for Cam4

The login dialog uses a WebView to load the login form from cam4.com
Username and password get filled in by ctbrec, the user has to solve
the captcha. Afterwards all cookies (especially the session cookie)
are extracted from the webview and transfered to the OkHttp client,
so that it can be used for further requests.
This commit is contained in:
0xboobface 2018-10-29 17:36:58 +01:00
parent 64beb44316
commit 43cb005fcd
5 changed files with 175 additions and 7 deletions

View File

@ -24,6 +24,8 @@ public class Settings {
public String password = ""; // chaturbate password TODO maybe rename this onetime
public String mfcUsername = "";
public String mfcPassword = "";
public String cam4Username;
public String cam4Password;
public String lastDownloadDir = "";
public List<Model> models = new ArrayList<Model>();

View File

@ -62,17 +62,13 @@ public class Cam4 extends AbstractSite {
@Override
public void login() throws IOException {
getHttpClient().login();
}
@Override
public HttpClient getHttpClient() {
if(httpClient == null) {
httpClient = new HttpClient() {
@Override
public boolean login() throws IOException {
return false;
}
};
httpClient = new Cam4HttpClient();
}
return httpClient;
}

View File

@ -0,0 +1,64 @@
package ctbrec.sites.cam4;
import java.io.IOException;
import java.net.HttpCookie;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import org.json.JSONObject;
import ctbrec.io.HttpClient;
import okhttp3.Cookie;
import okhttp3.HttpUrl;
import okhttp3.Request;
import okhttp3.Response;
public class Cam4HttpClient extends HttpClient {
@Override
public boolean login() throws IOException {
// login with javafx WebView
Cam4LoginDialog loginDialog = new Cam4LoginDialog();
// transfer cookies from WebView to OkHttp cookie jar
transferCookies(loginDialog);
return checkLoginSuccess();
}
/**
* check, if the login worked by requesting unchecked mail
* @throws IOException
*/
private boolean checkLoginSuccess() throws IOException {
String mailUrl = "https://www.cam4.de.com/mail/unreadThreads";
Request req = new Request.Builder().url(mailUrl).build();
Response response = execute(req);
if(response.isSuccessful()) {
JSONObject json = new JSONObject(response.body().string());
return json.has("status") && Objects.equals("success", json.getString("status"));
} else {
response.close();
return false;
}
}
private void transferCookies(Cam4LoginDialog loginDialog) {
HttpUrl redirectedUrl = HttpUrl.parse(loginDialog.getUrl());
List<Cookie> cookies = new ArrayList<>();
for (HttpCookie webViewCookie : loginDialog.getCookies()) {
Cookie cookie = Cookie.parse(redirectedUrl, webViewCookie.toString());
cookies.add(cookie);
}
cookieJar.saveFromResponse(redirectedUrl, cookies);
HttpUrl origUrl = HttpUrl.parse(Cam4LoginDialog.URL);
cookies = new ArrayList<>();
for (HttpCookie webViewCookie : loginDialog.getCookies()) {
Cookie cookie = Cookie.parse(origUrl, webViewCookie.toString());
cookies.add(cookie);
}
cookieJar.saveFromResponse(origUrl, cookies);
}
}

View File

@ -0,0 +1,101 @@
package ctbrec.sites.cam4;
import java.net.CookieHandler;
import java.net.CookieManager;
import java.net.HttpCookie;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.Objects;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ctbrec.Config;
import javafx.concurrent.Worker.State;
import javafx.scene.Scene;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class Cam4LoginDialog {
private static final transient Logger LOG = LoggerFactory.getLogger(Cam4LoginDialog.class);
public static final String URL = Cam4.BASE_URI + "/login";
private List<HttpCookie> cookies = null;
private String url;
private Region veil;
private ProgressIndicator p;
public Cam4LoginDialog() {
Stage stage = new Stage();
stage.setTitle("Cam4 Login");
CookieManager cookieManager = new CookieManager();
CookieHandler.setDefault(cookieManager);
WebView webView = createWebView(stage);
veil = new Region();
veil.setStyle("-fx-background-color: rgba(0, 0, 0, 0.4)");
//veil.setPrefSize(240, 160);
p = new ProgressIndicator();
p.setMaxSize(140, 140);
StackPane stackPane = new StackPane();
stackPane.getChildren().addAll(webView, veil, p);
stage.setScene(new Scene(stackPane, 480, 854));
stage.showAndWait();
cookies = cookieManager.getCookieStore().getCookies();
}
private WebView createWebView(Stage stage) {
WebView browser = new WebView();
WebEngine webEngine = browser.getEngine();
webEngine.setJavaScriptEnabled(true);
webEngine.locationProperty().addListener((obs, oldV, newV) -> {
try {
URL _url = new URL(newV);
if (Objects.equals(_url.getPath(), "/")) {
stage.close();
}
} catch (MalformedURLException e) {
LOG.error("Couldn't parse new url {}", newV, e);
}
url = newV.toString();
});
webEngine.getLoadWorker().stateProperty().addListener((observable, oldState, newState) -> {
System.out.println(newState);
if (newState == State.SUCCEEDED) {
String username = Config.getInstance().getSettings().cam4Username;
if (username != null && !username.trim().isEmpty()) {
webEngine.executeScript("$('input[name=username]').attr('value','" + username + "')");
}
String password = Config.getInstance().getSettings().cam4Password;
if (password != null && !password.trim().isEmpty()) {
webEngine.executeScript("$('input[name=password]').attr('value','" + password + "')");
}
webEngine.executeScript("$('div[class~=navbar]').css('display','none')");
webEngine.executeScript("$('div#footer').css('display','none')");
webEngine.executeScript("$('div#content').css('padding','0')");
veil.setVisible(false);
p.setVisible(false);
} else if (newState == State.CANCELLED || newState == State.FAILED) {
veil.setVisible(false);
p.setVisible(false);
}
});
webEngine.load(URL);
return browser;
}
public List<HttpCookie> getCookies() {
return cookies;
}
public String getUrl() {
return url;
}
}

View File

@ -6,6 +6,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -50,7 +51,11 @@ public class CookieJarImpl implements CookieJar {
public List<Cookie> loadForRequest(HttpUrl url) {
String host = getHost(url);
List<Cookie> cookies = cookieStore.get(host);
LOG.debug("Cookies for {}: {}", url.host(), cookies);
LOG.debug("Cookies for {}", url);
Optional.ofNullable(cookies).ifPresent(cookiez -> cookiez.forEach(c -> {
LOG.debug(" {} expires on:{}", c, c.expiresAt());
}));
//LOG.debug("Cookies for {}: {}", url.host(), cookies);
return cookies != null ? cookies : new ArrayList<Cookie>();
}