/* * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.intellij.cvsSupport2.connections.pserver; import com.intellij.CvsBundle; import com.intellij.cvsSupport2.config.CvsApplicationLevelConfiguration; import com.intellij.cvsSupport2.connections.login.CvsLoginWorker; import com.intellij.cvsSupport2.connections.login.CvsLoginWorkerImpl; import com.intellij.cvsSupport2.connections.ssh.SolveableAuthenticationException; import com.intellij.cvsSupport2.javacvsImpl.io.ReadWriteStatistics; import com.intellij.cvsSupport2.javacvsImpl.io.StreamLogger; import com.intellij.cvsSupport2.util.CvsFileUtil; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.io.FileUtil; import org.jetbrains.annotations.Nullable; import org.netbeans.lib.cvsclient.connection.AuthenticationException; import org.netbeans.lib.cvsclient.connection.IConnection; import org.netbeans.lib.cvsclient.connection.PServerPasswordScrambler; import org.netbeans.lib.cvsclient.connection.UnknownUserException; import java.io.*; import java.util.List; /** * author: lesya */ public class PServerLoginProviderImpl extends PServerLoginProvider { private static final Logger LOG = Logger.getInstance("#com.intellij.cvsSupport2.connections.pserver.PServerLoginProviderImpl"); @Override @Nullable public String getScrambledPasswordForCvsRoot(String cvsRoot) { return getPassword(cvsRoot); } @Nullable private static String requestForPassword(String cvsRoot) { final String password = Messages.showPasswordDialog(CvsBundle.message("prompt.text.enter.password.for.cvs.root", cvsRoot), CvsBundle.message("prompt.title.enter.password.for.cvs.root")); return password != null ? PServerPasswordScrambler.getInstance().scramble(password) : null; } @Override public CvsLoginWorker getLoginWorker(final Project project, final PServerCvsSettings pServerCvsSettings) { return new PServerLoginWorker(project, pServerCvsSettings); } private static class PServerLoginWorker extends CvsLoginWorkerImpl<PServerCvsSettings> { private PServerLoginWorker(final Project project, final PServerCvsSettings settings) { super(project, settings); } @Override protected void silentLoginImpl(final boolean forceCheck) throws AuthenticationException { final String cvsRoot = mySettings.getCvsRootAsString(); final String stored = getPassword(cvsRoot); if (stored == null) throw new SolveableAuthenticationException(null); if (forceCheck) { tryConnection(); } } private void tryConnection() throws AuthenticationException { final IConnection connection = mySettings.createConnection(new ReadWriteStatistics()); try { connection.open(new StreamLogger()); mySettings.setOffline(false); } catch (UnknownUserException e) { throw new SolveableAuthenticationException(e.getMessage(), e); } finally { try { connection.close(); } catch (IOException e) { LOG.info(e); } } } @Override public boolean promptForPassword() { final String cvsRoot = mySettings.getCvsRootAsString(); final String password = requestForPassword(cvsRoot); if (password == null) return false; try { removeAllPasswordsForThisCvsRootFromPasswordFile(cvsRoot); storePassword(cvsRoot, password); } catch (IOException e) { showConnectionErrorMessage(myProject, CvsBundle.message("error.message.cannot.store.password", e.getLocalizedMessage())); return false; } mySettings.storePassword(password); return true; } @Override protected void clearOldCredentials() { mySettings.releasePassword(); } } // TODO do release password ! when opening a connection and there's a problem with authorization private static void removeAllPasswordsForThisCvsRootFromPasswordFile(String cvsRoot) throws IOException { final File passFile = getPassFile(); if (!passFile.isFile()) { return; } final List<String> lines = CvsFileUtil.readLinesFrom(passFile, cvsRoot); try { CvsFileUtil.storeLines(lines, passFile); } catch (IOException e) { LOG.error(e); } } private static void storePassword(String stringConfiguration, String scrambledPassword) throws IOException { final File passFile = getPassFile(); FileUtil.createIfDoesntExist(passFile); final List<String> lines = CvsFileUtil.readLinesFrom(passFile); lines.add(stringConfiguration + " " + scrambledPassword); CvsFileUtil.storeLines(lines, passFile); } @Nullable private static String getPassword(String config) { final File passFile = getPassFile(); try { final BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(passFile), CvsApplicationLevelConfiguration.getCharset())); try { return findPasswordIn(reader, config); } finally { reader.close(); } } catch (IOException e) { return null; } } private static File getPassFile() { return CvsApplicationLevelConfiguration.getInstance().getPassFile(); } @Nullable private static String findPasswordIn(BufferedReader reader, String config) throws IOException { String line; while ((line = reader.readLine()) != null) { final int position = line.indexOf(config); if (position == -1) { continue; } final String result = line.substring(position + config.length()); if (result.isEmpty()) { continue; } return result.substring(1); } return null; } }