450 lines
13 KiB
C++
450 lines
13 KiB
C++
/*
|
|
Copyright (c) 2013-2015 pCloud Ltd. All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions
|
|
are met: Redistributions of source code must retain the above
|
|
copyright notice, this list of conditions and the following
|
|
disclaimer. Redistributions in binary form must reproduce the above
|
|
copyright notice, this list of conditions and the following
|
|
disclaimer in the documentation and/or other materials provided with
|
|
the distribution. Neither the name of pCloud Ltd nor the names of
|
|
its contributors may be used to endorse or promote products derived
|
|
from this software without specific prior written permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL pCloud
|
|
Ltd BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
|
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
|
DAMAGE.
|
|
*/
|
|
|
|
#include "pclsync_lib.h"
|
|
#include "pcompat.h"
|
|
#include "psynclib.h"
|
|
|
|
#include <iostream>
|
|
|
|
#include <iostream>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <string>
|
|
#include <termios.h>
|
|
#include <unistd.h>
|
|
|
|
namespace cc = console_client;
|
|
namespace clib = cc::clibrary;
|
|
|
|
static const std::string client_name = "pCloud CC v3.0.0";
|
|
|
|
clib::pclsync_lib::pclsync_lib() : status_(new pstatus_struct_()),
|
|
was_init_(false),
|
|
setup_crypto_(false) {}
|
|
|
|
clib::pclsync_lib::~pclsync_lib() {}
|
|
|
|
const std::string&
|
|
clib::pclsync_lib::get_username() {
|
|
return username_;
|
|
}
|
|
|
|
const std::string &
|
|
clib::pclsync_lib::get_password() {
|
|
return password_;
|
|
}
|
|
|
|
const std::string &
|
|
clib::pclsync_lib::get_crypto_pass() {
|
|
return crypto_pass_;
|
|
};
|
|
|
|
const std::string &
|
|
clib::pclsync_lib::get_mount() {
|
|
return mount_;
|
|
}
|
|
|
|
void
|
|
clib::pclsync_lib::set_username(const std::string &arg) {
|
|
username_ = arg;
|
|
}
|
|
void
|
|
clib::pclsync_lib::set_password(const std::string &arg) {
|
|
password_ = arg;
|
|
}
|
|
void
|
|
clib::pclsync_lib::set_crypto_pass(const std::string &arg) {
|
|
crypto_pass_ = arg;
|
|
};
|
|
void
|
|
clib::pclsync_lib::set_mount(const std::string &arg) {
|
|
mount_ = arg;
|
|
}
|
|
void
|
|
clib::pclsync_lib::set_savepass(bool s) {
|
|
save_pass_ = s;
|
|
}
|
|
void
|
|
clib::pclsync_lib::setupsetup_crypto(bool p) {
|
|
setup_crypto_ = p;
|
|
}
|
|
void
|
|
clib::pclsync_lib::set_newuser(bool p) {
|
|
newuser_ = p;
|
|
}
|
|
void
|
|
clib::pclsync_lib::set_daemon(bool p) {
|
|
daemon_ = p;
|
|
}
|
|
void
|
|
clib::pclsync_lib::set_status_callback(status_callback_t p) {
|
|
status_callback_ = p;
|
|
}
|
|
|
|
clib::pclsync_lib &
|
|
clib::pclsync_lib::get_lib() {
|
|
static clib::pclsync_lib g_lib;
|
|
return g_lib;
|
|
}
|
|
|
|
static std::string
|
|
exec(const char *cmd) {
|
|
FILE *pipe;
|
|
char buffer[128];
|
|
std::string result = "";
|
|
|
|
pipe = popen(cmd, "r");
|
|
if (!pipe) {
|
|
return "ERROR";
|
|
}
|
|
while (!feof(pipe)) {
|
|
if (fgets(buffer, 128, pipe)) {
|
|
result += buffer;
|
|
}
|
|
}
|
|
pclose(pipe);
|
|
return result;
|
|
}
|
|
|
|
char *
|
|
clib::pclsync_lib::get_token() { return psync_get_token(); }
|
|
|
|
void
|
|
clib::pclsync_lib::get_pass_from_console() {
|
|
do_get_pass_from_console(password_);
|
|
}
|
|
|
|
void
|
|
clib::pclsync_lib::get_cryptopass_from_console() {
|
|
do_get_pass_from_console(crypto_pass_);
|
|
}
|
|
|
|
void
|
|
clib::pclsync_lib::do_get_pass_from_console(std::string &password) {
|
|
if (daemon_) {
|
|
std::cout << "Not able to read password when started as daemon."
|
|
<< std::endl;
|
|
exit(1);
|
|
}
|
|
#ifdef P_OS_POSIX
|
|
termios oldt;
|
|
tcgetattr(STDIN_FILENO, &oldt);
|
|
termios newt = oldt;
|
|
newt.c_lflag &= ~ECHO;
|
|
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
|
|
std::cout << "Please, enter password" << std::endl;
|
|
getline(std::cin, password);
|
|
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
|
|
#else
|
|
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
|
|
DWORD modeoff;
|
|
DWORD modeon;
|
|
DWORD mode;
|
|
GetConsoleMode(hStdin, &mode);
|
|
modeoff = mode & ~ENABLE_ECHO_INPUT;
|
|
modeon = mode | ENABLE_ECHO_INPUT;
|
|
SetConsoleMode(hStdin, modeoff);
|
|
std::cout << "Please, enter password" << std::endl;
|
|
getline(std::cin, password);
|
|
SetConsoleMode(hStdin, modeon);
|
|
#endif
|
|
}
|
|
|
|
void
|
|
event_handler(psync_eventtype_t event, psync_eventdata_t eventdata) {
|
|
if (event < PEVENT_FIRST_USER_EVENT) {
|
|
if (event & PEVENT_TYPE_FOLDER) {
|
|
std::cout << "folder event=" << event
|
|
<< ", syncid=" << eventdata.folder->syncid
|
|
<< ", folderid=" << eventdata.folder->folderid
|
|
<< ", name=" << eventdata.folder->name
|
|
<< ", local=" << eventdata.folder->localpath
|
|
<< ", remote=" << eventdata.folder->remotepath << std::endl;
|
|
} else {
|
|
std::cout << "file event=" << event
|
|
<< ", syncid=" << eventdata.folder->syncid
|
|
<< ", file=" << eventdata.file->fileid
|
|
<< ", name=" << eventdata.file->name
|
|
<< ", local=" << eventdata.file->localpath
|
|
<< ", remote=" << eventdata.file->remotepath << std::endl;
|
|
}
|
|
} else if (event >= PEVENT_FIRST_SHARE_EVENT) {
|
|
std::cout << "share event=" << event
|
|
<< ", folderid=" << eventdata.share->folderid
|
|
<< ", sharename=" << eventdata.share->sharename
|
|
<< ", email=" << eventdata.share->toemail
|
|
<< ", message=" << eventdata.share->message
|
|
<< ", userid=" << eventdata.share->userid
|
|
<< ", shareid=" << eventdata.share->shareid
|
|
<< ", sharerequestid=" << eventdata.share->sharerequestid
|
|
<< ", created=" << eventdata.share->created
|
|
<< ", canread=" << eventdata.share->canread
|
|
<< ", cancreate=" << eventdata.share->cancreate
|
|
<< ", canmodify=" << eventdata.share->canmodify
|
|
<< ", candelete=" << eventdata.share->candelete << std::endl;
|
|
} else {
|
|
std::cout << "event" << event << std::endl;
|
|
}
|
|
}
|
|
|
|
static int
|
|
lib_setup_cripto() {
|
|
int ret = 0;
|
|
ret = psync_crypto_issetup();
|
|
if (ret) {
|
|
ret = psync_crypto_start(clib::pclsync_lib::get_lib()
|
|
.get_crypto_pass().c_str());
|
|
std::cout << "crypto is setup, login result=" << ret << std::endl;
|
|
} else {
|
|
std::cout << "crypto is not setup" << std::endl;
|
|
ret = psync_crypto_setup(clib::pclsync_lib::get_lib()
|
|
.get_crypto_pass().c_str(), "no hint");
|
|
if (ret) {
|
|
std::cout << "crypto setup failed" << std::endl;
|
|
} else {
|
|
ret = psync_crypto_start(
|
|
clib::pclsync_lib::get_lib().get_crypto_pass().c_str());
|
|
std::cout << "crypto setup successful, start=" << ret << std::endl;
|
|
ret = psync_crypto_mkdir(0, "Crypto", NULL, NULL);
|
|
std::cout << "creating folder=" << ret << std::endl;
|
|
}
|
|
}
|
|
clib::pclsync_lib::get_lib().crypto_on_ = true;
|
|
return ret;
|
|
}
|
|
|
|
static const char *
|
|
status2string(uint32_t status) {
|
|
switch (status) {
|
|
case PSTATUS_READY:
|
|
return "READY";
|
|
case PSTATUS_DOWNLOADING:
|
|
return "DOWNLOADING";
|
|
case PSTATUS_UPLOADING:
|
|
return "UPLOADING";
|
|
case PSTATUS_DOWNLOADINGANDUPLOADING:
|
|
return "DOWNLOADINGANDUPLOADING";
|
|
case PSTATUS_LOGIN_REQUIRED:
|
|
return "LOGIN_REQUIRED";
|
|
case PSTATUS_BAD_LOGIN_DATA:
|
|
return "BAD_LOGIN_DATA";
|
|
case PSTATUS_BAD_LOGIN_TOKEN:
|
|
return "BAD_LOGIN_TOKEN";
|
|
case PSTATUS_ACCOUNT_FULL:
|
|
return "ACCOUNT_FULL";
|
|
case PSTATUS_DISK_FULL:
|
|
return "DISK_FULL";
|
|
case PSTATUS_PAUSED:
|
|
return "PAUSED";
|
|
case PSTATUS_STOPPED:
|
|
return "STOPPED";
|
|
case PSTATUS_OFFLINE:
|
|
return "OFFLINE";
|
|
case PSTATUS_CONNECTING:
|
|
return "CONNECTING";
|
|
case PSTATUS_SCANNING:
|
|
return "SCANNING";
|
|
case PSTATUS_USER_MISMATCH:
|
|
return "USER_MISMATCH";
|
|
case PSTATUS_ACCOUT_EXPIRED:
|
|
return "ACCOUT_EXPIRED";
|
|
default:
|
|
return "Unrecognized status";
|
|
}
|
|
}
|
|
|
|
static void
|
|
status_change(pstatus_t *status) {
|
|
static int cryptocheck = 0;
|
|
static int mount_set = 0;
|
|
|
|
char *err;
|
|
err = (char *)malloc(1024);
|
|
|
|
std::cout << "Down: " << status->downloadstr << "| Up: " << status->uploadstr
|
|
<< ", status is " << status2string(status->status) << std::endl;
|
|
*clib::pclsync_lib::get_lib().status_ = *status;
|
|
if (status->status == PSTATUS_LOGIN_REQUIRED) {
|
|
if (clib::pclsync_lib::get_lib().get_password().empty()) {
|
|
clib::pclsync_lib::get_lib().get_pass_from_console();
|
|
}
|
|
|
|
// std::cout << "Username: " <<
|
|
// clib::pclsync_lib::get_lib().get_username().c_str() << "| Password: " <<
|
|
// clib::pclsync_lib::get_lib().get_password().c_str() << std::endl;
|
|
psync_set_user_pass(clib::pclsync_lib::get_lib().get_username().c_str(),
|
|
clib::pclsync_lib::get_lib().get_password().c_str(),
|
|
(int)clib::pclsync_lib::get_lib().save_pass_);
|
|
std::cout << "logging in" << std::endl;
|
|
} else if (status->status == PSTATUS_BAD_LOGIN_DATA) {
|
|
if (!clib::pclsync_lib::get_lib().newuser_) {
|
|
clib::pclsync_lib::get_lib().get_pass_from_console();
|
|
psync_set_user_pass(clib::pclsync_lib::get_lib().get_username().c_str(),
|
|
clib::pclsync_lib::get_lib().get_password().c_str(),
|
|
(int)clib::pclsync_lib::get_lib().save_pass_);
|
|
} else {
|
|
std::cout << "registering" << std::endl;
|
|
if (psync_register(clib::pclsync_lib::get_lib().get_username().c_str(),
|
|
clib::pclsync_lib::get_lib().get_password().c_str(),
|
|
1, "bineapi.pcloud.com", 2, &err)) {
|
|
std::cout << "both login and registration failed" << std::endl;
|
|
exit(1);
|
|
} else {
|
|
std::cout << "registered, logging in" << std::endl;
|
|
psync_set_user_pass(clib::pclsync_lib::get_lib().get_username().c_str(),
|
|
clib::pclsync_lib::get_lib().get_password().c_str(),
|
|
(int)clib::pclsync_lib::get_lib().save_pass_);
|
|
}
|
|
}
|
|
}
|
|
if (status->status == PSTATUS_READY || status->status == PSTATUS_UPLOADING ||
|
|
status->status == PSTATUS_DOWNLOADING ||
|
|
status->status == PSTATUS_DOWNLOADINGANDUPLOADING) {
|
|
if (!cryptocheck) {
|
|
cryptocheck = 1;
|
|
if (clib::pclsync_lib::get_lib().setup_crypto_) {
|
|
lib_setup_cripto();
|
|
}
|
|
}
|
|
psync_fs_start();
|
|
}
|
|
if (clib::pclsync_lib::get_lib().status_callback_) {
|
|
clib::pclsync_lib::get_lib()
|
|
.status_callback_((int)status->status,
|
|
status2string(status->status));
|
|
}
|
|
}
|
|
|
|
int
|
|
clib::pclsync_lib::start_crypto(const char *pass, void *rep) {
|
|
std::cout << "calling startcrypto pass: " << pass << std::endl;
|
|
get_lib().crypto_pass_ = pass;
|
|
return lib_setup_cripto();
|
|
}
|
|
|
|
int
|
|
clib::pclsync_lib::stop_crypto(const char *path, void *rep) {
|
|
int res = -1;
|
|
psync_crypto_stop();
|
|
get_lib().crypto_on_ = false;
|
|
return res;
|
|
}
|
|
|
|
int
|
|
clib::pclsync_lib::finalize(const char *path, void *rep) {
|
|
psync_destroy();
|
|
exit(0);
|
|
}
|
|
|
|
int
|
|
clib::pclsync_lib::list_sync_folders(const char *path, void *rep) {
|
|
psync_folder_list_t *folders = psync_get_sync_list();
|
|
rep = psync_malloc(sizeof(*folders));
|
|
memcpy(rep, folders, sizeof(*folders));
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
clib::pclsync_lib::init()
|
|
{
|
|
// std::string& username, std::string& password,
|
|
// std::string* crypto_pass, int setup_crypto, int usesrypto_userpass)
|
|
// std::string software_string = exec("lsb_release -ds");
|
|
|
|
std::string software_string;
|
|
int isfsautostart;
|
|
char *username_old;
|
|
|
|
psync_set_software_string(client_name.c_str());
|
|
|
|
if (setup_crypto_ && crypto_pass_.empty()) {
|
|
return 3;
|
|
}
|
|
|
|
if (psync_init()) {
|
|
std::cout << "init failed\n";
|
|
return 1;
|
|
}
|
|
|
|
was_init_ = true;
|
|
|
|
if (!get_mount().empty()) {
|
|
psync_set_string_setting("fsroot", get_mount().c_str());
|
|
}
|
|
|
|
// _tunnel = psync_ssl_tunnel_start("127.0.0.1", 9443, "62.210.116.50", 443);
|
|
|
|
isfsautostart = psync_get_bool_setting("autostartfs");
|
|
psync_start_sync(status_change, event_handler);
|
|
|
|
username_old = psync_get_username();
|
|
if (username_old) {
|
|
if (username_.compare(username_old) != 0) {
|
|
std::cout << "logged in with user " << username_old << ", not "
|
|
<< username_ << ", unlinking" << std::endl;
|
|
psync_unlink();
|
|
psync_free(username_old);
|
|
return 2;
|
|
}
|
|
psync_free(username_old);
|
|
}
|
|
|
|
psync_add_overlay_callback(20, &clib::pclsync_lib::start_crypto);
|
|
psync_add_overlay_callback(21, &clib::pclsync_lib::stop_crypto);
|
|
psync_add_overlay_callback(22, &clib::pclsync_lib::finalize);
|
|
psync_add_overlay_callback(23, &clib::pclsync_lib::list_sync_folders);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
clib::pclsync_lib::login(const char *user, const char *pass, int save) {
|
|
set_username(user);
|
|
set_password(pass);
|
|
set_savepass(bool(save));
|
|
psync_set_user_pass(user, pass, save);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
clib::pclsync_lib::logout() {
|
|
set_password("");
|
|
psync_logout();
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
clib::pclsync_lib::unlink() {
|
|
set_username("");
|
|
set_password("");
|
|
psync_unlink();
|
|
return 0;
|
|
}
|
|
|