pcloudcc-lneely/pCloudCC/pclsync_lib.cpp

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;
}