FritzBoxSession.java
/**
* A Java API for managing FritzBox HomeAutomation
* Copyright (C) 2017 Christoph Pirkl <christoph at users.sourceforge.net>
*
* 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 com.github.kaklakariada.fritzbox;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.github.kaklakariada.fritzbox.http.HttpTemplate;
import com.github.kaklakariada.fritzbox.http.QueryParameters;
import com.github.kaklakariada.fritzbox.login.ChallengeResponse;
import com.github.kaklakariada.fritzbox.model.SessionInfo;
/**
* This class allows logging in to a fritzbox and execute authenticated requests.
*/
public class FritzBoxSession {
private static final Logger LOG = LoggerFactory.getLogger(FritzBoxSession.class);
private static final String LOGIN_PATH = "/login_sid.lua";
private static final String WEBCM_PATH = "/home/home.lua";
private static final String EMPTY_SESSION_ID = "0000000000000000";
private String sid;
private final HttpTemplate httpTemplate;
FritzBoxSession(final String baseUrl) {
this(new HttpTemplate(baseUrl));
}
FritzBoxSession(final HttpTemplate httpTemplate) {
this(httpTemplate, null);
}
private FritzBoxSession(final HttpTemplate httpTemplate, final String sid) {
this.httpTemplate = httpTemplate;
this.sid = sid;
}
public String getSid() {
return sid;
}
public void login(final String username, final String password) {
final SessionInfo sessionWithChallenge = httpTemplate.get(LOGIN_PATH,
QueryParameters.builder().add("version", "2").build(), SessionInfo.class);
if (!EMPTY_SESSION_ID.equals(sessionWithChallenge.getSid())) {
throw new FritzBoxException("Already logged in: " + sessionWithChallenge);
}
final String response = createResponse(sessionWithChallenge.getChallenge(), password);
LOG.debug("Got response {} for challenge {}", response, sessionWithChallenge.getChallenge());
final QueryParameters arguments = QueryParameters.builder() //
.add("username", username == null ? "" : username) //
.add("response", response) //
.build();
final SessionInfo sessionInfo = httpTemplate.get(LOGIN_PATH, arguments, SessionInfo.class);
if (EMPTY_SESSION_ID.equals(sessionInfo.getSid())) {
throw new LoginFailedException(sessionInfo);
}
LOG.debug("Logged in with session id {} and rights {}", sessionInfo.getSid(), sessionInfo.getRights());
this.sid = sessionInfo.getSid();
}
private String createResponse(final String challenge, final String password) {
return ChallengeResponse.getAlgorithm(challenge).calculateResponse(challenge, password);
}
public <T> T getAutenticated(final String path, final QueryParameters parameters, final Class<T> resultType) {
if (sid == null) {
throw new FritzBoxException("Not logged in, session id is null");
}
final QueryParameters parametersWithSessionId = parameters.newBuilder().add("sid", this.sid).build();
return httpTemplate.get(path, parametersWithSessionId, resultType);
}
public void logout() {
httpTemplate.get(WEBCM_PATH, QueryParameters.builder().add("sid", sid).add("logout", "1").build(),
String.class);
LOG.debug("Logged out, invalidate sid");
sid = null;
}
}