Allow passing user/pass explicitly or via netrc

#2211
This commit is contained in:
Daniel Molkentin 2014-09-16 23:52:28 +02:00
parent 97cc05eeea
commit fe023e2229
11 changed files with 792 additions and 53 deletions

View file

@ -427,7 +427,7 @@ if(KRAZY2_EXECUTABLE)
endif()
set(owncloudcmd_NAME ${APPLICATION_EXECUTABLE}cmd)
set(OWNCLOUDCMD_SRC owncloudcmd/simplesslerrorhandler.cpp owncloudcmd/owncloudcmd.cpp)
set(OWNCLOUDCMD_SRC owncloudcmd/simplesslerrorhandler.cpp owncloudcmd/owncloudcmd.cpp owncloudcmd/netrcparser.cpp)
if(NOT BUILD_LIBRARIES_ONLY)
add_executable(${owncloudcmd_NAME} ${OWNCLOUDCMD_SRC})

428
src/CMakeLists.txt.orig Normal file
View file

@ -0,0 +1,428 @@
# TODO: OSX and LIB_ONLY seem to require this to go to binary dir only
set(BIN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
set(synclib_NAME ${APPLICATION_EXECUTABLE}sync)
<<<<<<< HEAD
add_subdirectory(libsync)
if (NOT BUILD_LIBRARIES_ONLY)
add_subdirectory(gui)
add_subdirectory(cmd)
endif(NOT BUILD_LIBRARIES_ONLY)
=======
if ( APPLE )
list(APPEND OS_SPECIFIC_LINK_LIBRARIES
/System/Library/Frameworks/CoreServices.framework
/System/Library/Frameworks/Foundation.framework
/System/Library/Frameworks/AppKit.framework
)
endif()
IF(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
list(APPEND OS_SPECIFIC_LINK_LIBRARIES
inotify
)
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
if(SPARKLE_FOUND AND NOT BUILD_LIBRARIES_ONLY)
list (APPEND OS_SPECIFIC_LINK_LIBRARIES ${SPARKLE_LIBRARY})
endif()
set(3rdparty_SRC
3rdparty/qtsingleapplication/qtsingleapplication.cpp
3rdparty/qtsingleapplication/qtlocalpeer.cpp
3rdparty/qtsingleapplication/qtsinglecoreapplication.cpp
3rdparty/qtlockedfile/qtlockedfile.cpp
3rdparty/fancylineedit/fancylineedit.cpp
3rdparty/QProgressIndicator/QProgressIndicator.cpp
)
if (APPLE)
list(APPEND 3rdparty_SRC
3rdparty/qtmacgoodies/src/macpreferenceswindow.mm
3rdparty/qtmacgoodies/src/macstandardicon.mm
3rdparty/qtmacgoodies/src/macwindow.mm
)
endif()
if(NOT WIN32)
list(APPEND 3rdparty_SRC 3rdparty/qtlockedfile/qtlockedfile_unix.cpp)
else()
list(APPEND 3rdparty_SRC 3rdparty/qtlockedfile/qtlockedfile_win.cpp )
endif()
set(3rdparty_INC
${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/qtlockedfile
${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/qtsingleapplication
${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/QProgressIndicator
${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/fancylineedit
${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/qjson
${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/qtmacgoodies/src
)
set(libsync_SRCS
mirall/authenticationdialog.cpp
mirall/syncresult.cpp
mirall/mirallconfigfile.cpp
mirall/syncengine.cpp
mirall/owncloudpropagator.cpp
mirall/propagatorjobs.cpp
mirall/propagator_qnam.cpp
mirall/propagator_legacy.cpp
mirall/syncjournalfilerecord.cpp
mirall/syncjournaldb.cpp
mirall/theme.cpp
mirall/owncloudtheme.cpp
mirall/logger.cpp
mirall/utility.cpp
mirall/filesystem.cpp
mirall/connectionvalidator.cpp
mirall/progressdispatcher.cpp
mirall/mirallaccessmanager.cpp
mirall/networkjobs.cpp
mirall/account.cpp
mirall/quotainfo.cpp
mirall/clientproxy.cpp
mirall/cookiejar.cpp
mirall/syncfilestatus.cpp
mirall/discoveryphase.cpp
creds/dummycredentials.cpp
creds/abstractcredentials.cpp
creds/credentialsfactory.cpp
creds/http/httpconfigfile.cpp
creds/credentialscommon.cpp
3rdparty/qjson/json.cpp
)
if(TOKEN_AUTH_ONLY)
set (libsync_SRCS
${libsync_SRCS}
creds/tokencredentials.cpp
)
else()
set (libsync_SRCS
${libsync_SRCS}
creds/httpcredentials.cpp
creds/shibbolethcredentials.cpp
creds/shibboleth/shibbolethwebview.cpp
creds/shibboleth/shibbolethrefresher.cpp
creds/shibboleth/shibbolethuserjob.cpp
)
endif()
# These headers are installed for libowncloudsync to be used by 3rd party apps
set(owncloudsync_HEADERS
mirall/account.h
mirall/syncengine.h
mirall/mirallconfigfile.h
mirall/networkjobs.h
mirall/progressdispatcher.h
mirall/syncfileitem.h
mirall/syncjournaldb.h
mirall/syncresult.h
)
set(creds_HEADERS
creds/abstractcredentials.h
creds/httpcredentials.h
)
IF (NOT APPLE)
INSTALL(
FILES ${owncloudsync_HEADERS}
DESTINATION ${INCLUDE_INSTALL_DIR}/${synclib_NAME}/mirall
)
INSTALL(
FILES ${creds_HEADERS}
DESTINATION ${INCLUDE_INSTALL_DIR}/${synclib_NAME}/creds
)
ENDIF(NOT APPLE)
list(APPEND libsync_LINK_TARGETS
${QT_LIBRARIES}
ocsync
httpbf
${OS_SPECIFIC_LINK_LIBRARIES}
)
if(QTKEYCHAIN_FOUND OR QT5KEYCHAIN_FOUND)
list(APPEND libsync_LINK_TARGETS ${QTKEYCHAIN_LIBRARY})
include_directories(${QTKEYCHAIN_INCLUDE_DIR})
endif()
if(NEON_FOUND)
list(APPEND libsync_LINK_TARGETS ${NEON_LIBRARIES})
include_directories(${NEON_INCLUDE_DIRS})
if(NEON_WITH_LFS)
add_definitions(-DNE_LFS)
endif()
endif()
add_library(${synclib_NAME} SHARED ${libsync_SRCS} ${syncMoc})
GENERATE_EXPORT_HEADER( ${synclib_NAME}
BASE_NAME ${synclib_NAME}
EXPORT_MACRO_NAME OWNCLOUDSYNC_EXPORT
EXPORT_FILE_NAME owncloudlib.h
STATIC_DEFINE OWNCLOUD_BUILT_AS_STATIC
)
if(TOKEN_AUTH_ONLY)
qt5_use_modules(${synclib_NAME} Network Xml Sql)
else()
qt5_use_modules(${synclib_NAME} Widgets Network Xml WebKitWidgets Sql)
endif()
set_target_properties( ${synclib_NAME} PROPERTIES
VERSION ${MIRALL_VERSION}
SOVERSION ${MIRALL_SOVERSION}
)
set_target_properties( ${synclib_NAME} PROPERTIES
INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR}/${APPLICATION_EXECUTABLE}" )
target_link_libraries(${synclib_NAME} ${libsync_LINK_TARGETS} )
if(BUILD_LIBRARIES_ONLY)
#add_library(${synclib_NAME}_static STATIC ${libsync_SRCS} ${syncMoc})
#qt5_use_modules(${synclib_NAME}_static Widgets Network Xml Sql)
#set_target_properties( ${synclib_NAME}_static PROPERTIES
# VERSION ${MIRALL_VERSION}
# SOVERSION ${MIRALL_SOVERSION}
#)
#target_link_libraries(${synclib_NAME}_static ${libsync_LINK_TARGETS} )
endif()
if(NOT BUILD_OWNCLOUD_OSX_BUNDLE)
install(TARGETS ${synclib_NAME}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
if(NOT WIN32)
configure_file(${CMAKE_SOURCE_DIR}/mirall.desktop.in
${CMAKE_CURRENT_BINARY_DIR}/${APPLICATION_EXECUTABLE}.desktop)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${APPLICATION_EXECUTABLE}.desktop DESTINATION share/applications )
endif()
else()
install(TARGETS ${synclib_NAME} DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/MacOS)
if (SPARKLE_FOUND)
install(DIRECTORY "${SPARKLE_LIBRARY}"
DESTINATION "${OWNCLOUD_OSX_BUNDLE}/Contents/Frameworks")
endif (SPARKLE_FOUND)
endif()
set(mirall_UI
mirall/folderwizardsourcepage.ui
mirall/folderwizardtargetpage.ui
mirall/sslerrordialog.ui
mirall/settingsdialog.ui
mirall/generalsettings.ui
mirall/networksettings.ui
mirall/accountsettings.ui
mirall/ignorelisteditor.ui
mirall/protocolwidget.ui
wizard/owncloudsetupnocredspage.ui
wizard/owncloudhttpcredspage.ui
wizard/owncloudwizardresultpage.ui
wizard/owncloudadvancedsetuppage.ui
)
qt_wrap_ui(mirall_UI_SRCS ${mirall_UI})
set(mirall_SRCS
mirall/application.cpp
mirall/systray.cpp
mirall/folderman.cpp
mirall/folder.cpp
mirall/folderwatcher.cpp
mirall/folderwizard.cpp
mirall/folderstatusmodel.cpp
mirall/protocolwidget.cpp
mirall/openfilemanager.cpp
wizard/owncloudwizard.cpp
wizard/owncloudsetuppage.cpp
wizard/owncloudhttpcredspage.cpp
wizard/abstractcredswizardpage.cpp
wizard/owncloudwizardresultpage.cpp
wizard/owncloudwizardcommon.cpp
wizard/owncloudshibbolethcredspage.cpp
wizard/owncloudadvancedsetuppage.cpp
mirall/owncloudsetupwizard.cpp
mirall/sslerrordialog.cpp
mirall/logbrowser.cpp
mirall/settingsdialog.cpp
mirall/generalsettings.cpp
mirall/networksettings.cpp
mirall/accountsettings.cpp
mirall/ignorelisteditor.cpp
mirall/owncloudgui.cpp
mirall/socketapi.cpp
mirall/sslbutton.cpp
mirall/syncrunfilelog.cpp
mirall/selectivesyncdialog.cpp
)
set(updater_SRCS
updater/updateinfo.cpp
updater/updater.cpp
updater/ocupdater.cpp
)
IF( APPLE )
list(APPEND mirall_SRCS mirall/cocoainitializer_mac.mm)
list(APPEND mirall_SRCS mirall/settingsdialogmac.cpp)
if(SPARKLE_FOUND)
# Define this, we need to check in updater.cpp
add_definitions( -DHAVE_SPARKLE )
list(APPEND updater_SRCS updater/sparkleupdater_mac.mm)
endif()
ENDIF()
IF( NOT WIN32 AND NOT APPLE )
set(mirall_SRCS ${mirall_SRCS} mirall/folderwatcher_linux.cpp)
ENDIF()
IF( WIN32 )
set(mirall_SRCS ${mirall_SRCS} mirall/folderwatcher_win.cpp)
ENDIF()
IF( APPLE )
list(APPEND mirall_SRCS mirall/folderwatcher_mac.cpp)
ENDIF()
# csync is required.
include_directories(../csync/src ../csync/src/httpbf/src ${CMAKE_CURRENT_BINARY_DIR}/../csync ${CMAKE_CURRENT_BINARY_DIR}/../csync/src )
include_directories(${3rdparty_INC})
qt_add_translation(mirall_I18N ${TRANSLATIONS})
set( final_src
${MIRALL_RC_SRC}
${mirall_SRCS}
${mirall_UI_SRCS}
${mirallMoc}
${mirall_I18N}
${3rdparty_SRC}
${3rdparty_MOC}
)
# add executable icon on windows and osx
include( AddAppIconMacro )
set(ownCloud_old ${ownCloud})
# set an icon_app_name. For historical reasons we can not use the
# application_shortname for ownCloud but must rather set it manually.
if ( EXISTS ${OEM_THEME_DIR}/OEM.cmake )
set(ICON_APP_NAME ${APPLICATION_SHORTNAME})
else()
set(ICON_APP_NAME "owncloud")
endif()
kde4_add_app_icon( ownCloud "${theme_dir}/colored/${ICON_APP_NAME}-icon*.png")
list(APPEND final_src ${ownCloud})
set(ownCloud ${ownCloud_old})
if (WITH_DBUS)
set(ADDITIONAL_APP_MODULES DBus)
endif(WITH_DBUS)
if(NOT BUILD_OWNCLOUD_OSX_BUNDLE AND NOT BUILD_LIBRARIES_ONLY)
set(BIN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
if(NOT WIN32)
file( GLOB _icons "${theme_dir}/colored/${ICON_APP_NAME}-icon-*.png" )
foreach( _file ${_icons} )
string( REPLACE "${theme_dir}/colored/${ICON_APP_NAME}-icon-" "" _res ${_file} )
string( REPLACE ".png" "" _res ${_res} )
install( FILES ${_file} RENAME ${ICON_APP_NAME}.png DESTINATION ${DATADIR}/icons/hicolor/${_res}x${_res}/apps )
endforeach( _file )
endif(NOT WIN32)
install(FILES ${mirall_I18N} DESTINATION share/${APPLICATION_EXECUTABLE}/i18n)
# we may not add MACOSX_BUNDLE here, if not building one
# add_executable( ${APPLICATION_EXECUTABLE} main.cpp ${final_src})
add_executable( ${APPLICATION_EXECUTABLE} WIN32 main.cpp ${final_src})
qt5_use_modules(${APPLICATION_EXECUTABLE} Widgets Network Xml WebKitWidgets Sql ${ADDITIONAL_APP_MODULES})
elseif(NOT BUILD_LIBRARIES_ONLY)
set(BIN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
if (Qt5Core_FOUND)
include(DeployQt5)
else(Qt5Core_FOUND)
include(DeployQt4)
endif(Qt5Core_FOUND)
set(CMAKE_INSTALL_PREFIX ".") # Examples use /Applications. hurmpf.
set(MACOSX_BUNDLE_ICON_FILE "ownCloud.icns")
# we must add MACOSX_BUNDLE only if building a bundle
add_executable( ${APPLICATION_EXECUTABLE} WIN32 MACOSX_BUNDLE main.cpp ${final_src})
qt5_use_modules(${APPLICATION_EXECUTABLE} Widgets Network Xml WebKitWidgets Sql ${ADDITIONAL_APP_MODULES})
set (QM_DIR ${OWNCLOUD_OSX_BUNDLE}/Contents/Resources/Translations)
install(FILES ${mirall_I18N} DESTINATION ${QM_DIR})
file(GLOB qt_I18N ${QT_TRANSLATIONS_DIR}/qt_??.qm ${QT_TRANSLATIONS_DIR}/qt_??_??.qm)
install(FILES ${qt_I18N} DESTINATION ${QM_DIR})
file(GLOB qtkeychain_I18N ${QT_TRANSLATIONS_DIR}/qtkeychain*.qm)
install(FILES ${qtkeychain_I18N} DESTINATION ${QM_DIR})
endif()
if(NOT BUILD_LIBRARIES_ONLY)
add_library(updater STATIC ${updater_SRCS} ${updaterMoc})
target_link_libraries(updater ${synclib_NAME})
qt5_use_modules(updater Widgets Network Xml)
set_target_properties( ${APPLICATION_EXECUTABLE} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${BIN_OUTPUT_DIRECTORY}
)
set_target_properties( ${APPLICATION_EXECUTABLE} PROPERTIES
INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR}/${APPLICATION_EXECUTABLE}" )
target_link_libraries( ${APPLICATION_EXECUTABLE} ${QT_LIBRARIES} )
target_link_libraries( ${APPLICATION_EXECUTABLE} ${synclib_NAME} )
target_link_libraries( ${APPLICATION_EXECUTABLE} updater )
target_link_libraries( ${APPLICATION_EXECUTABLE} ${OS_SPECIFIC_LINK_LIBRARIES} )
install(TARGETS ${APPLICATION_EXECUTABLE}
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
BUNDLE DESTINATION "."
)
endif()
#FIXME: find a nice solution to make the second if(BUILD_OWNCLOUD_OSX_BUNDLE) unnecessary
# currently it needs to be done because the code right above needs to be executed no matter
# if building a bundle or not and the install_qt4_executable needs to be called afterwards
if(BUILD_OWNCLOUD_OSX_BUNDLE AND NOT BUILD_LIBRARIES_ONLY)
if(Qt5Core_FOUND)
install_qt5_executable(${OWNCLOUD_OSX_BUNDLE} "qtaccessiblewidgets;qsqlite;qcocoa")
else(Qt5Core_FOUND)
install_qt4_executable(${OWNCLOUD_OSX_BUNDLE} "qtaccessiblewidgets;qsqlite")
endif(Qt5Core_FOUND)
endif()
>>>>>>> origin/master
find_program(KRAZY2_EXECUTABLE krazy2)
if(KRAZY2_EXECUTABLE)
# s/y k/y ALL k/ for building this target always
add_custom_target( krazy krazy2 --check-sets c++,qt4,foss
${PROJECT_SOURCE_DIR}/src/libsync/*.ui
${PROJECT_SOURCE_DIR}/src/libsync/*.h
${PROJECT_SOURCE_DIR}/src/libsync/*.cpp
${PROJECT_SOURCE_DIR}/src/gui/*.ui
${PROJECT_SOURCE_DIR}/src/gui/*.h
${PROJECT_SOURCE_DIR}/src/gui/*.cpp
${PROJECT_SOURCE_DIR}/src/cmd/*.h
${PROJECT_SOURCE_DIR}/src/cmd/*.cpp
)
endif()

View file

@ -36,7 +36,7 @@ AbstractCredentials* create(const QString& type)
// empty string might happen for old version of configuration
if (type == "http" || type == "") {
return new HttpCredentials;
return new HttpCredentialsGui;
} else if (type == "dummy") {
return new DummyCredentials;
} else if (type == "shibboleth") {

View file

@ -37,9 +37,6 @@ using namespace QKeychain;
namespace Mirall
{
namespace
{
int getauth(const char *prompt,
char *buf,
size_t len,
@ -74,10 +71,10 @@ int getauth(const char *prompt,
return re;
}
namespace
{
const char userC[] = "user";
const char authenticationFailedC[] = "owncloud-authentication-failed";
} // ns
class HttpCredentialsAccessManager : public MirallAccessManager {
@ -299,19 +296,6 @@ void HttpCredentials::slotReadJobDone(QKeychain::Job *job)
}
}
QString HttpCredentials::queryPassword(bool *ok)
{
if (ok) {
QString str = QInputDialog::getText(0, tr("Enter Password"),
tr("Please enter %1 password for user '%2':")
.arg(Theme::instance()->appNameGUI(), _user),
QLineEdit::Password, QString(), ok);
return str;
} else {
return QString();
}
}
void HttpCredentials::invalidateToken(Account *account)
{
_password = QString();
@ -380,4 +364,17 @@ void HttpCredentials::slotAuthentication(QNetworkReply* reply, QAuthenticator* a
reply->close();
}
QString HttpCredentialsGui::queryPassword(bool *ok)
{
if (ok) {
QString str = QInputDialog::getText(0, tr("Enter Password"),
tr("Please enter %1 password for user '%2':")
.arg(Theme::instance()->appNameGUI(), _user),
QLineEdit::Password, QString(), ok);
return str;
} else {
return QString();
}
}
} // ns Mirall

View file

@ -49,7 +49,7 @@ public:
void persist(Account *account) Q_DECL_OVERRIDE;
QString user() const Q_DECL_OVERRIDE;
QString password() const;
QString queryPassword(bool *ok);
virtual QString queryPassword(bool *ok) = 0;
void invalidateToken(Account *account) Q_DECL_OVERRIDE;
QString fetchUser(Account *account);
@ -58,14 +58,23 @@ private Q_SLOTS:
void slotReadJobDone(QKeychain::Job*);
void slotWriteJobDone(QKeychain::Job*);
private:
protected:
QString _user;
QString _password;
private:
bool _ready;
bool _fetchJobInProgress; //True if the keychain job is in progress or the input dialog visible
bool _readPwdFromDeprecatedPlace;
};
class OWNCLOUDSYNC_EXPORT HttpCredentialsGui : public HttpCredentials {
public:
HttpCredentialsGui() : HttpCredentials() {}
HttpCredentialsGui(const QString& user, const QString& password) : HttpCredentials(user, password) {}
QString queryPassword(bool *ok) Q_DECL_OVERRIDE;
};
} // ns Mirall
#endif

View file

@ -0,0 +1,97 @@
/*
* Copyright (C) by Daniel Molkentin <danimo@owncloud.com>
*
* 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 2 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.
*/
#include <QDir>
#include <QFile>
#include <QTextStream>
#include "netrcparser.h"
namespace Mirall {
namespace {
QString defaultKeyword = QLatin1String("default");
QString machineKeyword = QLatin1String("machine");
QString loginKeyword = QLatin1String("login");
QString passwordKeyword = QLatin1String("password");
}
NetrcParser::NetrcParser(const QString &fileName)
: _fileName(fileName)
{
if (_fileName.isEmpty()) {
_fileName = QDir::homePath()+QLatin1String("/.netrc");
}
}
void NetrcParser::tryAddEntryAndClear(QString& machine, LoginPair& pair, bool& isDefault) {
if (isDefault) {
_default = pair;
} else if (!machine.isEmpty() && !pair.first.isEmpty()){
_entries.insert(machine, pair);
}
pair = qMakePair(QString(), QString());
machine.clear();
isDefault = false;
}
bool NetrcParser::parse()
{
QFile netrc(_fileName);
if (!netrc.open(QIODevice::ReadOnly)) {
return false;
}
QTextStream ts(&netrc);
LoginPair pair;
QString machine;
bool isDefault = false;
while (!ts.atEnd()) {
QString next;
ts >> next;
if (next == defaultKeyword) {
tryAddEntryAndClear(machine, pair, isDefault);
isDefault = true;
}
if (next == machineKeyword) {
tryAddEntryAndClear(machine, pair, isDefault);
ts >> machine;
} else if (next == loginKeyword) {
ts >> pair.first;
} else if (next == passwordKeyword) {
ts >> pair.second;
} // ignore unsupported tokens
}
tryAddEntryAndClear(machine, pair, isDefault);
if (!_entries.isEmpty() || _default != qMakePair(QString(), QString())) {
return true;
} else {
return false;
}
}
NetrcParser::LoginPair NetrcParser::find(const QString &machine)
{
QHash<QString, LoginPair>::const_iterator it = _entries.find(machine);
if (it != _entries.end()) {
return *it;
} else {
return _default;
}
}
} // namespace Mirall

View file

@ -0,0 +1,41 @@
/*
* Copyright (C) by Daniel Molkentin <danimo@owncloud.com>
*
* 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 2 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.
*/
#ifndef NETRCPARSER_H
#define NETRCPARSER_H
#include <QHash>
#include <QPair>
namespace Mirall {
class NetrcParser
{
public:
typedef QPair<QString, QString> LoginPair;
NetrcParser(const QString &fileName = QString::null);
bool parse();
LoginPair find(const QString &machine);
private:
void tryAddEntryAndClear(QString &machine, LoginPair &pair, bool &isDefault);
QHash<QString, LoginPair> _entries;
LoginPair _default;
QString _fileName;
};
} // namespace Mirall
#endif // NETRCPARSER_H

View file

@ -31,15 +31,26 @@
#include "owncloudcmd.h"
#include "simplesslerrorhandler.h"
#include "netrcparser.h"
#ifdef Q_OS_WIN32
#include <windows.h>
#else
#include <termios.h>
#endif
using namespace Mirall;
struct CmdOptions {
QString source_dir;
QString target_url;
QString config_directory;
QString user;
QString password;
QString proxy;
bool silent;
bool trustSSL;
bool useNetrc;
QString exclude;
};
@ -47,21 +58,59 @@ struct CmdOptions {
// So we have to use a global variable
CmdOptions *opts = 0;
int getauth(const char* prompt, char* buf, size_t len, int a, int b, void *userdata)
class EchoDisabler
{
Q_UNUSED(a) Q_UNUSED(b) Q_UNUSED(userdata)
std::cout << "** Authentication required: \n" << prompt << std::endl;
std::string s;
if(opts && opts->trustSSL) {
s = "yes";
} else {
std::getline(std::cin, s);
public:
EchoDisabler()
{
#ifdef Q_OS_WIN
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
GetConsoleMode(hStdin, &mode);
SetConsoleMode(hStdin, mode & (~ENABLE_ECHO_INPUT));
#else
tcgetattr(STDIN_FILENO, &tios);
termios tios_new = tios;
tios_new.c_lflag &= ~ECHO;
tcsetattr(STDIN_FILENO, TCSANOW, &tios_new);
#endif
}
strncpy( buf, s.c_str(), len );
return 0;
~EchoDisabler()
{
#ifdef Q_OS_WIN
SetConsoleMode(hStdin, mode);
#else
tcsetattr(STDIN_FILENO, TCSANOW, &tios);
#endif
}
private:
#ifdef Q_OS_WIN
DWORD mode = 0;
#else
termios tios;
#endif
};
QString queryPassword(const QString &user)
{
EchoDisabler disabler;
std::cout << "Password for user " << qPrintable(user) << ": ";
std::string s;
std::getline(std::cin, s);
return QString::fromStdString(s);
}
class HttpCredentialsText : public HttpCredentials {
public:
HttpCredentialsText(const QString& user, const QString& password) : HttpCredentials(user, password) {}
QString queryPassword(bool *ok) {
if (ok) {
*ok = true;
}
return ::queryPassword(user());
}
};
void help()
{
std::cout << "owncloudcmd - command line ownCloud client tool." << std::endl;
@ -72,12 +121,15 @@ void help()
std::cout << "uses the setting from a configured sync client." << std::endl;
std::cout << std::endl;
std::cout << "Options:" << std::endl;
std::cout << " --silent Don't be so verbose" << std::endl;
std::cout << " --silent, -s Don't be so verbose" << std::endl;
std::cout << " --confdir = configdir: Read config from there." << std::endl;
std::cout << " --httpproxy = proxy: Specify a http proxy to use." << std::endl;
std::cout << " Proxy is http://server:port" << std::endl;
std::cout << " --trust Trust the SSL certification." << std::endl;
std::cout << " --exclude [file] exclude list file" << std::endl;
std::cout << " --user, -u [name] Use [name] as the login name" << std::endl;
std::cout << " --password, -p [pass] Use [pass] as password" << std::endl;
std::cout << " -n Use netrc (5) for login" << std::endl;
std::cout << "" << std::endl;
exit(1);
@ -118,10 +170,16 @@ void parseOptions( const QStringList& app_args, CmdOptions *options )
options->config_directory = it.next();
} else if( option == "--httpproxy" && !it.peekNext().startsWith("-")) {
options->proxy = it.next();
} else if( option == "--silent") {
} else if( option == "-s" || option == "--silent") {
options->silent = true;
} else if( option == "--trust") {
options->trustSSL = true;
} else if( option == "-n") {
options->useNetrc = true;
} else if( (option == "-u" || option == "--user") && !it.peekNext().startsWith("-") ) {
options->user = it.next();
} else if( (option == "-p" || option == "--password") && !it.peekNext().startsWith("-") ) {
options->user = it.next();
} else if( option == "--exclude" && !it.peekNext().startsWith("-") ) {
options->exclude = it.next();
} else {
@ -140,26 +198,54 @@ int main(int argc, char **argv) {
CmdOptions options;
options.silent = false;
options.trustSSL = false;
options.useNetrc = false;
ClientProxy clientProxy;
parseOptions( app.arguments(), &options );
QUrl url(options.target_url.toUtf8());
if (url.userName().isEmpty()) {
std::cout << "** Please enter the username:" << std::endl;
std::string s;
std::getline(std::cin, s);
url.setUserName(QString::fromStdString(s));
}
if (url.password().isEmpty()) {
std::cout << "** Please enter the password:" << std::endl;
std::string s;
std::getline(std::cin, s);
url.setPassword(QString::fromStdString(s));
QUrl url = QUrl::fromUserInput(options.target_url);
// Fetch username and password. If empty, try to retrieve
// from URL and strip URL
QString user;
QString password;
if (options.useNetrc) {
NetrcParser parser;
if (parser.parse()) {
NetrcParser::LoginPair pair = parser.find(url.host());
user = pair.first;
password = pair.second;
}
} else {
user = options.user;
if (user.isEmpty()) {
user = url.userName();
}
password = options.password;
if (password.isEmpty()) {
password = url.password();
}
if (user.isEmpty()) {
std::cout << "Please enter user name: ";
std::string s;
std::getline(std::cin, s);
user = QString::fromStdString(s);
}
if (password.isEmpty()) {
password = queryPassword(user);
}
}
QUrl originalUrl = url;
// ### ensure URL is free of credentials
if (url.userName().isEmpty()) {
url.setUserName(user);
}
if (url.password().isEmpty()) {
url.setPassword(password);
}
Account account;
@ -171,16 +257,19 @@ int main(int argc, char **argv) {
SimpleSslErrorHandler *sslErrorHandler = new SimpleSslErrorHandler;
HttpCredentials *cred = new HttpCredentialsText(user, password);
account.setUrl(url);
account.setCredentials(new HttpCredentials(url.userName(), url.password()));
account.setCredentials(cred);
account.setSslErrorHandler(sslErrorHandler);
AccountManager::instance()->setAccount(&account);
restart_sync:
CSYNC *_csync_ctx;
if( csync_create( &_csync_ctx, options.source_dir.toUtf8(),
originalUrl.toEncoded().constData()) < 0 ) {
url.toEncoded().constData()) < 0 ) {
qFatal("Unable to create csync-context!");
return EXIT_FAILURE;
}
@ -192,7 +281,7 @@ restart_sync:
csync_set_log_level(options.silent ? 1 : 11);
opts = &options;
csync_set_auth_callback( _csync_ctx, getauth );
cred->syncContextPreInit(_csync_ctx);
if( csync_init( _csync_ctx ) < 0 ) {
qFatal("Could not initialize csync!");
@ -239,8 +328,9 @@ restart_sync:
csync_add_exclude_list(_csync_ctx, options.exclude.toLocal8Bit());
}
OwncloudCmd owncloudCmd;
cred->syncContextPreStart(_csync_ctx);
OwncloudCmd owncloudCmd;
SyncJournalDb db(options.source_dir);
SyncEngine engine(_csync_ctx, options.source_dir, QUrl(options.target_url).path(), folder, &db);
QObject::connect(&engine, SIGNAL(finished()), &app, SLOT(quit()));

View file

@ -148,7 +148,7 @@ void OwncloudHttpCredsPage::setErrorString(const QString& err)
AbstractCredentials* OwncloudHttpCredsPage::getCredentials() const
{
return new HttpCredentials(_ui.leUsername->text(), _ui.lePassword->text());
return new HttpCredentialsGui(_ui.leUsername->text(), _ui.lePassword->text());
}
void OwncloudHttpCredsPage::setConfigExists(bool config)

View file

@ -26,5 +26,6 @@ if( UNIX AND NOT APPLE )
endif(UNIX AND NOT APPLE)
owncloud_add_test(CSyncSqlite "")
owncloud_add_test(NetrcParser ../src/owncloudcmd/netrcparser.cpp)

76
test/testnetrcparser.h Normal file
View file

@ -0,0 +1,76 @@
/*
* This software is in the public domain, furnished "as is", without technical
* support, and with no warranty, express or implied, as to its usefulness for
* any purpose.
* */
#ifndef MIRALL_INOTIFYWATCHER_H
#define MIRALL_INOTIFYWATCHER_H
#include <QtTest>
#include "owncloudcmd/netrcparser.h"
using namespace Mirall;
namespace {
const char testfileC[] = "netrctest";
const char testfileWithDefaultC[] = "netrctestDefault";
const char testfileEmptyC[] = "netrctestEmpty";
}
class TestNetrcParser : public QObject
{
Q_OBJECT
private slots:
void initTestCase() {
QFile netrc(testfileC);
QVERIFY(netrc.open(QIODevice::WriteOnly));
netrc.write("machine foo login bar password baz\n");
netrc.write("machine broken login bar2 dontbelonghere password baz2 extratokens dontcare andanother\n");
netrc.write("machine\nfunnysplit\tlogin bar3 password baz3\n");
QFile netrcWithDefault(testfileWithDefaultC);
QVERIFY(netrcWithDefault.open(QIODevice::WriteOnly));
netrcWithDefault.write("machine foo login bar password baz\n");
netrcWithDefault.write("default login user password pass\n");
QFile netrcEmpty(testfileEmptyC);
QVERIFY(netrcEmpty.open(QIODevice::WriteOnly));
}
void cleanupTestCase() {
QVERIFY(QFile::remove(testfileC));
QVERIFY(QFile::remove(testfileWithDefaultC));
QVERIFY(QFile::remove(testfileEmptyC));
}
void testValidNetrc() {
NetrcParser parser(testfileC);
QVERIFY(parser.parse());
QCOMPARE(parser.find("foo"), qMakePair(QString("bar"), QString("baz")));
QCOMPARE(parser.find("broken"), qMakePair(QString("bar2"), QString("baz2")));
QCOMPARE(parser.find("funnysplit"), qMakePair(QString("bar3"), QString("baz3")));
}
void testEmptyNetrc() {
NetrcParser parser(testfileEmptyC);
QVERIFY(!parser.parse());
QCOMPARE(parser.find("foo"), qMakePair(QString(), QString()));
}
void testValidNetrcWithDefault() {
NetrcParser parser(testfileWithDefaultC);
QVERIFY(parser.parse());
QCOMPARE(parser.find("foo"), qMakePair(QString("bar"), QString("baz")));
QCOMPARE(parser.find("dontknow"), qMakePair(QString("user"), QString("pass")));
}
void testInvalidNetrc() {
NetrcParser parser("/invalid");
QVERIFY(!parser.parse());
}
};
#endif