2924 lines
107 KiB
C
2924 lines
107 KiB
C
/* Copyright (c) 2013-2014 Anton Titov.
|
|
* Copyright (c) 2013-2014 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 "pcompat.h"
|
|
#include "pdiff.h"
|
|
#include "pstatus.h"
|
|
#include "psettings.h"
|
|
#include "plibs.h"
|
|
#include "papi.h"
|
|
#include "ptimer.h"
|
|
#include "psyncer.h"
|
|
#include "ptasks.h"
|
|
#include "pfolder.h"
|
|
#include "psyncer.h"
|
|
#include "pdownload.h"
|
|
#include "pcallbacks.h"
|
|
#include "pfileops.h"
|
|
#include "pfsxattr.h"
|
|
#include "pfs.h"
|
|
#include "pnotifications.h"
|
|
#include "pnetlibs.h"
|
|
#include "pcache.h"
|
|
#include "pbusinessaccount.h"
|
|
#include "publiclinks.h"
|
|
#include "pcontacts.h"
|
|
#include "pcloudcrypto.h"
|
|
#include "ppathstatus.h"
|
|
#include <ctype.h>
|
|
#include "ptools.h"
|
|
|
|
|
|
#define PSYNC_SQL_DOWNLOAD "synctype&"NTO_STR(PSYNC_DOWNLOAD_ONLY)"="NTO_STR(PSYNC_DOWNLOAD_ONLY)
|
|
|
|
typedef struct {
|
|
psync_eventtype_t eventid;
|
|
psync_share_event_t *event_data;
|
|
uint64_t touserid;
|
|
uint64_t fromuserid;
|
|
uint64_t teamid;
|
|
|
|
char *str;
|
|
} notify_paramst;
|
|
|
|
typedef struct {
|
|
uint64_t diffid;
|
|
uint32_t notificationid;
|
|
uint64_t publinkid;
|
|
uint64_t uploadlinkid;
|
|
} subscribed_ids;
|
|
|
|
static uint64_t used_quota=0, current_quota=0, free_quota=0;
|
|
static time_t last_event=0;
|
|
static psync_uint_t needdownload=0;
|
|
static psync_socket_t exceptionsockwrite=INVALID_SOCKET;
|
|
static pthread_mutex_t diff_mutex=PTHREAD_MUTEX_INITIALIZER;
|
|
static int initialdownload=0;
|
|
static paccount_cache_callback_t psync_cache_callback=NULL;
|
|
static uint32_t psync_is_business=0;
|
|
static unsigned char adapter_hash[PSYNC_FAST_HASH256_LEN];
|
|
int unlinked=0;
|
|
int tfa = 0;
|
|
|
|
void do_register_account_events_callback(paccount_cache_callback_t callback){
|
|
psync_cache_callback=callback;
|
|
}
|
|
|
|
static void psync_notify_cache_change(psync_changetype_t event){
|
|
paccount_cache_callback_t callback;
|
|
psync_changetype_t *chtype=psync_new(psync_changetype_t);
|
|
*chtype=event;
|
|
callback=psync_cache_callback;
|
|
if (callback)
|
|
psync_run_thread1("cache start callback", callback, chtype);
|
|
else
|
|
psync_free(chtype);
|
|
}
|
|
|
|
|
|
static void psync_diff_refresh_fs_add_folder(psync_folderid_t folderid);
|
|
static void do_send_eventdata(void * param);
|
|
|
|
static void delete_cached_crypto_keys(){
|
|
psync_sql_statement("DELETE FROM setting WHERE id IN ('crypto_public_key', 'crypto_private_key', 'crypto_private_iter', "\
|
|
"'crypto_private_salt', 'crypto_private_sha1', 'crypto_public_sha1')");
|
|
if (psync_sql_affected_rows()){
|
|
debug(D_NOTICE, "deleted cached crypto keys");
|
|
psync_cloud_crypto_clean_cache();
|
|
}
|
|
psync_sql_statement("DELETE FROM cryptofolderkey");
|
|
psync_sql_statement("DELETE FROM cryptofilekey");
|
|
}
|
|
|
|
void psync_delete_cached_crypto_keys(){
|
|
void delete_cached_crypto_keys();
|
|
}
|
|
|
|
static binresult *get_userinfo_user_digest(psync_socket *sock, const char *username, size_t userlen, const char *pwddig, const char *digest, uint32_t diglen,
|
|
const char *osversion, const char *appversion, const char *deviceid, const char *devicestring){
|
|
binparam params[]={P_STR("timeformat", "timestamp"),
|
|
P_LSTR("username", username, userlen),
|
|
P_LSTR("digest", digest, diglen),
|
|
P_LSTR("passworddigest", pwddig, PSYNC_SHA1_DIGEST_HEXLEN),
|
|
P_STR("osversion", osversion),
|
|
P_STR("appversion", appversion),
|
|
P_STR("deviceid", deviceid),
|
|
P_STR("device", devicestring),
|
|
P_BOOL("getauth", 1),
|
|
P_BOOL("getapiserver", 1),
|
|
P_BOOL("cryptokeyssign", 1),
|
|
P_BOOL("getlastsubscription", 1),
|
|
P_NUM("os", P_OS_ID)};
|
|
return send_command(sock, "login", params);
|
|
}
|
|
|
|
static binresult *get_userinfo_user_pass(psync_socket *sock, const char *username, const char *password, const char *osversion,
|
|
const char *appversion, const char *deviceid, const char *devicestring){
|
|
binparam empty_params[]={P_STR("MS", "sucks")};
|
|
psync_sha1_ctx ctx;
|
|
binresult *res, *ret;
|
|
const binresult *dig;
|
|
unsigned char *uc;
|
|
size_t ul, i;
|
|
unsigned char sha1bin[PSYNC_SHA1_DIGEST_LEN];
|
|
char sha1hex[PSYNC_SHA1_DIGEST_HEXLEN];
|
|
|
|
res=send_command(sock, "getdigest", empty_params);
|
|
|
|
if (!res)
|
|
return res;
|
|
|
|
if (psync_find_result(res, "result", PARAM_NUM)->num!=0){
|
|
psync_free(res);
|
|
return NULL;
|
|
}
|
|
|
|
dig=psync_find_result(res, "digest", PARAM_STR);
|
|
|
|
debug(D_NOTICE, "got digest %s", dig->str);
|
|
|
|
ul=strlen(username);
|
|
uc=psync_new_cnt(unsigned char, ul);
|
|
|
|
for (i=0; i<ul; i++)
|
|
uc[i]=tolower(username[i]);
|
|
|
|
psync_sha1(uc, ul, sha1bin);
|
|
psync_free(uc);
|
|
psync_binhex(sha1hex, sha1bin, PSYNC_SHA1_DIGEST_LEN);
|
|
psync_sha1_init(&ctx);
|
|
psync_sha1_update(&ctx, password, strlen(password));
|
|
psync_sha1_update(&ctx, sha1hex, PSYNC_SHA1_DIGEST_HEXLEN);
|
|
psync_sha1_update(&ctx, dig->str, dig->length);
|
|
psync_sha1_final(sha1bin, &ctx);
|
|
psync_binhex(sha1hex, sha1bin, PSYNC_SHA1_DIGEST_LEN);
|
|
|
|
ret=get_userinfo_user_digest(sock, username, ul, sha1hex, dig->str, dig->length, osversion, appversion, deviceid, devicestring);
|
|
|
|
psync_free(res);
|
|
return ret;
|
|
}
|
|
|
|
char *generate_device_id(){
|
|
psync_sql_res *q;
|
|
unsigned char deviceidbin[16];
|
|
char deviceidhex[32+2];
|
|
psync_ssl_rand_strong(deviceidbin, sizeof(deviceidbin));
|
|
psync_binhex(deviceidhex, deviceidbin, sizeof(deviceidbin));
|
|
deviceidhex[sizeof(deviceidbin)*2]=0;
|
|
q=psync_sql_prep_statement("REPLACE INTO setting (id, value) VALUES ('deviceid', ?)");
|
|
psync_sql_bind_string(q, 1, deviceidhex);
|
|
psync_sql_run_free(q);
|
|
return psync_strdup(deviceidhex);
|
|
}
|
|
|
|
int check_active_subscribtion(const binresult *res){
|
|
const binresult *sub;
|
|
char *status;
|
|
sub = psync_check_result(res, "lastsubscription", PARAM_HASH);
|
|
if (sub)
|
|
{
|
|
status = psync_strdup(psync_find_result(sub, "status", PARAM_STR)->str);
|
|
if (!strcmp(status, "active")){
|
|
psync_free(status);
|
|
return 1;
|
|
}
|
|
psync_free(status);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int check_user_relocated(uint64_t luserid, psync_socket* sock){
|
|
binresult* res;
|
|
const binresult* userids;
|
|
uint64_t result,userid;
|
|
int cnt,i,lid,clid;
|
|
binresult* id;
|
|
binparam params[] = { P_STR("timeformat", "timestamp"),
|
|
P_STR("auth", psync_my_auth)};
|
|
res = send_command(sock, "getolduserids", params);
|
|
if(unlikely_log(!res)) return 0;
|
|
result = psync_find_result(res, "result", PARAM_NUM)->num;
|
|
if(result){
|
|
debug(D_NOTICE, "getolduserids returned error %lu %s", (unsigned long)result, psync_find_result(res, "error", PARAM_STR)->str);
|
|
psync_free(res);
|
|
return 0;
|
|
}
|
|
|
|
userids = psync_find_result(res, "userids", PARAM_ARRAY);
|
|
cnt = userids->length;
|
|
if (!cnt) {
|
|
psync_free(res);
|
|
return 0;
|
|
}
|
|
|
|
clid = psync_sql_cellint("SELECT value FROM setting WHERE id='last_logged_location_id'", 1);
|
|
|
|
for (i = 0; i < cnt; ++i) {
|
|
id = userids->array[i];
|
|
userid = psync_find_result(id, "userid", PARAM_NUM)->num;
|
|
lid = psync_find_result(id, "locationid", PARAM_NUM)->num;
|
|
if (luserid == userid && lid == clid) return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static psync_socket *get_connected_socket(){
|
|
char *auth, *user, *pass, *deviceid, *osversion, *devicestring, *binapi, *chrUserid;
|
|
const char *appversion;
|
|
psync_socket *sock;
|
|
binresult *res;
|
|
const binresult *cres;
|
|
psync_sql_res *q;
|
|
uint64_t result, userid, luserid, locationid;
|
|
int saveauth, isbusiness, cryptosetup, digest, lid, isFirstLogin;
|
|
|
|
digest=1;
|
|
psync_free(psync_my_2fa_token);
|
|
auth=user=pass=psync_my_2fa_token=NULL;
|
|
psync_is_business=0;
|
|
deviceid=psync_sql_cellstr("SELECT value FROM setting WHERE id='deviceid'");
|
|
|
|
if (!deviceid)
|
|
deviceid=generate_device_id();
|
|
|
|
debug(D_NOTICE, "using deviceid %s", deviceid);
|
|
appversion=psync_appname();
|
|
devicestring=psync_device_string();
|
|
|
|
while (1){
|
|
psync_free(auth);
|
|
psync_free(user);
|
|
psync_free(pass);
|
|
psync_wait_status(PSTATUS_TYPE_RUN, PSTATUS_RUN_RUN|PSTATUS_RUN_PAUSE);
|
|
|
|
auth=psync_sql_cellstr("SELECT value FROM setting WHERE id='auth'");
|
|
user=psync_sql_cellstr("SELECT value FROM setting WHERE id='user'");
|
|
pass=psync_sql_cellstr("SELECT value FROM setting WHERE id='pass'");
|
|
if (user && !user[0]) user = NULL;
|
|
if (pass && !pass[0]) pass = NULL;
|
|
if (auth && !auth[0]) auth = NULL;
|
|
|
|
chrUserid = psync_sql_cellstr("SELECT value FROM setting WHERE id='userid'");
|
|
|
|
//If there is no userid row, we assume it's first login, after instalation.
|
|
//Rise a flag so we can send a first login event later.
|
|
if (chrUserid == NULL) {
|
|
isFirstLogin = 1;
|
|
}
|
|
else {
|
|
isFirstLogin = 0;
|
|
}
|
|
|
|
|
|
if (!auth && psync_my_auth[0])
|
|
auth=psync_strdup(psync_my_auth);
|
|
if (!user && psync_my_user)
|
|
user=psync_strdup(psync_my_user);
|
|
if (!pass && psync_my_pass)
|
|
pass=psync_strdup(psync_my_pass);
|
|
if (!auth && (!pass || !user)){
|
|
#if defined(P_OS_LINUX)
|
|
if(tfa){
|
|
tfa=0;
|
|
psync_milisleep(1000);
|
|
debug(D_WARNING, "tfa sleep");
|
|
continue;
|
|
}
|
|
#endif
|
|
psync_set_status(PSTATUS_TYPE_AUTH, PSTATUS_AUTH_REQUIRED);
|
|
psync_wait_status(PSTATUS_TYPE_AUTH, PSTATUS_AUTH_PROVIDED);
|
|
continue;
|
|
}
|
|
|
|
psync_set_status(PSTATUS_TYPE_AUTH, PSTATUS_AUTH_PROVIDED);
|
|
saveauth=psync_setting_get_bool(_PS(saveauth));
|
|
sock=psync_api_connect(apiserver, psync_setting_get_bool(_PS(usessl)));
|
|
|
|
if (unlikely_log(!sock)){
|
|
psync_set_status(PSTATUS_TYPE_ONLINE, PSTATUS_ONLINE_OFFLINE);
|
|
psync_milisleep(PSYNC_SLEEP_BEFORE_RECONNECT);
|
|
continue;
|
|
}
|
|
osversion=psync_deviceos();
|
|
|
|
if (psync_my_2fa_token && psync_my_2fa_code_type && psync_my_2fa_code[0]){
|
|
const char *method=psync_my_2fa_code_type==1?"tfa_login":"tfa_loginwithrecoverycode";
|
|
binparam params[]={P_STR("timeformat", "timestamp"),
|
|
P_STR("token", psync_my_2fa_token),
|
|
P_STR("code", psync_my_2fa_code),
|
|
P_BOOL("trustdevice", psync_my_2fa_trust),
|
|
P_STR("osversion", osversion),
|
|
P_STR("appversion", appversion),
|
|
P_STR("deviceid", deviceid),
|
|
P_STR("device", devicestring),
|
|
P_BOOL("getauth", 1),
|
|
P_BOOL("cryptokeyssign", 1),
|
|
P_BOOL("getapiserver", 1),
|
|
P_BOOL("getlastsubscription", 1),
|
|
P_NUM("os", P_OS_ID)};
|
|
res=send_command(sock, method, params);
|
|
}
|
|
else if (user && pass && pass[0]){
|
|
if (digest){
|
|
res=get_userinfo_user_pass(sock, user, pass, osversion, appversion, deviceid, devicestring);
|
|
}
|
|
else{
|
|
binparam params[]={P_STR("timeformat", "timestamp"),
|
|
P_STR("username", user),
|
|
P_STR("password", pass),
|
|
P_STR("osversion", osversion),
|
|
P_STR("appversion", appversion),
|
|
P_STR("deviceid", deviceid),
|
|
P_STR("device", devicestring),
|
|
P_BOOL("getauth", 1),
|
|
P_BOOL("cryptokeyssign", 1),
|
|
P_BOOL("getapiserver", 1),
|
|
P_BOOL("getlastsubscription", 1),
|
|
P_NUM("os", P_OS_ID)};
|
|
res=send_command(sock, "login", params);
|
|
}
|
|
}
|
|
else {
|
|
binparam params[]={P_STR("timeformat", "timestamp"),
|
|
P_STR("auth", auth),
|
|
P_STR("osversion", osversion),
|
|
P_STR("appversion", appversion),
|
|
P_STR("deviceid", deviceid),
|
|
P_STR("device", devicestring),
|
|
P_BOOL("getauth", 1),
|
|
P_BOOL("cryptokeyssign", 1),
|
|
P_BOOL("getapiserver", 1),
|
|
P_BOOL("getlastsubscription", 1),
|
|
P_NUM("os", P_OS_ID)};
|
|
res=send_command(sock, "userinfo", params);
|
|
}
|
|
|
|
psync_free(osversion);
|
|
|
|
if (unlikely_log(!res)){
|
|
psync_socket_close(sock);
|
|
psync_set_status(PSTATUS_TYPE_ONLINE, PSTATUS_ONLINE_OFFLINE);
|
|
psync_milisleep(PSYNC_SLEEP_BEFORE_RECONNECT);
|
|
psync_api_conn_fail_inc();
|
|
continue;
|
|
}
|
|
|
|
psync_api_conn_fail_reset();
|
|
result=psync_find_result(res, "result", PARAM_NUM)->num;
|
|
|
|
if (unlikely(result)){
|
|
debug(D_NOTICE, "userinfo returned error %lu %s", (unsigned long)result, psync_find_result(res, "error", PARAM_STR)->str);
|
|
// here we only handle statuses that need to access the result
|
|
if (result==2297){
|
|
psync_free(psync_my_2fa_token);
|
|
psync_my_2fa_token=psync_strdup(psync_find_result(res, "token", PARAM_STR)->str);
|
|
psync_my_2fa_has_devices=psync_find_result(res, "hasdevices", PARAM_BOOL)->num;
|
|
psync_my_2fa_type=psync_find_result(res, "tfatype", PARAM_NUM)->num;
|
|
psync_my_2fa_code_type=0;
|
|
psync_my_2fa_code[0]=0;
|
|
psync_set_status(PSTATUS_TYPE_AUTH, PSTATUS_AUTH_TFAREQ);
|
|
psync_wait_status(PSTATUS_TYPE_AUTH, PSTATUS_AUTH_PROVIDED);
|
|
psync_socket_close(sock);
|
|
psync_free(res);
|
|
continue;
|
|
}
|
|
|
|
if (result==2306){
|
|
psync_free(psync_my_verify_token);
|
|
psync_my_verify_token = psync_strdup(psync_find_result(res, "verifytoken", PARAM_STR)->str);
|
|
psync_set_status(PSTATUS_TYPE_AUTH, PSTATUS_AUTH_VERIFYREQ);
|
|
psync_wait_status(PSTATUS_TYPE_AUTH, PSTATUS_AUTH_PROVIDED);
|
|
psync_socket_close(sock);
|
|
psync_free(res);
|
|
continue;
|
|
}
|
|
|
|
if (result==2321){
|
|
cres=psync_check_result(res, "location", PARAM_HASH);
|
|
if (cres){
|
|
binapi=psync_strdup(psync_find_result(cres, "binapi", PARAM_STR)->str);
|
|
|
|
locationid=psync_find_result(cres, "id", PARAM_NUM)->num;
|
|
psync_set_apiserver(binapi,locationid);
|
|
}
|
|
|
|
psync_socket_close(sock);
|
|
psync_free(res);
|
|
continue;
|
|
}
|
|
|
|
if(result==2330){
|
|
psync_set_apiserver(PSYNC_API_HOST, PSYNC_LOCATIONID_DEFAULT);
|
|
psync_set_status(PSTATUS_TYPE_AUTH, PSTATUS_AUTH_RELOCATING);
|
|
psync_wait_status(PSTATUS_TYPE_AUTH, PSTATUS_AUTH_PROVIDED);
|
|
psync_socket_close(sock);
|
|
psync_free(res);
|
|
continue;
|
|
}
|
|
|
|
psync_socket_close(sock);
|
|
psync_free(res);
|
|
|
|
if (result==2000 || result==2012 || result==2064 || result==2074 || result==2092){
|
|
psync_my_2fa_code_type=0;
|
|
psync_my_2fa_code[0]=0;
|
|
if (result==2012 || result==2064 || result==2074 || result==2092)
|
|
psync_set_status(PSTATUS_TYPE_AUTH, PSTATUS_AUTH_BADCODE);
|
|
else if (user && pass){
|
|
//Ugly fix, sorry :(
|
|
if (!strcmp(user, "pass") && !strcmp(pass, "dummy"))
|
|
{
|
|
debug(D_NOTICE, "got %lu, for user=%s, not rising PSTATUS_AUTH_BADLOGIN", (unsigned long)result, user);
|
|
psync_milisleep(1000);
|
|
continue;
|
|
}
|
|
else {
|
|
psync_set_status(PSTATUS_TYPE_AUTH, PSTATUS_AUTH_BADLOGIN);
|
|
psync_free(psync_my_pass);
|
|
psync_my_pass = NULL;
|
|
}
|
|
}
|
|
else {
|
|
psync_set_status(PSTATUS_TYPE_AUTH, PSTATUS_AUTH_BADTOKEN);
|
|
psync_set_apiserver(PSYNC_API_HOST, PSYNC_LOCATIONID_DEFAULT);
|
|
}
|
|
psync_wait_status(PSTATUS_TYPE_AUTH, PSTATUS_AUTH_PROVIDED);
|
|
}
|
|
else if (result==4000)
|
|
psync_milisleep(5*60*1000);
|
|
else if (result==2205 || result==2229){
|
|
psync_set_apiserver(PSYNC_API_HOST, PSYNC_LOCATIONID_DEFAULT);
|
|
psync_set_status(PSTATUS_TYPE_AUTH, PSTATUS_AUTH_EXPIRED);
|
|
psync_wait_status(PSTATUS_TYPE_AUTH, PSTATUS_AUTH_PROVIDED);
|
|
}
|
|
else if (result==2237) {
|
|
digest=0;
|
|
continue;
|
|
}
|
|
else
|
|
psync_milisleep(PSYNC_SLEEP_BEFORE_RECONNECT);
|
|
continue;
|
|
}
|
|
|
|
psync_my_userid=userid=psync_find_result(res, "userid", PARAM_NUM)->num;
|
|
current_quota=psync_find_result(res, "quota", PARAM_NUM)->num;
|
|
cres = psync_check_result(res, "freequota", PARAM_NUM);
|
|
|
|
if (cres){
|
|
free_quota=cres->num;
|
|
}
|
|
|
|
luserid=psync_sql_cellint("SELECT value FROM setting WHERE id='userid'", 0);
|
|
psync_is_business=psync_find_result(res, "business", PARAM_BOOL)->num;
|
|
lid=psync_setting_get_uint(_PS(location_id));
|
|
psync_sql_start_transaction();
|
|
psync_strlcpy(psync_my_auth, psync_find_result(res, "auth", PARAM_STR)->str, sizeof(psync_my_auth));
|
|
|
|
if (luserid){
|
|
if (unlikely_log(luserid!=userid)){
|
|
if(check_user_relocated(luserid, sock)){
|
|
debug(D_NOTICE, "setting PSTATUS_AUTH_RELOCATED");
|
|
psync_set_status(PSTATUS_TYPE_AUTH, PSTATUS_AUTH_RELOCATED);
|
|
}
|
|
else {
|
|
debug(D_NOTICE, "user mistmatch, db userid=%lu, connected userid=%lu", (unsigned long)luserid, (unsigned long)userid);
|
|
psync_set_status(PSTATUS_TYPE_AUTH, PSTATUS_AUTH_MISMATCH);
|
|
}
|
|
psync_sql_rollback_transaction();
|
|
psync_socket_close(sock);
|
|
psync_free(res);
|
|
psync_wait_status(PSTATUS_TYPE_AUTH, PSTATUS_AUTH_PROVIDED);
|
|
continue;
|
|
}
|
|
if (saveauth){
|
|
q=psync_sql_prep_statement("REPLACE INTO setting (id, value) VALUES ('auth', ?)");
|
|
psync_sql_bind_string(q, 1, psync_my_auth);
|
|
psync_sql_run_free(q);
|
|
}
|
|
}
|
|
else{
|
|
used_quota=0;
|
|
q=psync_sql_prep_statement("REPLACE INTO setting (id, value) VALUES (?, ?)");
|
|
psync_sql_bind_string(q, 1, "userid");
|
|
psync_sql_bind_uint(q, 2, userid);
|
|
psync_sql_run(q);
|
|
psync_sql_bind_string(q, 1, "last_logged_location_id");
|
|
psync_sql_bind_uint(q, 2, lid);
|
|
psync_sql_run(q);
|
|
psync_sql_bind_string(q, 1, "quota");
|
|
psync_sql_bind_uint(q, 2, current_quota);
|
|
psync_sql_run(q);
|
|
psync_sql_bind_string(q, 1, "freequota");
|
|
psync_sql_bind_uint(q, 2, free_quota);
|
|
psync_sql_run(q);
|
|
psync_sql_bind_string(q, 1, "usedquota");
|
|
psync_sql_bind_uint(q, 2, 0);
|
|
psync_sql_run(q);
|
|
result=psync_find_result(res, "premium", PARAM_BOOL)->num;
|
|
psync_sql_bind_string(q, 1, "premium");
|
|
psync_sql_bind_uint(q, 2, result);
|
|
psync_sql_run(q);
|
|
if (result)
|
|
result=psync_find_result(res, "premiumexpires", PARAM_NUM)->num;
|
|
else
|
|
result=0;
|
|
psync_sql_bind_string(q, 1, "premiumexpires");
|
|
psync_sql_bind_uint(q, 2, result);
|
|
psync_sql_run(q);
|
|
psync_sql_bind_string(q, 1, "emailverified");
|
|
psync_sql_bind_uint(q, 2, psync_find_result(res, "emailverified", PARAM_BOOL)->num);
|
|
psync_sql_run(q);
|
|
psync_sql_bind_string(q, 1, "registered");
|
|
psync_sql_bind_uint(q, 2, psync_find_result(res, "registered", PARAM_NUM)->num);
|
|
psync_sql_run(q);
|
|
psync_sql_bind_string(q, 1, "username");
|
|
psync_sql_bind_string(q, 2, psync_find_result(res, "email", PARAM_STR)->str);
|
|
psync_sql_run(q);
|
|
psync_sql_bind_string(q, 1, "language");
|
|
psync_sql_bind_string(q, 2, psync_find_result(res, "language", PARAM_STR)->str);
|
|
psync_sql_run(q);
|
|
psync_sql_bind_string(q, 1, "plan");
|
|
psync_sql_bind_uint(q, 2, psync_find_result(res, "plan", PARAM_NUM)->num);
|
|
psync_sql_run(q);
|
|
psync_sql_bind_string(q, 1, "business");
|
|
psync_sql_bind_uint(q, 2, psync_find_result(res, "business", PARAM_BOOL)->num);
|
|
psync_sql_run(q);
|
|
psync_sql_bind_string(q, 1, "premiumlifetime");
|
|
psync_sql_bind_uint(q, 2, psync_find_result(res, "premiumlifetime", PARAM_BOOL)->num);
|
|
psync_sql_run(q);
|
|
cres = psync_check_result(res, "vivapcloud", PARAM_BOOL);
|
|
if (cres){
|
|
psync_sql_bind_string(q, 1, "vivapcloud");
|
|
psync_sql_bind_uint(q, 2, cres->num);
|
|
psync_sql_run(q);
|
|
}
|
|
cres = psync_check_result(res, "family", PARAM_HASH);
|
|
if (cres){
|
|
psync_sql_bind_string(q, 1, "owner");
|
|
psync_sql_bind_uint(q, 2, psync_find_result(cres, "owner", PARAM_BOOL)->num);
|
|
psync_sql_run(q);
|
|
}
|
|
if (saveauth){
|
|
psync_sql_bind_string(q, 1, "auth");
|
|
psync_sql_bind_string(q, 2, psync_my_auth);
|
|
psync_sql_run(q);
|
|
}
|
|
psync_sql_free_result(q);
|
|
}
|
|
if (psync_status_get(PSTATUS_TYPE_AUTH)!=PSTATUS_AUTH_PROVIDED){
|
|
psync_sql_rollback_transaction();
|
|
psync_socket_close(sock);
|
|
psync_free(res);
|
|
psync_wait_status(PSTATUS_TYPE_AUTH, PSTATUS_AUTH_PROVIDED);
|
|
continue;
|
|
}
|
|
debug(D_NOTICE, "userid %lu", (unsigned long)userid);
|
|
cres=psync_check_result(res, "account", PARAM_HASH);
|
|
q=psync_sql_prep_statement("REPLACE INTO setting (id, value) VALUES (?, ?)");
|
|
if (cres){
|
|
psync_sql_bind_string(q, 1, "business");
|
|
psync_sql_bind_uint(q, 2, 1);
|
|
psync_sql_run(q);
|
|
psync_sql_bind_string(q, 1, "firstname");
|
|
psync_sql_bind_string(q, 2, psync_find_result(cres, "firstname", PARAM_STR)->str);
|
|
psync_sql_run(q);
|
|
psync_sql_bind_string(q, 1, "lastname");
|
|
psync_sql_bind_string(q, 2, psync_find_result(cres, "lastname", PARAM_STR)->str);
|
|
psync_sql_run(q);
|
|
isbusiness=1;
|
|
}
|
|
else{
|
|
psync_sql_bind_string(q, 1, "business");
|
|
psync_sql_bind_uint(q, 2, 0);
|
|
psync_sql_run(q);
|
|
isbusiness=0;
|
|
}
|
|
|
|
cres=psync_check_result(res, "cryptov2isactive", PARAM_BOOL);
|
|
if (cres)
|
|
psync_set_bool_setting("cryptov2isactive", cres->num);
|
|
else
|
|
psync_set_bool_setting("cryptov2isactive", 0);
|
|
cryptosetup=psync_find_result(res, "cryptosetup", PARAM_BOOL)->num;
|
|
psync_sql_bind_string(q, 1, "cryptosetup");
|
|
psync_sql_bind_uint(q, 2, cryptosetup);
|
|
psync_sql_run(q);
|
|
if (cryptosetup){
|
|
char *publicsha1=psync_sql_cellstr("SELECT value FROM setting WHERE id='crypto_public_sha1'");
|
|
char *privatesha1=psync_sql_cellstr("SELECT value FROM setting WHERE id='crypto_private_sha1'");
|
|
if (!publicsha1 || !privatesha1 || strcmp(publicsha1, psync_find_result(res, "publicsha1", PARAM_STR)->str) ||
|
|
strcmp(privatesha1, psync_find_result(res, "privatesha1", PARAM_STR)->str))
|
|
delete_cached_crypto_keys();
|
|
psync_free(privatesha1);
|
|
psync_free(publicsha1);
|
|
}
|
|
else
|
|
delete_cached_crypto_keys();
|
|
psync_sql_bind_string(q, 1, "cryptosubscription");
|
|
psync_sql_bind_uint(q, 2, psync_find_result(res, "cryptosubscription", PARAM_BOOL)->num);
|
|
psync_sql_run(q);
|
|
cres=psync_check_result(res, "cryptoexpires", PARAM_NUM);
|
|
psync_sql_bind_string(q, 1, "cryptoexpires");
|
|
psync_sql_bind_uint(q, 2, cres?cres->num:0);
|
|
psync_sql_run(q);
|
|
int sub = check_active_subscribtion(res);
|
|
psync_sql_bind_string(q, 1, "hasactivesubscription");
|
|
psync_sql_bind_uint(q, 2, sub);
|
|
psync_sql_run(q);
|
|
psync_sql_free_result(q);
|
|
psync_sql_commit_transaction();
|
|
pthread_mutex_lock(&psync_my_auth_mutex);
|
|
if (psync_my_pass){
|
|
memset(psync_my_pass, 'X', strlen(psync_my_pass));
|
|
q=psync_sql_prep_statement("UPDATE setting SET value=? WHERE id='pass'");
|
|
psync_sql_bind_string(q, 1, psync_my_pass);
|
|
psync_sql_run_free(q);
|
|
psync_free(psync_my_pass);
|
|
psync_my_pass=NULL;
|
|
}
|
|
pthread_mutex_unlock(&psync_my_auth_mutex);
|
|
if (saveauth)
|
|
psync_sql_statement("DELETE FROM setting WHERE id='pass'");
|
|
else
|
|
psync_sql_statement("DELETE FROM setting WHERE id IN ('pass', 'auth')");
|
|
cres=psync_find_result(psync_find_result(res, "apiserver", PARAM_HASH), "binapi", PARAM_ARRAY);
|
|
if (cres->length)
|
|
psync_apipool_set_server(cres->array[0]->str);
|
|
psync_free(res);
|
|
|
|
//If the flag is up, send a first login event to track the number of sucessful installs.
|
|
if (isFirstLogin) {
|
|
debug(D_NOTICE, "This is a first login. Send the FIRST_LOGIN event. Token:[%s], User id: [%lu]", psync_my_auth, (unsigned long)userid);
|
|
time_t rawtime;
|
|
time(&rawtime);
|
|
|
|
char* macAddr;
|
|
macAddr = getMACaddr();
|
|
|
|
eventParams params = {
|
|
1, //Number of parameters we are passing below.
|
|
{
|
|
P_STR(EPARAM_MAC, macAddr)
|
|
}
|
|
};
|
|
create_backend_event(
|
|
apiserver,
|
|
INST_EVENT_CATEG,
|
|
INST_EVENT_FLOGIN,
|
|
INST_EVENT_CATEG,
|
|
psync_my_auth,
|
|
P_OS_ID,
|
|
rawtime,
|
|
¶ms,
|
|
(char **)res);
|
|
}
|
|
else {
|
|
debug(D_NOTICE, "Not a first login. Run sync event.");
|
|
|
|
send_psyncs_event(
|
|
apiserver,
|
|
psync_my_auth);
|
|
}
|
|
|
|
if (isbusiness){
|
|
binparam params[]={P_STR("timeformat", "timestamp"),
|
|
P_STR("auth", psync_my_auth)};
|
|
res=send_command(sock, "account_info", params);
|
|
if (unlikely_log(!res)){
|
|
psync_socket_close(sock);
|
|
continue;
|
|
}
|
|
result=psync_find_result(res, "result", PARAM_NUM)->num;
|
|
if (likely(result==0)){
|
|
cres=psync_check_result(res, "account", PARAM_HASH);
|
|
q=psync_sql_prep_statement("REPLACE INTO setting (id, value) VALUES (?, ?)");
|
|
psync_sql_bind_string(q, 1, "company");
|
|
psync_sql_bind_string(q, 2, psync_find_result(cres, "company", PARAM_STR)->str);
|
|
psync_sql_run_free(q);
|
|
cres=psync_check_result(cres, "owner", PARAM_HASH);
|
|
psync_set_bool_setting("owner_cryptosetup", psync_find_result(cres, "cryptosetup", PARAM_BOOL)->num);
|
|
}
|
|
else
|
|
debug(D_WARNING, "account_info returned %lu, continuing without business info", (unsigned long)result);
|
|
psync_free(res);
|
|
psync_sql_sync();
|
|
}
|
|
|
|
psync_free(auth);
|
|
psync_free(user);
|
|
psync_free(pass);
|
|
psync_free(psync_my_2fa_token);
|
|
psync_my_2fa_token=NULL;
|
|
psync_my_2fa_code_type=0;
|
|
psync_my_2fa_code[0]=0;
|
|
psync_free(deviceid);
|
|
psync_free(devicestring);
|
|
psync_sql_sync();
|
|
return sock;
|
|
}
|
|
}
|
|
|
|
static uint64_t extract_meta_folder_flags(const binresult *meta) {
|
|
const binresult *res;
|
|
uint64_t flags = 0;
|
|
if ((res=psync_check_result(meta, "encrypted", PARAM_BOOL)) && res->num)
|
|
flags|=PSYNC_FOLDER_FLAG_ENCRYPTED;
|
|
if ((res=psync_check_result(meta, "ispublicroot", PARAM_BOOL)) && res->num)
|
|
flags|=PSYNC_FOLDER_FLAG_PUBLIC_ROOT;
|
|
if ((res=psync_check_result(meta, "isbackupdevicelist", PARAM_BOOL)) && res->num)
|
|
flags|=PSYNC_FOLDER_FLAG_BACKUP_DEVICE_LIST;
|
|
if ((res=psync_check_result(meta, "isbackupdevice", PARAM_BOOL)) && res->num)
|
|
flags|=PSYNC_FOLDER_FLAG_BACKUP_DEVICE;
|
|
if ((res=psync_check_result(meta, "isbackuproot", PARAM_BOOL)) && res->num)
|
|
flags|=PSYNC_FOLDER_FLAG_BACKUP_ROOT;
|
|
if ((res=psync_check_result(meta, "isbackup", PARAM_BOOL)) && res->num)
|
|
flags|=PSYNC_FOLDER_FLAG_BACKUP;
|
|
|
|
return flags;
|
|
}
|
|
|
|
static void process_createfolder(const binresult *entry){
|
|
static psync_sql_res *st=NULL, *st2=NULL;
|
|
psync_sql_res *res, *stmt, *stmt2;
|
|
const binresult *meta, *name;
|
|
uint64_t userid, perms, mtime, flags;
|
|
psync_uint_row row;
|
|
psync_folderid_t parentfolderid, folderid, localfolderid;
|
|
// char *localname;
|
|
psync_syncid_t syncid;
|
|
if (!entry){
|
|
if (st){
|
|
psync_sql_free_result(st);
|
|
st=NULL;
|
|
}
|
|
if (st2){
|
|
psync_sql_free_result(st2);
|
|
st2=NULL;
|
|
}
|
|
return;
|
|
}
|
|
if (!st){
|
|
st=psync_sql_prep_statement("INSERT OR IGNORE INTO folder (id, parentfolderid, userid, permissions, name, ctime, mtime, flags, subdircnt) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 0)");
|
|
if (!st)
|
|
return;
|
|
st2=psync_sql_prep_statement("UPDATE folder SET subdircnt=subdircnt+1, mtime=? WHERE id=?");
|
|
if (!st2)
|
|
return;
|
|
}
|
|
meta=psync_find_result(entry, "metadata", PARAM_HASH);
|
|
flags=extract_meta_folder_flags(meta);
|
|
if (psync_find_result(meta, "ismine", PARAM_BOOL)->num){
|
|
userid=psync_my_userid;
|
|
perms=PSYNC_PERM_ALL;
|
|
}
|
|
else{
|
|
userid=psync_find_result(meta, "userid", PARAM_NUM)->num;
|
|
perms=psync_get_permissions(meta);
|
|
}
|
|
name=psync_find_result(meta, "name", PARAM_STR);
|
|
folderid=psync_find_result(meta, "folderid", PARAM_NUM)->num;
|
|
parentfolderid=psync_find_result(meta, "parentfolderid", PARAM_NUM)->num;
|
|
mtime=psync_find_result(meta, "modified", PARAM_NUM)->num;
|
|
psync_sql_bind_uint(st, 1, folderid);
|
|
psync_sql_bind_uint(st, 2, parentfolderid);
|
|
psync_sql_bind_uint(st, 3, userid);
|
|
psync_sql_bind_uint(st, 4, perms);
|
|
psync_sql_bind_lstring(st, 5, name->str, name->length);
|
|
psync_sql_bind_uint(st, 6, psync_find_result(meta, "created", PARAM_NUM)->num);
|
|
psync_sql_bind_uint(st, 7, mtime);
|
|
psync_sql_bind_uint(st, 8, flags);
|
|
psync_sql_run(st);
|
|
if (!psync_sql_affected_rows()){
|
|
res=psync_sql_prep_statement("UPDATE folder SET parentfolderid=?, userid=?, permissions=?, name=?, ctime=?, mtime=?, flags=? WHERE id=?");
|
|
psync_sql_bind_uint(res, 1, parentfolderid);
|
|
psync_sql_bind_uint(res, 2, userid);
|
|
psync_sql_bind_uint(res, 3, perms);
|
|
psync_sql_bind_lstring(res, 4, name->str, name->length);
|
|
psync_sql_bind_uint(res, 5, psync_find_result(meta, "created", PARAM_NUM)->num);
|
|
psync_sql_bind_uint(res, 6, mtime);
|
|
psync_sql_bind_uint(res, 7, flags);
|
|
psync_sql_bind_uint(res, 8, folderid);
|
|
psync_sql_run_free(res);
|
|
}
|
|
psync_sql_bind_uint(st2, 1, mtime);
|
|
psync_sql_bind_uint(st2, 2, parentfolderid);
|
|
psync_sql_run(st2);
|
|
if (psync_is_folder_in_downloadlist(parentfolderid) && !psync_is_name_to_ignore(name->str)){
|
|
psync_add_folder_to_downloadlist(folderid);
|
|
res=psync_sql_query("SELECT syncid, localfolderid, synctype FROM syncedfolder WHERE folderid=? AND "PSYNC_SQL_DOWNLOAD);
|
|
psync_sql_bind_uint(res, 1, parentfolderid);
|
|
stmt=psync_sql_prep_statement("INSERT OR IGNORE INTO syncedfolder (syncid, folderid, localfolderid, synctype) VALUES (?, ?, ?, ?)");
|
|
while ((row=psync_sql_fetch_rowint(res))){
|
|
syncid=row[0];
|
|
debug(D_NOTICE, "creating local folder %lu/%s for folderid %lu, parentfolderid %lu", (unsigned long)row[1], name->str, (unsigned long)folderid, (unsigned long)parentfolderid);
|
|
localfolderid=psync_create_local_folder_in_db(syncid, folderid, row[1], name->str);
|
|
psync_sql_bind_uint(stmt, 1, syncid);
|
|
psync_sql_bind_uint(stmt, 2, folderid);
|
|
psync_sql_bind_uint(stmt, 3, localfolderid);
|
|
psync_sql_bind_uint(stmt, 4, row[2]);
|
|
psync_sql_run(stmt);
|
|
if (psync_sql_affected_rows()==1){
|
|
psync_task_create_local_folder(syncid, folderid, localfolderid);
|
|
needdownload=1;
|
|
}
|
|
else{
|
|
stmt2=psync_sql_prep_statement("UPDATE syncedfolder SET folderid=? WHERE syncid=? AND localfolderid=?");
|
|
psync_sql_bind_uint(stmt2, 1, folderid);
|
|
psync_sql_bind_uint(stmt2, 2, syncid);
|
|
psync_sql_bind_uint(stmt2, 3, localfolderid);
|
|
psync_sql_run_free(stmt2);
|
|
}
|
|
}
|
|
psync_sql_free_result(stmt);
|
|
psync_sql_free_result(res);
|
|
}
|
|
}
|
|
|
|
static void group_results_by_col(psync_full_result_int *restrict r1, psync_full_result_int *restrict r2, uint32_t col){
|
|
psync_def_var_arr(buff, uint64_t, r1->cols);
|
|
size_t rowsize;
|
|
uint32_t i, j, l;
|
|
l=0;
|
|
rowsize=sizeof(r1->data[0])*r1->cols;
|
|
assert(r1->cols==r2->cols);
|
|
for (i=0; i<r1->rows; i++)
|
|
for (j=0; j<r2->rows; j++)
|
|
if (psync_get_result_cell(r1, i, col)==psync_get_result_cell(r2, j, col)){
|
|
if (i!=l){
|
|
memcpy(buff, r1->data+i*r1->cols, rowsize);
|
|
memcpy(r1->data+i*r1->cols, r1->data+l*r1->cols, rowsize);
|
|
memcpy(r1->data+l*r1->cols, buff, rowsize);
|
|
}
|
|
if (j!=l){
|
|
memcpy(buff, r2->data+j*r2->cols, rowsize);
|
|
memcpy(r2->data+j*r2->cols, r2->data+l*r2->cols, rowsize);
|
|
memcpy(r2->data+l*r2->cols, buff, rowsize);
|
|
}
|
|
l++;
|
|
}
|
|
}
|
|
|
|
static void del_synced_folder_rec(psync_folderid_t folderid, psync_syncid_t syncid){
|
|
psync_sql_res *res;
|
|
psync_uint_row row;
|
|
res=psync_sql_prep_statement("DELETE FROM syncedfolder WHERE folderid=? AND syncid=?");
|
|
psync_sql_bind_uint(res, 1, folderid);
|
|
psync_sql_bind_uint(res, 2, syncid);
|
|
psync_sql_run_free(res);
|
|
res=psync_sql_query("SELECT id FROM folder WHERE parentfolderid=?");
|
|
psync_sql_bind_uint(res, 1, folderid);
|
|
while ((row=psync_sql_fetch_rowint(res)))
|
|
del_synced_folder_rec(row[0], syncid);
|
|
psync_sql_free_result(res);
|
|
}
|
|
|
|
static void process_modifyfolder(const binresult *entry){
|
|
static psync_sql_res *st=NULL;
|
|
psync_sql_res *res;
|
|
psync_full_result_int *fres1, *fres2;
|
|
const binresult *meta, *name;
|
|
uint64_t userid, perms, mtime, flags, oldflags;
|
|
psync_variant_row vrow;
|
|
psync_uint_row row;
|
|
psync_folderid_t parentfolderid, folderid, oldparentfolderid, localfolderid;
|
|
char *oldname;
|
|
psync_syncid_t syncid;
|
|
uint32_t i, cnt;
|
|
int oldsync, newsync;
|
|
if (!entry){
|
|
process_createfolder(NULL);
|
|
if (st){
|
|
psync_sql_free_result(st);
|
|
st=NULL;
|
|
}
|
|
return;
|
|
}
|
|
if (!st){
|
|
st=psync_sql_prep_statement("UPDATE folder SET parentfolderid=?, userid=?, permissions=?, name=?, ctime=?, mtime=?, flags=? WHERE id=?");
|
|
if (!st)
|
|
return;
|
|
}
|
|
meta=psync_find_result(entry, "metadata", PARAM_HASH);
|
|
flags=extract_meta_folder_flags(meta);
|
|
if (psync_find_result(meta, "ismine", PARAM_BOOL)->num){
|
|
userid=psync_my_userid;
|
|
perms=PSYNC_PERM_ALL;
|
|
}
|
|
else{
|
|
userid=psync_find_result(meta, "userid", PARAM_NUM)->num;
|
|
perms=psync_get_permissions(meta);
|
|
}
|
|
name=psync_find_result(meta, "name", PARAM_STR);
|
|
folderid=psync_find_result(meta, "folderid", PARAM_NUM)->num;
|
|
parentfolderid=psync_find_result(meta, "parentfolderid", PARAM_NUM)->num;
|
|
res=psync_sql_query("SELECT parentfolderid, name, flags FROM folder WHERE id=?");
|
|
psync_sql_bind_uint(res, 1, folderid);
|
|
vrow=psync_sql_fetch_row(res);
|
|
if (likely(vrow)){
|
|
oldparentfolderid=psync_get_number(vrow[0]);
|
|
oldname=psync_dup_string(vrow[1]);
|
|
oldflags=psync_get_number(vrow[2]);
|
|
}
|
|
else{
|
|
debug(D_ERROR, "got modify for non-existing folder %lu (%s), processing as create", (unsigned long)folderid, name->str);
|
|
psync_sql_free_result(res);
|
|
process_createfolder(entry);
|
|
return;
|
|
}
|
|
psync_sql_free_result(res);
|
|
|
|
if ((oldflags & PSYNC_FOLDER_FLAG_BACKUP_ROOT) != 0 && (flags & PSYNC_FOLDER_FLAG_BACKUP_ROOT) == 0) {
|
|
debug(D_NOTICE, "Stop backup root");
|
|
psync_delete_sync_by_folderid(folderid);
|
|
//psync_run_thread1("psync_async_backup_delete", psync_delete_sync_by_folderid, folderid);
|
|
}
|
|
|
|
if ((oldflags & PSYNC_FOLDER_FLAG_BACKUP_DEVICE) != 0 && (flags & PSYNC_FOLDER_FLAG_BACKUP_DEVICE) == 0) {
|
|
debug(D_NOTICE, "Stop backup device");
|
|
psync_delete_backup_device(folderid);
|
|
}
|
|
|
|
mtime=psync_find_result(meta, "modified", PARAM_NUM)->num;
|
|
psync_sql_bind_uint(st, 1, parentfolderid);
|
|
psync_sql_bind_uint(st, 2, userid);
|
|
psync_sql_bind_uint(st, 3, perms);
|
|
psync_sql_bind_lstring(st, 4, name->str, name->length);
|
|
psync_sql_bind_uint(st, 5, psync_find_result(meta, "created", PARAM_NUM)->num);
|
|
psync_sql_bind_uint(st, 6, mtime);
|
|
psync_sql_bind_uint(st, 7, flags);
|
|
psync_sql_bind_uint(st, 8, folderid);
|
|
psync_sql_run(st);
|
|
|
|
if (oldparentfolderid!=parentfolderid){
|
|
res=psync_sql_prep_statement("UPDATE folder SET subdircnt=subdircnt-1, mtime=? WHERE id=?");
|
|
psync_sql_bind_uint(res, 1, mtime);
|
|
psync_sql_bind_uint(res, 2, oldparentfolderid);
|
|
psync_sql_run_free(res);
|
|
res=psync_sql_prep_statement("UPDATE folder SET subdircnt=subdircnt+1, mtime=? WHERE id=?");
|
|
psync_sql_bind_uint(res, 1, mtime);
|
|
psync_sql_bind_uint(res, 2, parentfolderid);
|
|
psync_sql_run_free(res);
|
|
psync_path_status_folder_moved(folderid, oldparentfolderid, parentfolderid);
|
|
}
|
|
/* We should check if oldparentfolderid is in downloadlist, not folderid. If parentfolderid is not in and
|
|
* folderid is in, it means that folder that is a "root" of a syncid is modified, we do not care about that.
|
|
*/
|
|
oldsync=psync_is_folder_in_downloadlist(oldparentfolderid);
|
|
if (oldparentfolderid==parentfolderid)
|
|
newsync=oldsync;
|
|
else{
|
|
newsync=psync_is_folder_in_downloadlist(parentfolderid);
|
|
psync_diff_refresh_fs_add_folder(oldparentfolderid);
|
|
}
|
|
if ((oldsync || newsync) && (oldparentfolderid!=parentfolderid || strcmp(name->str, oldname))){
|
|
if (!oldsync)
|
|
psync_add_folder_to_downloadlist(folderid);
|
|
else if (!newsync){
|
|
res=psync_sql_query("SELECT id FROM syncfolder WHERE folderid=? AND "PSYNC_SQL_DOWNLOAD);
|
|
psync_sql_bind_uint(res, 1, folderid);
|
|
if (!psync_sql_fetch_rowint(res))
|
|
psync_del_folder_from_downloadlist(folderid);
|
|
psync_sql_free_result(res);
|
|
}
|
|
res=psync_sql_query("SELECT syncid, localfolderid, synctype FROM syncedfolder WHERE folderid=? AND "PSYNC_SQL_DOWNLOAD);
|
|
psync_sql_bind_uint(res, 1, oldparentfolderid);
|
|
fres1=psync_sql_fetchall_int(res);
|
|
res=psync_sql_query("SELECT syncid, localfolderid, synctype FROM syncedfolder WHERE folderid=? AND "PSYNC_SQL_DOWNLOAD);
|
|
psync_sql_bind_uint(res, 1, parentfolderid);
|
|
fres2=psync_sql_fetchall_int(res);
|
|
if (psync_is_name_to_ignore(name->str))
|
|
fres2->rows=0;
|
|
group_results_by_col(fres1, fres2, 0);
|
|
cnt=fres2->rows>fres1->rows?fres1->rows:fres2->rows;
|
|
for (i=0; i<cnt; i++){
|
|
res=psync_sql_query("SELECT localfolderid FROM syncedfolder WHERE folderid=? AND syncid=?");
|
|
psync_sql_bind_uint(res, 1, folderid);
|
|
psync_sql_bind_uint(res, 2, psync_get_result_cell(fres1, i, 0));
|
|
row=psync_sql_fetch_rowint(res);
|
|
if (unlikely(!row)){
|
|
debug(D_ERROR, "could not find local folder of folderid %lu", (unsigned long)folderid);
|
|
psync_sql_free_result(res);
|
|
continue;
|
|
}
|
|
localfolderid=row[0];
|
|
psync_sql_free_result(res);
|
|
psync_task_rename_local_folder(psync_get_result_cell(fres2, i, 0), folderid, localfolderid, psync_get_result_cell(fres2, i, 1), name->str);
|
|
needdownload=1;
|
|
if (psync_get_result_cell(fres2, i, 0)!=psync_get_result_cell(fres1, i, 0)){
|
|
res=psync_sql_prep_statement("UPDATE syncedfolder SET syncid=?, synctype=? WHERE syncid=? AND folderid=?");
|
|
psync_sql_bind_uint(res, 1, psync_get_result_cell(fres2, i, 0));
|
|
psync_sql_bind_uint(res, 2, psync_get_result_cell(fres2, i, 2));
|
|
psync_sql_bind_uint(res, 3, psync_get_result_cell(fres1, i, 0));
|
|
psync_sql_bind_uint(res, 4, folderid);
|
|
psync_sql_run_free(res);
|
|
}
|
|
}
|
|
for (/*i is already=cnt*/; i<fres1->rows; i++){
|
|
syncid=psync_get_result_cell(fres1, i, 0);
|
|
res=psync_sql_query("SELECT localfolderid FROM syncedfolder WHERE folderid=? AND syncid=?");
|
|
psync_sql_bind_uint(res, 1, folderid);
|
|
psync_sql_bind_uint(res, 2, syncid);
|
|
row=psync_sql_fetch_rowint(res);
|
|
if (unlikely(!row)){
|
|
debug(D_ERROR, "could not find local folder of folderid %lu", (unsigned long)folderid);
|
|
psync_sql_free_result(res);
|
|
continue;
|
|
}
|
|
localfolderid=row[0];
|
|
psync_sql_free_result(res);
|
|
del_synced_folder_rec(folderid, syncid);
|
|
psync_task_delete_local_folder_recursive(syncid, folderid, localfolderid);
|
|
needdownload=1;
|
|
}
|
|
for (/*i is already=cnt*/; i<fres2->rows; i++){
|
|
syncid=psync_get_result_cell(fres2, i, 0);
|
|
debug(D_NOTICE, "creating local folder %lu/%s for folderid %lu, parentfolderid %lu", (unsigned long)psync_get_result_cell(fres2, i, 1), name->str, (unsigned long)folderid, (unsigned long)parentfolderid);
|
|
localfolderid=psync_create_local_folder_in_db(syncid, folderid, psync_get_result_cell(fres2, i, 1), name->str);
|
|
psync_task_create_local_folder(syncid, folderid, localfolderid);
|
|
psync_add_folder_for_downloadsync(syncid, psync_get_result_cell(fres2, i, 2), folderid, localfolderid);
|
|
needdownload=1;
|
|
}
|
|
psync_free(fres1);
|
|
psync_free(fres2);
|
|
}
|
|
psync_free(oldname);
|
|
}
|
|
|
|
static void process_deletefolder(const binresult *entry){
|
|
static psync_sql_res *st=NULL, *st2=NULL;
|
|
const binresult *meta;
|
|
psync_sql_res *res, *stmt;
|
|
char *path;
|
|
psync_folderid_t folderid;
|
|
psync_uint_row row;
|
|
if (!entry){
|
|
if (st){
|
|
psync_sql_free_result(st);
|
|
st=NULL;
|
|
}
|
|
if (st2){
|
|
psync_sql_free_result(st2);
|
|
st2=NULL;
|
|
}
|
|
return;
|
|
}
|
|
if (!st){
|
|
st=psync_sql_prep_statement("DELETE FROM folder WHERE id=?");
|
|
if (!st)
|
|
return;
|
|
st2=psync_sql_prep_statement("UPDATE folder SET subdircnt=subdircnt-1, mtime=? WHERE id=?");
|
|
if (!st2)
|
|
return;
|
|
}
|
|
meta=psync_find_result(entry, "metadata", PARAM_HASH);
|
|
folderid=psync_find_result(meta, "folderid", PARAM_NUM)->num;
|
|
psync_path_status_folder_deleted(folderid);
|
|
if (psync_is_folder_in_downloadlist(folderid)){
|
|
psync_del_folder_from_downloadlist(folderid);
|
|
res=psync_sql_query("SELECT syncid, localfolderid FROM syncedfolder WHERE folderid=?");
|
|
psync_sql_bind_uint(res, 1, folderid);
|
|
while ((row=psync_sql_fetch_rowint(res))){
|
|
stmt=psync_sql_prep_statement("DELETE FROM syncedfolder WHERE syncid=? AND folderid=?");
|
|
psync_sql_bind_uint(stmt, 1, row[0]);
|
|
psync_sql_bind_uint(stmt, 2, folderid);
|
|
psync_sql_run_free(stmt);
|
|
if (psync_sql_affected_rows()==1){
|
|
path=psync_get_path_by_folderid(folderid, NULL);
|
|
psync_task_delete_local_folder(row[0], folderid, row[1], path);
|
|
psync_free(path);
|
|
needdownload=1;
|
|
}
|
|
}
|
|
psync_sql_free_result(res);
|
|
}
|
|
psync_sql_bind_uint(st, 1, folderid);
|
|
psync_sql_run(st);
|
|
if (psync_sql_affected_rows()){
|
|
psync_sql_bind_uint(st2, 1, psync_find_result(meta, "modified", PARAM_NUM)->num);
|
|
psync_sql_bind_uint(st2, 2, psync_find_result(meta, "parentfolderid", PARAM_NUM)->num);
|
|
psync_sql_run(st2);
|
|
psync_fs_folder_deleted(folderid);
|
|
}
|
|
}
|
|
|
|
static void check_for_deletedfileid(const binresult *meta){
|
|
const binresult *delfileid;
|
|
delfileid=psync_check_result(meta, "deletedfileid", PARAM_NUM);
|
|
if (likely(!delfileid))
|
|
return;
|
|
else{
|
|
psync_sql_res *res;
|
|
res=psync_sql_prep_statement("DELETE FROM file WHERE id=?");
|
|
psync_sql_bind_uint(res, 1, delfileid->num);
|
|
psync_sql_run_free(res);
|
|
psync_fs_file_deleted(delfileid->num);
|
|
}
|
|
}
|
|
|
|
#define bind_num(s) psync_sql_bind_uint(res, off++, psync_find_result(meta, s, PARAM_NUM)->num)
|
|
#define bind_bool(s) psync_sql_bind_uint(res, off++, psync_find_result(meta, s, PARAM_BOOL)->num)
|
|
#define bind_str(s) do {br=psync_find_result(meta, s, PARAM_STR); psync_sql_bind_lstring(res, off++, br->str, br->length);} while (0)
|
|
#define bind_opt_str(s) \
|
|
do {\
|
|
br=psync_check_result(meta, s, PARAM_STR);\
|
|
if (br)\
|
|
psync_sql_bind_lstring(res, off++, br->str, br->length);\
|
|
else\
|
|
psync_sql_bind_null(res, off++);\
|
|
} while (0)
|
|
#define bind_opt_num(s) \
|
|
do {\
|
|
br=psync_check_result(meta, s, PARAM_NUM);\
|
|
if (br)\
|
|
psync_sql_bind_uint(res, off++, br->num);\
|
|
else\
|
|
psync_sql_bind_null(res, off++);\
|
|
} while (0)
|
|
#define bind_opt_double(s) \
|
|
do {\
|
|
br=psync_check_result(meta, s, PARAM_STR);\
|
|
if (br)\
|
|
psync_sql_bind_double(res, off++, atof(br->str));\
|
|
else\
|
|
psync_sql_bind_null(res, off++);\
|
|
} while (0)
|
|
|
|
static int bind_meta(psync_sql_res *res, const binresult *meta, int off){
|
|
const binresult *br;
|
|
bind_num("created");
|
|
bind_num("modified");
|
|
bind_num("category");
|
|
bind_bool("thumb");
|
|
bind_str("icon");
|
|
bind_opt_str("artist");
|
|
bind_opt_str("album");
|
|
bind_opt_str("title");
|
|
bind_opt_str("genre");
|
|
bind_opt_num("trackno");
|
|
bind_opt_num("width");
|
|
bind_opt_num("height");
|
|
bind_opt_double("duration");
|
|
bind_opt_double("fps");
|
|
bind_opt_str("videocodec");
|
|
bind_opt_str("audiocodec");
|
|
bind_opt_num("videobitrate");
|
|
bind_opt_num("audiobitrate");
|
|
bind_opt_num("audiosamplerate");
|
|
bind_opt_num("rotate");
|
|
return off;
|
|
}
|
|
|
|
static void insert_revision(psync_fileid_t fileid, uint64_t hash, uint64_t ctime, uint64_t size){
|
|
static psync_sql_res *st=NULL;
|
|
if (!fileid){
|
|
if (st){
|
|
psync_sql_free_result(st);
|
|
st=NULL;
|
|
}
|
|
return;
|
|
}
|
|
if (!st)
|
|
st=psync_sql_prep_statement("REPLACE INTO filerevision (fileid, hash, ctime, size) VALUES (?, ?, ?, ?)");
|
|
psync_sql_bind_uint(st, 1, fileid);
|
|
psync_sql_bind_uint(st, 2, hash);
|
|
psync_sql_bind_uint(st, 3, ctime);
|
|
psync_sql_bind_uint(st, 4, size);
|
|
psync_sql_run(st);
|
|
}
|
|
|
|
static void process_createfile(const binresult *entry){
|
|
static psync_sql_res *st=NULL;
|
|
const binresult *meta, *name;
|
|
psync_sql_res *res, *res2;
|
|
psync_folderid_t parentfolderid;
|
|
psync_fileid_t fileid;
|
|
uint64_t size, userid, hash;
|
|
psync_uint_row row;
|
|
psync_str_row row2;
|
|
int hasit;
|
|
if (!entry){
|
|
if (st){
|
|
psync_sql_free_result(st);
|
|
st=NULL;
|
|
}
|
|
insert_revision(0, 0, 0, 0);
|
|
return;
|
|
}
|
|
if (!st)
|
|
st=psync_sql_prep_statement("INSERT OR IGNORE INTO file (id, parentfolderid, userid, size, hash, name, ctime, mtime, category, thumb, icon, "
|
|
"artist, album, title, genre, trackno, width, height, duration, fps, videocodec, audiocodec, videobitrate, "
|
|
"audiobitrate, audiosamplerate, rotate) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
meta=psync_find_result(entry, "metadata", PARAM_HASH);
|
|
size=psync_find_result(meta, "size", PARAM_NUM)->num;
|
|
fileid=psync_find_result(meta, "fileid", PARAM_NUM)->num;
|
|
parentfolderid=psync_find_result(meta, "parentfolderid", PARAM_NUM)->num;
|
|
if (psync_find_result(meta, "ismine", PARAM_BOOL)->num){
|
|
userid=psync_my_userid;
|
|
used_quota+=size;
|
|
}
|
|
else
|
|
userid=psync_find_result(meta, "userid", PARAM_NUM)->num;
|
|
hash=psync_find_result(meta, "hash", PARAM_NUM)->num;
|
|
name=psync_find_result(meta, "name", PARAM_STR);
|
|
check_for_deletedfileid(meta);
|
|
psync_sql_bind_uint(st, 1, fileid);
|
|
psync_sql_bind_uint(st, 2, parentfolderid);
|
|
psync_sql_bind_uint(st, 3, userid);
|
|
psync_sql_bind_uint(st, 4, size);
|
|
psync_sql_bind_uint(st, 5, hash);
|
|
psync_sql_bind_lstring(st, 6, name->str, name->length);
|
|
bind_meta(st, meta, 7);
|
|
psync_sql_run(st);
|
|
if (!psync_sql_affected_rows()){
|
|
int off;
|
|
res=psync_sql_prep_statement("UPDATE file SET id=?, parentfolderid=?, userid=?, size=?, hash=?, name=?, ctime=?, mtime=?, category=?, thumb=?, icon=?, "
|
|
"artist=?, album=?, title=?, genre=?, trackno=?, width=?, height=?, duration=?, fps=?, videocodec=?, audiocodec=?, videobitrate=?, "
|
|
"audiobitrate=?, audiosamplerate=?, rotate=? WHERE id=?");
|
|
psync_sql_bind_uint(res, 1, fileid);
|
|
psync_sql_bind_uint(res, 2, parentfolderid);
|
|
psync_sql_bind_uint(res, 3, userid);
|
|
psync_sql_bind_uint(res, 4, size);
|
|
psync_sql_bind_uint(res, 5, hash);
|
|
psync_sql_bind_lstring(res, 6, name->str, name->length);
|
|
off=bind_meta(res, meta, 7);
|
|
psync_sql_bind_uint(res, off, fileid);
|
|
psync_sql_run_free(res);
|
|
}
|
|
insert_revision(fileid, hash, psync_find_result(meta, "modified", PARAM_NUM)->num, size);
|
|
if (psync_is_folder_in_downloadlist(parentfolderid) && !psync_is_name_to_ignore(name->str)){
|
|
res=psync_sql_query("SELECT syncid, localfolderid FROM syncedfolder WHERE folderid=? AND "PSYNC_SQL_DOWNLOAD);
|
|
psync_sql_bind_uint(res, 1, parentfolderid);
|
|
while ((row=psync_sql_fetch_rowint(res))){
|
|
res2=psync_sql_query("SELECT name FROM localfile WHERE syncid=? AND localparentfolderid=? AND hash=? AND fileid=?");
|
|
psync_sql_bind_uint(res2, 1, row[0]);
|
|
psync_sql_bind_uint(res2, 2, row[1]);
|
|
psync_sql_bind_uint(res2, 3, hash);
|
|
psync_sql_bind_uint(res2, 4, fileid);
|
|
if ((row2=psync_sql_fetch_rowstr(res2)))
|
|
hasit=1;
|
|
else
|
|
hasit=0;
|
|
psync_sql_free_result(res2);
|
|
if (!hasit){
|
|
debug(D_NOTICE, "downloading file %s with hash %ld to local folder %lu", name->str, (long)hash, (unsigned long)row[1]);
|
|
psync_task_download_file_silent(row[0], fileid, row[1], name->str);
|
|
needdownload=1;
|
|
}
|
|
else
|
|
debug(D_NOTICE, "file %s with hash %ld already exists in local folder %lu", name->str, (long)hash, (unsigned long)row[1]);
|
|
}
|
|
psync_sql_free_result(res);
|
|
}
|
|
}
|
|
|
|
static void process_modifyfile(const binresult *entry){
|
|
static psync_sql_res *sq=NULL, *st=NULL;
|
|
psync_sql_res *res;
|
|
psync_full_result_int *fres1, *fres2;
|
|
const binresult *meta, *name, *enc;
|
|
const char *oldname;
|
|
size_t oldnamelen;
|
|
psync_variant_row row;
|
|
psync_fileid_t fileid;
|
|
psync_folderid_t parentfolderid, oldparentfolderid;
|
|
uint64_t size, userid, hash, oldsize;
|
|
int oldsync, newsync, lneeddownload, needrename;
|
|
uint32_t cnt, i;
|
|
if (!entry){
|
|
if (sq){
|
|
psync_sql_free_result(sq);
|
|
sq=NULL;
|
|
}
|
|
if (st){
|
|
psync_sql_free_result(st);
|
|
st=NULL;
|
|
}
|
|
process_createfile(NULL);
|
|
return;
|
|
}
|
|
meta=psync_find_result(entry, "metadata", PARAM_HASH);
|
|
fileid=psync_find_result(meta, "fileid", PARAM_NUM)->num;
|
|
name=psync_find_result(meta, "name", PARAM_STR);
|
|
if (sq)
|
|
psync_sql_reset(sq);
|
|
else
|
|
sq=psync_sql_query("SELECT parentfolderid, userid, size, hash, name FROM file WHERE id=?");
|
|
psync_sql_bind_uint(sq, 1, fileid);
|
|
row=psync_sql_fetch_row(sq);
|
|
if (!row){
|
|
debug(D_ERROR, "got modify for non-existing file %lu (%s), processing as create", (unsigned long)fileid, name->str);
|
|
process_createfile(entry);
|
|
return;
|
|
}
|
|
oldsize=psync_get_number(row[2]);
|
|
if (psync_get_number(row[1])==psync_my_userid)
|
|
used_quota-=oldsize;
|
|
if (!st)
|
|
st=psync_sql_prep_statement("UPDATE file SET id=?, parentfolderid=?, userid=?, size=?, hash=?, name=?, ctime=?, mtime=?, category=?, thumb=?, icon=?, "
|
|
"artist=?, album=?, title=?, genre=?, trackno=?, width=?, height=?, duration=?, fps=?, videocodec=?, audiocodec=?, videobitrate=?, "
|
|
"audiobitrate=?, audiosamplerate=?, rotate=? WHERE id=?");
|
|
size=psync_find_result(meta, "size", PARAM_NUM)->num;
|
|
parentfolderid=psync_find_result(meta, "parentfolderid", PARAM_NUM)->num;
|
|
hash=psync_find_result(meta, "hash", PARAM_NUM)->num;
|
|
enc=psync_check_result(meta, "encrypted", PARAM_BOOL);
|
|
if (enc && enc->num){
|
|
res=psync_sql_prep_statement("DELETE FROM cryptofilekey WHERE fileid=? AND hash!=?");
|
|
psync_sql_bind_uint(res, 1, fileid);
|
|
psync_sql_bind_uint(res, 2, hash);
|
|
psync_sql_run_free(res);
|
|
}
|
|
if (psync_find_result(meta, "ismine", PARAM_BOOL)->num){
|
|
userid=psync_my_userid;
|
|
used_quota+=size;
|
|
}
|
|
else
|
|
userid=psync_find_result(meta, "userid", PARAM_NUM)->num;
|
|
check_for_deletedfileid(meta);
|
|
psync_sql_bind_uint(st, 1, fileid);
|
|
psync_sql_bind_uint(st, 2, parentfolderid);
|
|
psync_sql_bind_uint(st, 3, userid);
|
|
psync_sql_bind_uint(st, 4, size);
|
|
psync_sql_bind_uint(st, 5, hash);
|
|
psync_sql_bind_lstring(st, 6, name->str, name->length);
|
|
i=bind_meta(st, meta, 7);
|
|
psync_sql_bind_uint(st, i, fileid);
|
|
psync_sql_run(st);
|
|
insert_revision(fileid, hash, psync_find_result(meta, "modified", PARAM_NUM)->num, size);
|
|
oldparentfolderid=psync_get_number(row[0]);
|
|
oldsync=psync_is_folder_in_downloadlist(oldparentfolderid);
|
|
if (oldparentfolderid==parentfolderid)
|
|
newsync=oldsync;
|
|
else{
|
|
newsync=psync_is_folder_in_downloadlist(parentfolderid);
|
|
psync_diff_refresh_fs_add_folder(oldparentfolderid);
|
|
}
|
|
if (oldsync || newsync){
|
|
if (psync_is_name_to_ignore(name->str)){
|
|
char *path;
|
|
psync_delete_download_tasks_for_file(fileid, 0, 1);
|
|
path=psync_get_path_by_fileid(fileid, NULL);
|
|
psync_task_delete_local_file(fileid, path);
|
|
psync_free(path);
|
|
needdownload=1;
|
|
return;
|
|
}
|
|
lneeddownload=hash!=psync_get_number(row[3]) || size!=oldsize;
|
|
oldname=psync_get_lstring(row[4], &oldnamelen);
|
|
if (lneeddownload)
|
|
psync_delete_download_tasks_for_file(fileid, 0, 0);
|
|
needrename=oldparentfolderid!=parentfolderid || name->length!=oldnamelen || memcmp(name->str, oldname, oldnamelen);
|
|
res=psync_sql_query("SELECT syncid, localfolderid, synctype FROM syncedfolder WHERE folderid=? AND "PSYNC_SQL_DOWNLOAD);
|
|
psync_sql_bind_uint(res, 1, oldparentfolderid);
|
|
fres1=psync_sql_fetchall_int(res);
|
|
res=psync_sql_query("SELECT syncid, localfolderid, synctype FROM syncedfolder WHERE folderid=? AND "PSYNC_SQL_DOWNLOAD);
|
|
psync_sql_bind_uint(res, 1, parentfolderid);
|
|
fres2=psync_sql_fetchall_int(res);
|
|
group_results_by_col(fres1, fres2, 0);
|
|
cnt=fres2->rows>fres1->rows?fres1->rows:fres2->rows;
|
|
// debug(D_NOTICE, "cnt=%u fres1->rows=%u, fres2->rows=%u, oldparentfolderid=%lu, parentfolderid=%lu", cnt, fres1->rows, fres2->rows, oldparentfolderid, parentfolderid);
|
|
for (i=0; i<cnt; i++){
|
|
if (needrename){
|
|
psync_task_rename_local_file(psync_get_result_cell(fres1, i, 0), psync_get_result_cell(fres2, i, 0), fileid,
|
|
psync_get_result_cell(fres1, i, 1), psync_get_result_cell(fres2, i, 1),
|
|
name->str);
|
|
needdownload=1;
|
|
}
|
|
if (lneeddownload){
|
|
res=psync_sql_query("SELECT 1 FROM localfile WHERE localparentfolderid=? AND fileid=? AND hash=? AND syncid=?");
|
|
psync_sql_bind_uint(res, 1, psync_get_result_cell(fres2, i, 1));
|
|
psync_sql_bind_uint(res, 2, fileid);
|
|
psync_sql_bind_uint(res, 3, hash);
|
|
psync_sql_bind_uint(res, 4, psync_get_result_cell(fres2, i, 0));
|
|
row=psync_sql_fetch_row(res);
|
|
psync_sql_free_result(res);
|
|
if (row)
|
|
debug(D_NOTICE, "ignoring update for file %s, has correct hash in the database", name->str);
|
|
else{
|
|
psync_task_download_file_silent(psync_get_result_cell(fres2, i, 0), fileid, psync_get_result_cell(fres2, i, 1), name->str);
|
|
needdownload=1;
|
|
}
|
|
}
|
|
}
|
|
for (/*i is already=cnt*/; i<fres2->rows; i++){
|
|
psync_task_download_file_silent(psync_get_result_cell(fres2, i, 0), fileid, psync_get_result_cell(fres2, i, 1), name->str);
|
|
needdownload=1;
|
|
}
|
|
for (/*i is already=cnt*/; i<fres1->rows; i++){
|
|
char *path=psync_get_path_by_fileid(fileid, NULL);
|
|
psync_task_delete_local_file_syncid(psync_get_result_cell(fres1, i, 0), fileid, path);
|
|
psync_delete_download_tasks_for_file(fileid, psync_get_result_cell(fres1, i, 0), 1);
|
|
psync_free(path);
|
|
needdownload=1;
|
|
}
|
|
psync_free(fres1);
|
|
psync_free(fres2);
|
|
}
|
|
}
|
|
|
|
static void process_deletefile(const binresult *entry){
|
|
static psync_sql_res *st=NULL;
|
|
const binresult *meta;
|
|
char *path;
|
|
psync_fileid_t fileid;
|
|
if (!entry){
|
|
if (st){
|
|
psync_sql_free_result(st);
|
|
st=NULL;
|
|
}
|
|
return;
|
|
}
|
|
if (!st){
|
|
st=psync_sql_prep_statement("DELETE FROM file WHERE id=?");
|
|
if (!st)
|
|
return;
|
|
}
|
|
meta=psync_find_result(entry, "metadata", PARAM_HASH);
|
|
fileid=psync_find_result(meta, "fileid", PARAM_NUM)->num;
|
|
if (psync_is_folder_in_downloadlist(psync_find_result(meta, "parentfolderid", PARAM_NUM)->num)){
|
|
psync_delete_download_tasks_for_file(fileid, 0, 1);
|
|
path=psync_get_path_by_fileid(fileid, NULL);
|
|
if (likely(path)){
|
|
psync_task_delete_local_file(fileid, path);
|
|
psync_free(path);
|
|
needdownload=1;
|
|
}
|
|
}
|
|
psync_sql_bind_uint(st, 1, fileid);
|
|
psync_sql_run(st);
|
|
if (psync_sql_affected_rows()){
|
|
if (psync_find_result(meta, "ismine", PARAM_BOOL)->num)
|
|
used_quota-=psync_find_result(meta, "size", PARAM_NUM)->num;
|
|
psync_fs_file_deleted(fileid);
|
|
}
|
|
}
|
|
|
|
void psync_diff_create_file(const binresult *meta){
|
|
psync_sql_res *st;
|
|
const binresult *name;
|
|
uint64_t userid, fileid, hash, size;
|
|
st=psync_sql_prep_statement("INSERT OR IGNORE INTO file (id, parentfolderid, userid, size, hash, name, ctime, mtime, category, thumb, icon, "
|
|
"artist, album, title, genre, trackno, width, height, duration, fps, videocodec, audiocodec, videobitrate, "
|
|
"audiobitrate, audiosamplerate, rotate) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
name=psync_find_result(meta, "name", PARAM_STR);
|
|
check_for_deletedfileid(meta);
|
|
if (psync_find_result(meta, "ismine", PARAM_BOOL)->num)
|
|
userid=psync_my_userid;
|
|
else
|
|
userid=psync_find_result(meta, "userid", PARAM_NUM)->num;
|
|
fileid=psync_find_result(meta, "fileid", PARAM_NUM)->num;
|
|
size=psync_find_result(meta, "size", PARAM_NUM)->num;
|
|
hash=psync_find_result(meta, "hash", PARAM_NUM)->num;
|
|
psync_sql_bind_uint(st, 1, fileid);
|
|
psync_sql_bind_uint(st, 2, psync_find_result(meta, "parentfolderid", PARAM_NUM)->num);
|
|
psync_sql_bind_uint(st, 3, userid);
|
|
psync_sql_bind_uint(st, 4, size);
|
|
psync_sql_bind_uint(st, 5, hash);
|
|
psync_sql_bind_lstring(st, 6, name->str, name->length);
|
|
bind_meta(st, meta, 7);
|
|
psync_sql_run_free(st);
|
|
insert_revision(fileid, hash, psync_find_result(meta, "modified", PARAM_NUM)->num, size);
|
|
insert_revision(0, 0, 0, 0);
|
|
}
|
|
|
|
static void start_download(){
|
|
if (needdownload){
|
|
psync_wake_download();
|
|
psync_status_recalc_to_download();
|
|
psync_send_status_update();
|
|
needdownload=0;
|
|
}
|
|
}
|
|
|
|
#define create_entry() \
|
|
binresult entry;\
|
|
hashpair pair;\
|
|
entry.type=PARAM_HASH;\
|
|
entry.length=1;\
|
|
entry.hash=&pair;\
|
|
pair.key="metadata";\
|
|
pair.value=(binresult *)meta;
|
|
|
|
void psync_diff_update_file(const binresult *meta){
|
|
create_entry();
|
|
process_modifyfile(&entry);
|
|
process_modifyfile(NULL);
|
|
start_download();
|
|
}
|
|
|
|
void psync_diff_delete_file(const binresult *meta){
|
|
create_entry();
|
|
process_deletefile(&entry);
|
|
process_deletefile(NULL);
|
|
start_download();
|
|
}
|
|
|
|
void psync_diff_update_folder(const binresult *meta){
|
|
create_entry();
|
|
process_modifyfolder(&entry);
|
|
process_modifyfolder(NULL);
|
|
start_download();
|
|
}
|
|
|
|
void psync_diff_delete_folder(const binresult *meta){
|
|
create_entry();
|
|
process_deletefolder(&entry);
|
|
process_deletefolder(NULL);
|
|
start_download();
|
|
}
|
|
|
|
static void stop_crypto_thread(){
|
|
psync_crypto_stop();
|
|
delete_cached_crypto_keys();
|
|
}
|
|
|
|
static void process_modifyuserinfo(const binresult *entry){
|
|
const binresult *res, *cres;
|
|
psync_sql_res *q;
|
|
uint64_t u, crexp, crsub = 0;
|
|
int crst = 0,crstat;
|
|
|
|
if (!entry)
|
|
return;
|
|
res=psync_find_result(entry, "userinfo", PARAM_HASH);
|
|
q=psync_sql_prep_statement("REPLACE INTO setting (id, value) VALUES (?, ?)");
|
|
|
|
cres=psync_check_result(res, "userid", PARAM_NUM);
|
|
if (cres){
|
|
psync_sql_bind_string(q, 1, "userid");
|
|
psync_sql_bind_uint(q, 2, cres->num);
|
|
psync_sql_run(q);
|
|
}
|
|
|
|
psync_sql_bind_string(q, 1, "quota");
|
|
current_quota=psync_find_result(res, "quota", PARAM_NUM)->num;
|
|
psync_sql_bind_uint(q, 2, current_quota);
|
|
psync_sql_run(q);
|
|
cres = psync_check_result(res, "freequota", PARAM_NUM);
|
|
if (cres){
|
|
free_quota = cres->num;
|
|
}
|
|
psync_sql_bind_string(q, 1, "freequota");
|
|
psync_sql_bind_uint(q, 2, free_quota);
|
|
psync_sql_run(q);
|
|
u=psync_find_result(res, "premium", PARAM_BOOL)->num;
|
|
psync_sql_bind_string(q, 1, "premium");
|
|
psync_sql_bind_uint(q, 2, u);
|
|
psync_sql_run(q);
|
|
if (u)
|
|
u=psync_find_result(res, "premiumexpires", PARAM_NUM)->num;
|
|
else
|
|
u=0;
|
|
psync_sql_bind_string(q, 1, "premiumexpires");
|
|
psync_sql_bind_uint(q, 2, u);
|
|
psync_sql_run(q);
|
|
psync_sql_bind_string(q, 1, "emailverified");
|
|
psync_sql_bind_uint(q, 2, psync_find_result(res, "emailverified", PARAM_BOOL)->num);
|
|
psync_sql_run(q);
|
|
psync_sql_bind_string(q, 1, "username");
|
|
psync_sql_bind_string(q, 2, psync_find_result(res, "email", PARAM_STR)->str);
|
|
psync_sql_run(q);
|
|
psync_sql_bind_string(q, 1, "language");
|
|
psync_sql_bind_string(q, 2, psync_find_result(res, "language", PARAM_STR)->str);
|
|
psync_sql_run(q);
|
|
psync_sql_bind_string(q, 1, "plan");
|
|
psync_sql_bind_uint(q, 2, psync_find_result(res, "plan", PARAM_NUM)->num);
|
|
psync_sql_run(q);
|
|
psync_sql_bind_string(q, 1, "business");
|
|
psync_sql_bind_uint(q, 2, psync_find_result(res, "business", PARAM_BOOL)->num);
|
|
psync_sql_run(q);
|
|
psync_sql_bind_string(q, 1, "premiumlifetime");
|
|
psync_sql_bind_uint(q, 2, psync_find_result(res, "premiumlifetime", PARAM_BOOL)->num);
|
|
psync_sql_run(q);
|
|
|
|
cres = psync_check_result(res, "vivapcloud", PARAM_BOOL);
|
|
if (cres){
|
|
psync_sql_bind_string(q, 1, "vivapcloud");
|
|
psync_sql_bind_uint(q, 2, cres->num);
|
|
psync_sql_run(q);
|
|
}
|
|
|
|
cres = psync_check_result(res, "family", PARAM_HASH);
|
|
if (cres){
|
|
psync_sql_bind_string(q, 1, "owner");
|
|
psync_sql_bind_uint(q, 2, psync_find_result(cres, "owner", PARAM_BOOL)->num);
|
|
psync_sql_run(q);
|
|
}
|
|
cres=psync_check_result(res, "cryptov2isactive", PARAM_BOOL);
|
|
psync_set_bool_setting("cryptov2isactive", cres?cres->num:0);
|
|
u=psync_find_result(res, "cryptosetup", PARAM_BOOL)->num;
|
|
psync_sql_bind_string(q, 1, "cryptosetup");
|
|
psync_sql_bind_uint(q, 2, u);
|
|
psync_sql_run(q);
|
|
if (!u)
|
|
psync_run_thread("stop crypto moduserinfo", stop_crypto_thread);
|
|
else
|
|
crst = 1;
|
|
psync_sql_bind_string(q, 1, "cryptosubscription");
|
|
crsub = psync_find_result(res, "cryptosubscription", PARAM_BOOL)->num;
|
|
psync_sql_bind_uint(q, 2, crsub);
|
|
psync_sql_run(q);
|
|
cres=psync_check_result(res, "cryptoexpires", PARAM_NUM);
|
|
crexp = cres?cres->num:0;
|
|
psync_sql_bind_string(q, 1, "cryptoexpires");
|
|
psync_sql_bind_uint(q, 2, crexp);
|
|
psync_sql_run(q);
|
|
if (psync_is_business || crsub){
|
|
if (crst)
|
|
crstat = 5;
|
|
else crstat = 4;
|
|
} else {
|
|
if (!crst)
|
|
crstat = 1;
|
|
else
|
|
{
|
|
if (psync_time() > crexp)
|
|
crstat = 3;
|
|
else
|
|
crstat = 2;
|
|
}
|
|
}
|
|
psync_sql_bind_string(q, 1, "cryptostatus");
|
|
psync_sql_bind_uint(q, 2, crstat);
|
|
psync_sql_run(q);
|
|
psync_sql_free_result(q);
|
|
psync_send_eventid(PEVENT_USERINFO_CHANGED);
|
|
}
|
|
|
|
#define fill_str(f, s, sl)\
|
|
do {\
|
|
if (s && sl) {\
|
|
memcpy(str, s, sl);\
|
|
f=str;\
|
|
str+=sl;\
|
|
}\
|
|
else\
|
|
f="";\
|
|
} while (0);
|
|
|
|
static void send_share_notify(psync_eventtype_t eventid, const binresult *share, int isba){
|
|
psync_share_event_t *e;
|
|
char *str, *sharename;
|
|
const char *message;
|
|
char *email = "tralalal@tralala.com";
|
|
const binresult *br;
|
|
uint64_t ctime;
|
|
size_t stringslen, sharenamelen, messagelen;
|
|
size_t emaillen = 254;
|
|
int freesharename;
|
|
const binresult *permissions;
|
|
uint64_t teamid = 0;
|
|
uint64_t touserid = 0;
|
|
uint64_t fromuserid = 0;
|
|
|
|
if (initialdownload)
|
|
return;
|
|
stringslen=0;
|
|
ctime=0;
|
|
if (!(br=psync_check_result(share, "frommail", PARAM_STR)) && !(br=psync_check_result(share, "tomail", PARAM_STR))){
|
|
if(!(br=psync_check_result(share, "touserid", PARAM_NUM)) &&
|
|
!(br=psync_check_result(share, "fromuserid", PARAM_NUM)) &&
|
|
!(br=psync_check_result(share, "toteamid", PARAM_NUM)) ) {
|
|
debug(D_WARNING, "Neigher frommail or tomail nor buissines share found for eventtype %u", (unsigned)eventid);
|
|
return;
|
|
}
|
|
}
|
|
if (isba) {
|
|
if((br=psync_check_result(share, "user", PARAM_BOOL)) && br->num)
|
|
touserid = psync_find_result(share, "touserid", PARAM_NUM)->num;
|
|
|
|
if((br=psync_check_result(share, "team", PARAM_BOOL)) && br->num)
|
|
teamid = psync_find_result(share, "toteamid", PARAM_NUM)->num;
|
|
|
|
if((br=psync_check_result(share, "fromuserid", PARAM_NUM)))
|
|
fromuserid = br->num;
|
|
|
|
stringslen+= ++emaillen;
|
|
stringslen+= ++emaillen;
|
|
} else {
|
|
email=(char *)br->str;
|
|
emaillen=br->length+1;
|
|
stringslen+=2*(br->length+1);
|
|
}
|
|
if ((br=psync_check_result(share, "message", PARAM_STR))){
|
|
message=br->str;
|
|
messagelen=br->length+1;
|
|
stringslen+=br->length+1;
|
|
}
|
|
else{
|
|
message=NULL;
|
|
messagelen=0;
|
|
}
|
|
if ((br=psync_check_result(share, "foldername", PARAM_STR)) || ( br=psync_check_result(share, "sharename", PARAM_STR))){
|
|
sharename=(char *)br->str;
|
|
sharenamelen=br->length+1;
|
|
stringslen+=br->length+1;
|
|
freesharename=0;
|
|
}
|
|
else{
|
|
psync_sql_res *res;
|
|
psync_variant_row row;
|
|
const char *cstr;
|
|
|
|
if ((br=psync_check_result(share, "shareid", PARAM_NUM)))
|
|
if (isba)
|
|
res=psync_sql_query("SELECT name, ctime FROM bsharedfolder WHERE id=? ");
|
|
else
|
|
res=psync_sql_query("SELECT name, ctime FROM sharedfolder WHERE id=? ");
|
|
else if ((br=psync_check_result(share, "sharerequestid", PARAM_NUM)))
|
|
res=psync_sql_query("SELECT name, ctime FROM sharerequest WHERE id=? ");
|
|
else {
|
|
debug(D_WARNING, "Neither sharename, shareid or sharerequestid found for eventtype %u", (unsigned)eventid);
|
|
return;
|
|
}
|
|
psync_sql_bind_uint(res, 1, br->num);
|
|
if ((row=psync_sql_fetch_row(res))){
|
|
cstr=psync_get_lstring(row[0], &sharenamelen);
|
|
stringslen+=++sharenamelen;
|
|
sharename=(char *)psync_malloc(sharenamelen);
|
|
memcpy(sharename, cstr, sharenamelen);
|
|
freesharename=1;
|
|
ctime=psync_get_number(row[1]);
|
|
}
|
|
else
|
|
sharename=NULL;
|
|
psync_sql_free_result(res);
|
|
if (!sharename){
|
|
debug(D_WARNING, "Could not find sharedfolder or sharerequest in the database.");
|
|
return;
|
|
}
|
|
}
|
|
e=(psync_share_event_t *)psync_malloc(sizeof(psync_share_event_t)+stringslen);
|
|
str=(char *)(e+1);
|
|
memset(e, 0, sizeof(psync_share_event_t));
|
|
e->folderid=psync_find_result(share, "folderid", PARAM_NUM)->num;
|
|
fill_str(e->sharename, sharename, sharenamelen);
|
|
if (freesharename)
|
|
psync_free(sharename);
|
|
|
|
fill_str(e->message, message, messagelen);
|
|
if ((br=psync_check_result(share, "userid", PARAM_NUM)))
|
|
e->userid=br->num;
|
|
if ((br=psync_check_result(share, "shareid", PARAM_NUM)))
|
|
e->shareid=br->num;
|
|
if ((br=psync_check_result(share, "sharerequestid", PARAM_NUM)))
|
|
e->sharerequestid=br->num;
|
|
if (isba) {
|
|
if ((br=psync_check_result(share, "shared", PARAM_NUM)))
|
|
ctime=br->num;
|
|
} else
|
|
if ((br=psync_check_result(share, "created", PARAM_NUM)))
|
|
ctime=br->num;
|
|
e->created=ctime;
|
|
permissions =psync_check_result(share, "permissions", PARAM_HASH);
|
|
if (isba && permissions) {
|
|
e->canread=psync_find_result(permissions, "canread", PARAM_BOOL)->num;
|
|
e->cancreate=psync_find_result(permissions, "cancreate", PARAM_BOOL)->num;
|
|
e->canmodify=psync_find_result(permissions, "canmodify", PARAM_BOOL)->num;
|
|
e->candelete=psync_find_result(permissions, "candelete", PARAM_BOOL)->num;
|
|
e->canmanage=psync_find_result(permissions, "canmanage", PARAM_BOOL)->num;
|
|
} else {
|
|
const binresult *canread = psync_check_result (share, "canread", PARAM_BOOL);
|
|
if (canread) {
|
|
e->canread=canread->num;
|
|
e->cancreate=psync_find_result(share, "cancreate", PARAM_BOOL)->num;
|
|
e->canmodify=psync_find_result(share, "canmodify", PARAM_BOOL)->num;
|
|
e->candelete=psync_find_result(share, "candelete", PARAM_BOOL)->num;
|
|
} else {
|
|
e->canread=0;
|
|
e->cancreate=0;
|
|
e->canmodify=0;
|
|
e->candelete=0;
|
|
}
|
|
}
|
|
if (isba) {
|
|
notify_paramst *params = psync_malloc(sizeof(notify_paramst));
|
|
params->eventid = eventid;
|
|
params->event_data = e;
|
|
params->touserid = touserid;
|
|
params->fromuserid = fromuserid;
|
|
params->teamid = teamid;
|
|
params->str = str;
|
|
psync_run_thread1("Share notify", do_send_eventdata, params);
|
|
} else {
|
|
fill_str(e->toemail, email, emaillen);
|
|
fill_str(e->fromemail, email, emaillen);
|
|
psync_send_eventdata(eventid, e);
|
|
}
|
|
}
|
|
|
|
static void do_send_eventdata(void * param) {
|
|
notify_paramst * data = (notify_paramst *)param;
|
|
char *email;
|
|
size_t emaillen;
|
|
char *str = data->str;
|
|
|
|
get_ba_member_email(data->fromuserid, &email, &emaillen);
|
|
fill_str(data->event_data->fromemail, email, emaillen);
|
|
psync_free(email);
|
|
|
|
if(data->touserid)
|
|
get_ba_member_email(data->touserid, &email, &emaillen);
|
|
else
|
|
get_ba_team_name(data->teamid, &email, &emaillen);
|
|
fill_str(data->event_data->toemail, email, emaillen);
|
|
psync_free(email);
|
|
|
|
if (email) {
|
|
psync_diff_lock();
|
|
psync_send_eventdata(data->eventid, data->event_data);
|
|
psync_diff_unlock();
|
|
}
|
|
|
|
psync_free(param);
|
|
}
|
|
|
|
static void process_requestsharein(const binresult *entry){
|
|
psync_sql_res *q;
|
|
const binresult *share, *br;
|
|
int isincomming = 1;
|
|
uint64_t folderowneruserid = 0, owneruserid, folderid;
|
|
|
|
if (!entry)
|
|
return;
|
|
share=psync_find_result(entry, "share", PARAM_HASH);
|
|
folderid = psync_find_result(share, "folderid", PARAM_NUM)->num;
|
|
psync_get_folder_ownerid(folderid, &folderowneruserid);
|
|
psync_get_current_userid(&owneruserid);
|
|
isincomming = (folderowneruserid == owneruserid) ? 0 : 1;
|
|
|
|
|
|
send_share_notify(((isincomming) ? PEVENT_SHARE_REQUESTIN : PEVENT_SHARE_REQUESTOUT ), share, 0);
|
|
q=psync_sql_prep_statement("REPLACE INTO sharerequest (id, folderid, ctime, etime, permissions, userid, mail, name, message, isincoming, isba) "
|
|
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
psync_sql_bind_uint(q, 1, psync_find_result(share, "sharerequestid", PARAM_NUM)->num);
|
|
psync_sql_bind_uint(q, 2, psync_find_result(share, "folderid", PARAM_NUM)->num);
|
|
psync_sql_bind_uint(q, 3, psync_find_result(share, "created", PARAM_NUM)->num);
|
|
psync_sql_bind_uint(q, 4, psync_find_result(share, "expires", PARAM_NUM)->num);
|
|
psync_sql_bind_uint(q, 5, psync_get_permissions(share));
|
|
psync_sql_bind_uint(q, 6, psync_find_result(share, "fromuserid", PARAM_NUM)->num);
|
|
br=psync_find_result(share, "frommail", PARAM_STR);
|
|
psync_sql_bind_lstring(q, 7, br->str, br->length);
|
|
if(!(br=psync_check_result(share, "foldername", PARAM_STR)))
|
|
br=psync_check_result(share, "sharename", PARAM_STR);
|
|
psync_sql_bind_lstring(q, 8, br->str, br->length);
|
|
br=psync_check_result(share, "message", PARAM_STR);
|
|
if (br)
|
|
psync_sql_bind_lstring(q, 9, br->str, br->length);
|
|
else
|
|
psync_sql_bind_null(q, 9);
|
|
psync_sql_bind_uint(q, 10, isincomming);
|
|
psync_sql_bind_uint(q, 11, !isincomming);
|
|
psync_sql_run_free(q);
|
|
}
|
|
|
|
static void process_requestshareout(const binresult *entry){
|
|
psync_sql_res *q;
|
|
const binresult *share, *br;
|
|
int isincomming = 0;
|
|
uint64_t folderowneruserid = 0, owneruserid, folderid;
|
|
|
|
if (!entry)
|
|
return;
|
|
|
|
share=psync_find_result(entry, "share", PARAM_HASH);
|
|
folderid = psync_find_result(share, "folderid", PARAM_NUM)->num;
|
|
psync_get_folder_ownerid(folderid, &folderowneruserid);
|
|
psync_get_current_userid(&owneruserid);
|
|
isincomming = (folderowneruserid == owneruserid) ? 0 : 1;
|
|
|
|
send_share_notify(((isincomming) ? PEVENT_SHARE_REQUESTIN : PEVENT_SHARE_REQUESTOUT ), share, 0);
|
|
q=psync_sql_prep_statement("REPLACE INTO sharerequest (id, folderid, ctime, etime, permissions, userid, mail, name, message, isincoming, isba) "
|
|
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
psync_sql_bind_uint(q, 1, psync_find_result(share, "sharerequestid", PARAM_NUM)->num);
|
|
psync_sql_bind_uint(q, 2, folderid);
|
|
psync_sql_bind_uint(q, 3, psync_find_result(share, "created", PARAM_NUM)->num);
|
|
psync_sql_bind_uint(q, 4, psync_find_result(share, "expires", PARAM_NUM)->num);
|
|
psync_sql_bind_uint(q, 5, psync_get_permissions(share));
|
|
psync_sql_bind_uint(q, 6, folderowneruserid);
|
|
br=psync_find_result(share, "tomail", PARAM_STR);
|
|
psync_sql_bind_lstring(q, 7, br->str, br->length);
|
|
if(!(br=psync_check_result(share, "foldername", PARAM_STR)))
|
|
br=psync_check_result(share, "sharename", PARAM_STR);
|
|
psync_sql_bind_lstring(q, 8, br->str, br->length);
|
|
br=psync_check_result(share, "message", PARAM_STR);
|
|
if (br)
|
|
psync_sql_bind_lstring(q, 9, br->str, br->length);
|
|
else
|
|
psync_sql_bind_null(q, 9);
|
|
psync_sql_bind_uint(q, 10, isincomming);
|
|
psync_sql_bind_uint(q, 11, isincomming);
|
|
psync_sql_run_free(q);
|
|
}
|
|
|
|
static void process_acceptedsharein(const binresult *entry){
|
|
psync_sql_res *q;
|
|
const binresult *share, *br;
|
|
if (!entry)
|
|
return;
|
|
share=psync_find_result(entry, "share", PARAM_HASH);
|
|
send_share_notify(PEVENT_SHARE_ACCEPTIN, share, 0);
|
|
q=psync_sql_prep_statement("DELETE FROM sharerequest WHERE id=?");
|
|
psync_sql_bind_uint(q, 1, psync_find_result(share, "sharerequestid", PARAM_NUM)->num);
|
|
psync_sql_run_free(q);
|
|
q=psync_sql_prep_statement("REPLACE INTO sharedfolder (id, isincoming, folderid, ctime, permissions, userid, mail, name) "
|
|
"VALUES (?, 1, ?, ?, ?, ?, ?, ?)");
|
|
debug(D_WARNING, "INSERT NORMAL SHARE IN id: %lld", (long long) psync_find_result(share, "shareid", PARAM_NUM)->num);
|
|
psync_sql_bind_uint(q, 1, psync_find_result(share, "shareid", PARAM_NUM)->num);
|
|
psync_sql_bind_uint(q, 2, psync_find_result(share, "folderid", PARAM_NUM)->num);
|
|
psync_sql_bind_uint(q, 3, psync_find_result(share, "created", PARAM_NUM)->num);
|
|
psync_sql_bind_uint(q, 4, psync_get_permissions(share));
|
|
psync_sql_bind_uint(q, 5, psync_find_result(share, "fromuserid", PARAM_NUM)->num);
|
|
br=psync_find_result(share, "frommail", PARAM_STR);
|
|
psync_sql_bind_lstring(q, 6, br->str, br->length);
|
|
if(!(br=psync_check_result(share, "foldername", PARAM_STR)))
|
|
br=psync_check_result(share, "sharename", PARAM_STR);
|
|
psync_sql_bind_lstring(q, 7, br->str, br->length);
|
|
psync_sql_run_free(q);
|
|
}
|
|
|
|
static void process_establishbsharein(const binresult *entry){
|
|
psync_sql_res *q;
|
|
const binresult *share, *br;
|
|
|
|
if (!entry)
|
|
return;
|
|
share=psync_find_result(entry, "share", PARAM_HASH);
|
|
send_share_notify(PEVENT_SHARE_ACCEPTIN, share, 1);
|
|
|
|
q=psync_sql_prep_statement("REPLACE INTO bsharedfolder (id, isincoming, folderid, ctime, permissions, message, name, isuser, "
|
|
"touserid, isteam, toteamid, fromuserid, folderownerid)"
|
|
"VALUES (?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
psync_sql_bind_int(q, 1, psync_find_result(share, "shareid", PARAM_NUM)->num);
|
|
psync_sql_bind_uint(q, 2, psync_find_result(share, "folderid", PARAM_NUM)->num);
|
|
if ((br=psync_check_result(share, "shared", PARAM_NUM)) || (br=psync_check_result(entry, "time", PARAM_NUM)))
|
|
psync_sql_bind_uint(q, 3, br->num);
|
|
else
|
|
psync_sql_bind_uint(q, 3, 0);
|
|
psync_sql_bind_uint(q, 4, psync_get_permissions(psync_find_result(share, "permissions", PARAM_HASH)));
|
|
br=psync_check_result(share, "message", PARAM_STR);
|
|
if (br)
|
|
psync_sql_bind_lstring(q, 5, br->str, br->length);
|
|
else
|
|
psync_sql_bind_null(q, 5);
|
|
if(!(br=psync_check_result(share, "foldername", PARAM_STR)))
|
|
br=psync_check_result(share, "sharename", PARAM_STR);
|
|
psync_sql_bind_lstring(q, 6, br->str, br->length);
|
|
br = psync_check_result(share, "user", PARAM_BOOL);
|
|
if(br)
|
|
psync_sql_bind_int(q, 7, br->num);
|
|
else
|
|
psync_sql_bind_int(q, 7, 0);
|
|
br = psync_check_result(share, "touserid", PARAM_NUM);
|
|
if (br)
|
|
psync_sql_bind_int(q, 8, br->num);
|
|
else
|
|
psync_sql_bind_null(q, 8);
|
|
br = psync_check_result(share, "team", PARAM_BOOL);
|
|
if(br)
|
|
psync_sql_bind_int(q, 9, br->num);
|
|
else
|
|
psync_sql_bind_int(q, 9, 0);
|
|
br = psync_check_result(share, "toteamid", PARAM_NUM);
|
|
if (br)
|
|
psync_sql_bind_int(q, 10, br->num);
|
|
else
|
|
psync_sql_bind_null(q, 10);
|
|
psync_sql_bind_int(q, 11, psync_find_result(share, "fromuserid", PARAM_NUM)->num);
|
|
psync_sql_bind_int(q, 12, psync_find_result(share, "folderownerid", PARAM_NUM)->num);
|
|
|
|
psync_sql_run_free(q);
|
|
}
|
|
|
|
static void process_acceptedshareout(const binresult *entry){
|
|
psync_sql_res *q;
|
|
const binresult *share, *br;
|
|
uint32_t aff = 0;
|
|
int isincomming = 0;
|
|
uint64_t folderowneruserid = 0, owneruserid, folderid;
|
|
|
|
if (!entry)
|
|
return;
|
|
share=psync_find_result(entry, "share", PARAM_HASH);
|
|
q=psync_sql_prep_statement("DELETE FROM sharerequest WHERE id=?");
|
|
psync_sql_bind_uint(q, 1, psync_find_result(share, "sharerequestid", PARAM_NUM)->num);
|
|
psync_sql_run(q);
|
|
aff=psync_sql_affected_rows();
|
|
psync_sql_free_result(q);
|
|
if (aff) {
|
|
|
|
folderid = psync_find_result(share, "folderid", PARAM_NUM)->num;
|
|
psync_get_folder_ownerid(folderid, &folderowneruserid);
|
|
psync_get_current_userid(&owneruserid);
|
|
isincomming = (folderowneruserid == owneruserid) ? 0 : 1;
|
|
|
|
send_share_notify(((isincomming) ? PEVENT_SHARE_REQUESTIN : PEVENT_SHARE_REQUESTOUT ), share, 0);
|
|
|
|
q=psync_sql_prep_statement("REPLACE INTO sharedfolder (id, folderid, ctime, permissions, userid, mail, name, isincoming) "
|
|
"VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
|
|
psync_sql_bind_uint(q, 1, psync_find_result(share, "shareid", PARAM_NUM)->num);
|
|
psync_sql_bind_uint(q, 2, psync_find_result(share, "folderid", PARAM_NUM)->num);
|
|
psync_sql_bind_uint(q, 3, psync_find_result(share, "created", PARAM_NUM)->num);
|
|
psync_sql_bind_uint(q, 4, psync_get_permissions(share));
|
|
psync_sql_bind_uint(q, 5, psync_find_result(share, "touserid", PARAM_NUM)->num);
|
|
br=psync_find_result(share, "tomail", PARAM_STR);
|
|
psync_sql_bind_lstring(q, 6, br->str, br->length);
|
|
if(!(br=psync_check_result(share, "foldername", PARAM_STR)))
|
|
br=psync_check_result(share, "sharename", PARAM_STR);
|
|
psync_sql_bind_lstring(q, 7, br->str, br->length);
|
|
psync_sql_bind_uint(q, 8, isincomming);
|
|
psync_sql_run_free(q);
|
|
}
|
|
}
|
|
|
|
static void process_establishbshareout(const binresult *entry) {
|
|
psync_sql_res *q;
|
|
const binresult *share, *br, *ownid, *fromuserid;
|
|
char *email = 0;
|
|
int isincomming = 0;
|
|
uint64_t folderowneruserid, owneruserid;
|
|
|
|
if (!entry)
|
|
return;
|
|
|
|
share=psync_find_result(entry, "share", PARAM_HASH);
|
|
ownid=psync_check_result(share, "folderownerid", PARAM_NUM);
|
|
if(ownid){
|
|
folderowneruserid = ownid->num;
|
|
psync_get_current_userid(&owneruserid);
|
|
fromuserid=psync_check_result(share, "fromuserid", PARAM_NUM);
|
|
if (fromuserid&&fromuserid->num==owneruserid){
|
|
isincomming=0;
|
|
}
|
|
else
|
|
{
|
|
isincomming=(folderowneruserid==owneruserid)?0:1;
|
|
}
|
|
}
|
|
send_share_notify(((isincomming) ? PEVENT_SHARE_REQUESTIN : PEVENT_SHARE_REQUESTOUT ), share, 1);
|
|
|
|
q=psync_sql_prep_statement("REPLACE INTO bsharedfolder (id, folderid, ctime, permissions, message, name, isuser, "
|
|
"touserid, isteam, toteamid, fromuserid, folderownerid, isincoming)"
|
|
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
psync_sql_bind_int(q, 1, psync_find_result(share, "shareid", PARAM_NUM)->num);
|
|
psync_sql_bind_uint(q, 2, psync_find_result(share, "folderid", PARAM_NUM)->num);
|
|
if ((br=psync_check_result(share, "shared", PARAM_NUM)) || (br=psync_check_result(entry, "time", PARAM_NUM)))
|
|
psync_sql_bind_uint(q, 3, br->num);
|
|
else
|
|
psync_sql_bind_uint(q, 3, 0);
|
|
psync_sql_bind_uint(q, 4, psync_get_permissions(psync_find_result(share, "permissions", PARAM_HASH)));
|
|
br=psync_find_result(share, "message", PARAM_STR);
|
|
psync_sql_bind_lstring(q, 5, br->str, br->length);
|
|
if(!(br=psync_check_result(share, "foldername", PARAM_STR)))
|
|
br=psync_check_result(share, "sharename", PARAM_STR);
|
|
psync_sql_bind_lstring(q, 6, br->str, br->length);
|
|
br = psync_check_result(share, "user", PARAM_BOOL);
|
|
if(br)
|
|
psync_sql_bind_int(q, 7, br->num);
|
|
else
|
|
psync_sql_bind_int(q, 7, 0);
|
|
br = psync_check_result(share, "touserid", PARAM_NUM);
|
|
if (br)
|
|
psync_sql_bind_int(q, 8, br->num);
|
|
else
|
|
psync_sql_bind_null(q, 8);
|
|
br = psync_check_result(share, "team", PARAM_BOOL);
|
|
if(br)
|
|
psync_sql_bind_int(q, 9, br->num);
|
|
else
|
|
psync_sql_bind_int(q, 9, 0);
|
|
br = psync_check_result(share, "toteamid", PARAM_NUM);
|
|
if (br)
|
|
psync_sql_bind_int(q, 10, br->num);
|
|
else
|
|
psync_sql_bind_null(q, 10);
|
|
psync_sql_bind_int(q, 11, psync_find_result(share, "fromuserid", PARAM_NUM)->num);
|
|
psync_sql_bind_int(q, 12, psync_find_result(share, "folderownerid", PARAM_NUM)->num);
|
|
psync_sql_bind_int(q, 13, isincomming);
|
|
|
|
psync_sql_run_free(q);
|
|
if (email)
|
|
psync_free(email);
|
|
}
|
|
|
|
static void delete_share_request(const binresult *share){
|
|
psync_sql_res *q;
|
|
q=psync_sql_prep_statement("DELETE FROM sharerequest WHERE id=?");
|
|
psync_sql_bind_uint(q, 1, psync_find_result(share, "sharerequestid", PARAM_NUM)->num);
|
|
psync_sql_run_free(q);
|
|
}
|
|
|
|
static void process_declinedsharein(const binresult *entry){
|
|
const binresult *share;
|
|
if (!entry)
|
|
return;
|
|
share=psync_find_result(entry, "share", PARAM_HASH);
|
|
send_share_notify(PEVENT_SHARE_DECLINEIN, share, 0);
|
|
delete_share_request(share);
|
|
}
|
|
|
|
static void process_declinedshareout(const binresult *entry){
|
|
const binresult *share;
|
|
if (!entry)
|
|
return;
|
|
share=psync_find_result(entry, "share", PARAM_HASH);
|
|
send_share_notify(PEVENT_SHARE_DECLINEOUT, share, 0);
|
|
delete_share_request(share);
|
|
}
|
|
|
|
static void process_cancelledsharein(const binresult *entry){
|
|
const binresult *share;
|
|
if (!entry)
|
|
return;
|
|
share=psync_find_result(entry, "share", PARAM_HASH);
|
|
send_share_notify(PEVENT_SHARE_CANCELIN, share, 0);
|
|
delete_share_request(share);
|
|
}
|
|
|
|
static void process_cancelledshareout(const binresult *entry){
|
|
const binresult *share;
|
|
if (!entry)
|
|
return;
|
|
share=psync_find_result(entry, "share", PARAM_HASH);
|
|
send_share_notify(PEVENT_SHARE_CANCELOUT, share, 0);
|
|
delete_share_request(share);
|
|
}
|
|
|
|
static void delete_shared_folder(const binresult *share){
|
|
psync_sql_res *q;
|
|
uint64_t shareid;
|
|
q=psync_sql_prep_statement("DELETE FROM sharedfolder WHERE id=?");
|
|
shareid = psync_find_result(share, "shareid", PARAM_NUM)->num;
|
|
psync_sql_bind_uint(q, 1, shareid);
|
|
psync_sql_run_free(q);
|
|
}
|
|
|
|
static void delete_bsshared_folder(const binresult *share){
|
|
psync_sql_res *q;
|
|
uint64_t shareid;
|
|
shareid = psync_find_result(share, "shareid", PARAM_NUM)->num;
|
|
|
|
q=psync_sql_prep_statement("DELETE FROM bsharedfolder WHERE id=?");
|
|
psync_sql_bind_uint(q, 1, shareid);
|
|
psync_sql_run_free(q);
|
|
}
|
|
|
|
static void process_removedsharein(const binresult *entry){
|
|
const binresult *share;
|
|
if (!entry)
|
|
return;
|
|
share=psync_find_result(entry, "share", PARAM_HASH);
|
|
send_share_notify(PEVENT_SHARE_REMOVEIN, share, 0);
|
|
delete_shared_folder(share);
|
|
}
|
|
|
|
static void process_removebsharein(const binresult *entry){
|
|
const binresult *share;
|
|
if (!entry)
|
|
return;
|
|
share=psync_find_result(entry, "share", PARAM_HASH);
|
|
send_share_notify(PEVENT_SHARE_REMOVEIN, share, 1);
|
|
delete_bsshared_folder(share);
|
|
}
|
|
|
|
static void process_removedshareout(const binresult *entry){
|
|
const binresult *share;
|
|
if (!entry)
|
|
return;
|
|
share=psync_find_result(entry, "share", PARAM_HASH);
|
|
send_share_notify(PEVENT_SHARE_REMOVEOUT, share, 0);
|
|
delete_shared_folder(share);
|
|
}
|
|
|
|
static void process_removebshareout(const binresult *entry){
|
|
const binresult *share;
|
|
if (!entry)
|
|
return;
|
|
share=psync_find_result(entry, "share", PARAM_HASH);
|
|
send_share_notify(PEVENT_SHARE_REMOVEOUT, share, 1);
|
|
delete_bsshared_folder(share);
|
|
}
|
|
|
|
static void modify_shared_folder(const binresult *perms, uint64_t shareid){
|
|
psync_sql_res *q;
|
|
q=psync_sql_prep_statement("UPDATE sharedfolder SET permissions=? WHERE id=?");
|
|
psync_sql_bind_uint(q, 1, psync_get_permissions(perms));
|
|
psync_sql_bind_uint(q, 2, shareid);
|
|
psync_sql_run_free(q);
|
|
}
|
|
|
|
static void modify_bshared_folder(const binresult *perms, uint64_t shareid){
|
|
psync_sql_res *q;
|
|
q=psync_sql_prep_statement("UPDATE bsharedfolder SET permissions=? WHERE id=?");
|
|
psync_sql_bind_uint(q, 1, psync_get_permissions(perms));
|
|
psync_sql_bind_uint(q, 2, shareid);
|
|
psync_sql_run_free(q);
|
|
}
|
|
|
|
static void process_modifiedsharein(const binresult *entry){
|
|
const binresult *share;
|
|
if (!entry)
|
|
return;
|
|
share=psync_find_result(entry, "share", PARAM_HASH);
|
|
send_share_notify(PEVENT_SHARE_MODIFYIN, share, 0);
|
|
modify_shared_folder(share, psync_find_result(share, "shareid", PARAM_NUM)->num);
|
|
}
|
|
|
|
static void process_modifiedshareout(const binresult *entry){
|
|
const binresult *share;
|
|
if (!entry)
|
|
return;
|
|
share=psync_find_result(entry, "share", PARAM_HASH);
|
|
send_share_notify(PEVENT_SHARE_MODIFYOUT, share, 0);
|
|
modify_shared_folder(share, psync_find_result(share, "shareid", PARAM_NUM)->num);
|
|
}
|
|
|
|
static void process_modifybsharein(const binresult *entry){
|
|
const binresult *share;
|
|
if (!entry)
|
|
return;
|
|
share=psync_find_result(entry, "share", PARAM_HASH);
|
|
send_share_notify(PEVENT_SHARE_MODIFYIN, share, 1);
|
|
modify_bshared_folder(psync_find_result(share, "permissions", PARAM_HASH),
|
|
psync_find_result(share, "shareid", PARAM_NUM)->num);
|
|
}
|
|
|
|
static void process_modifybshareout(const binresult *entry){
|
|
const binresult *share;
|
|
if (!entry)
|
|
return;
|
|
share=psync_find_result(entry, "share", PARAM_HASH);
|
|
send_share_notify(PEVENT_SHARE_MODIFYOUT, share, 1);
|
|
modify_bshared_folder(psync_find_result(share, "permissions", PARAM_HASH),
|
|
psync_find_result(share, "shareid", PARAM_NUM)->num);
|
|
}
|
|
|
|
static void process_cryptopasschange(const binresult *entry){
|
|
delete_cached_crypto_keys();
|
|
}
|
|
|
|
static void process_modifyaccountinfo(const binresult *entry){
|
|
const binresult *res;
|
|
psync_userid_t ret;
|
|
if (!entry)
|
|
return;
|
|
res=psync_find_result(entry, "metadata", PARAM_HASH);
|
|
psync_set_string_setting("companyname", psync_find_result(res, "companyname", PARAM_STR)->str);
|
|
psync_set_uint_setting("owneruserid", psync_find_result(res, "owneruserid", PARAM_NUM)->num);
|
|
psync_get_current_userid(&ret);
|
|
if (psync_get_uint_setting("owneruserid")==ret){
|
|
psync_set_bool_value("owner", 1);
|
|
}
|
|
psync_set_string_setting("ownerfirstname", psync_find_result(res, "ownerfirstname", PARAM_STR)->str);
|
|
psync_set_string_setting("ownerlastname", psync_find_result(res, "ownerlastname", PARAM_STR)->str);
|
|
psync_set_string_setting("owneremail", psync_find_result(res, "owneremail", PARAM_STR)->str);
|
|
psync_set_bool_setting("owner_cryptosetup", psync_find_result(res, "cryptosetup", PARAM_BOOL)->num);
|
|
}
|
|
|
|
#define FN(n) {process_##n, #n, sizeof(#n)-1, 0}
|
|
|
|
static struct {
|
|
void (*process)(const binresult *);
|
|
const char *name;
|
|
uint32_t len;
|
|
uint8_t used;
|
|
} event_list[] = {
|
|
FN(createfolder),
|
|
FN(modifyfolder),
|
|
FN(deletefolder),
|
|
FN(createfile),
|
|
FN(modifyfile),
|
|
FN(deletefile),
|
|
FN(modifyuserinfo),
|
|
FN(requestsharein),
|
|
FN(requestshareout),
|
|
FN(acceptedsharein),
|
|
FN(acceptedshareout),
|
|
FN(declinedsharein),
|
|
FN(declinedshareout),
|
|
FN(cancelledsharein),
|
|
FN(cancelledshareout),
|
|
FN(removedsharein),
|
|
FN(removedshareout),
|
|
FN(modifiedsharein),
|
|
FN(modifiedshareout),
|
|
FN(establishbsharein),
|
|
FN(establishbshareout),
|
|
FN(modifybsharein),
|
|
FN(modifybshareout),
|
|
FN(removebsharein),
|
|
FN(removebshareout),
|
|
FN(cryptopasschange),
|
|
FN(modifyaccountinfo)
|
|
};
|
|
|
|
#define event_list_size ARRAY_SIZE(event_list)
|
|
|
|
void psync_diff_lock(){
|
|
pthread_mutex_lock(&diff_mutex);
|
|
}
|
|
|
|
void psync_diff_unlock(){
|
|
pthread_mutex_unlock(&diff_mutex);
|
|
}
|
|
|
|
static uint64_t process_entries(const binresult *entries, uint64_t newdiffid){
|
|
const binresult *entry, *etype;
|
|
uint64_t oused_quota;
|
|
uint32_t i, j;
|
|
oused_quota=used_quota;
|
|
needdownload=0;
|
|
psync_diff_lock();
|
|
if (psync_status_get(PSTATUS_TYPE_AUTH)!=PSTATUS_AUTH_PROVIDED){
|
|
psync_diff_unlock();
|
|
return psync_sql_cellint("SELECT value FROM setting WHERE id='diffid'", 0);
|
|
}
|
|
psync_sql_start_transaction();
|
|
if (entries->length>=10000)
|
|
psync_sql_statement("DELETE FROM setting WHERE id='lastanalyze'");
|
|
for (i=0; i<entries->length; i++){
|
|
entry=entries->array[i];
|
|
etype=psync_find_result(entry, "event", PARAM_STR);
|
|
for (j=0; j<event_list_size; j++)
|
|
if (etype->length==event_list[j].len && !memcmp(etype->str, event_list[j].name, etype->length)){
|
|
event_list[j].process(entry);
|
|
event_list[j].used=1;
|
|
}
|
|
}
|
|
for (j=0; j<event_list_size; j++)
|
|
if (event_list[j].used)
|
|
event_list[j].process(NULL);
|
|
psync_set_uint_value("diffid", newdiffid);
|
|
psync_set_uint_value("usedquota", used_quota);
|
|
//update_ba_emails();
|
|
//update_ba_teams();
|
|
psync_path_status_clear_path_cache();
|
|
psync_sql_commit_transaction();
|
|
psync_diff_unlock();
|
|
if (needdownload){
|
|
psync_wake_download();
|
|
psync_status_recalc_to_download();
|
|
psync_send_status_update();
|
|
needdownload=0;
|
|
}
|
|
used_quota=psync_sql_cellint("SELECT value FROM setting WHERE id='usedquota'", 0);
|
|
if (oused_quota!=used_quota)
|
|
psync_send_eventid(PEVENT_USEDQUOTA_CHANGED);
|
|
return psync_sql_cellint("SELECT value FROM setting WHERE id='diffid'", 0);
|
|
}
|
|
|
|
static void check_overquota(){
|
|
static int lisover=0;
|
|
int isover=(used_quota>=current_quota);
|
|
if (isover!=lisover){
|
|
lisover=isover;
|
|
if (isover) {
|
|
psync_set_status(PSTATUS_TYPE_ACCFULL, PSTATUS_ACCFULL_OVERQUOTA);
|
|
}
|
|
else
|
|
psync_set_status(PSTATUS_TYPE_ACCFULL, PSTATUS_ACCFULL_QUOTAOK);
|
|
}
|
|
}
|
|
|
|
static void diff_exception_handler(){
|
|
debug(D_NOTICE, "got exception");
|
|
if (likely(exceptionsockwrite!=INVALID_SOCKET))
|
|
psync_pipe_write(exceptionsockwrite, "e", 1);
|
|
}
|
|
|
|
static psync_socket_t setup_exeptions(){
|
|
psync_socket_t pfds[2];
|
|
if (psync_pipe(pfds)==SOCKET_ERROR)
|
|
return INVALID_SOCKET;
|
|
exceptionsockwrite=pfds[1];
|
|
psync_timer_exception_handler(diff_exception_handler);
|
|
return pfds[0];
|
|
}
|
|
|
|
static int send_diff_command(psync_socket *sock, subscribed_ids ids){
|
|
if (psync_notifications_running()){
|
|
const char *ts=psync_notifications_get_thumb_size();
|
|
if (ts){
|
|
if (psync_is_business) {
|
|
binparam diffparams[]={P_STR("subscribefor", "diff,notifications,publinks,uploadlinks,teams,users,contacts"), P_STR("timeformat", "timestamp"),
|
|
P_NUM("difflimit", PSYNC_DIFF_LIMIT), P_NUM("diffid", ids.diffid),
|
|
P_NUM("notificationid", ids.notificationid), P_STR("notificationthumbsize", ts), P_NUM("publinkid", ids.publinkid),
|
|
P_NUM("uploadlinkid", ids.uploadlinkid)};
|
|
return send_command_no_res(sock, "subscribe", diffparams)?0:-1;
|
|
} else {
|
|
binparam diffparams[]={P_STR("subscribefor", "diff,notifications,publinks,uploadlinks,contacts"), P_STR("timeformat", "timestamp"),
|
|
P_NUM("difflimit", PSYNC_DIFF_LIMIT), P_NUM("diffid", ids.diffid),
|
|
P_NUM("notificationid", ids.notificationid), P_STR("notificationthumbsize", ts), P_NUM("publinkid", ids.publinkid),
|
|
P_NUM("uploadlinkid", ids.uploadlinkid)};
|
|
return send_command_no_res(sock, "subscribe", diffparams)?0:-1;
|
|
}
|
|
}
|
|
else{
|
|
if (psync_is_business) {
|
|
binparam diffparams[]={P_STR("subscribefor", "diff,notifications,publinks,uploadlinks,teams,users,contacts"), P_STR("timeformat", "timestamp"),
|
|
P_NUM("difflimit", PSYNC_DIFF_LIMIT), P_NUM("diffid", ids.diffid), P_NUM("notificationid", ids.notificationid), P_NUM("publinkid", ids.publinkid),
|
|
P_NUM("uploadlinkid", ids.uploadlinkid)};
|
|
return send_command_no_res(sock, "subscribe", diffparams)?0:-1;
|
|
} else {
|
|
binparam diffparams[]={P_STR("subscribefor", "diff,notifications,publinks,uploadlinks,contacts"), P_STR("timeformat", "timestamp"),
|
|
P_NUM("difflimit", PSYNC_DIFF_LIMIT), P_NUM("diffid", ids.diffid), P_NUM("notificationid", ids.notificationid), P_NUM("publinkid", ids.publinkid),
|
|
P_NUM("uploadlinkid", ids.uploadlinkid)};
|
|
return send_command_no_res(sock, "subscribe", diffparams)?0:-1;
|
|
}
|
|
}
|
|
}
|
|
else{
|
|
if (psync_is_business) {
|
|
binparam diffparams[]={P_STR("subscribefor", "diff,publinks,uploadlinks,teams,users,contacts"), P_STR("timeformat", "timestamp"), P_NUM("difflimit", PSYNC_DIFF_LIMIT),
|
|
P_NUM("diffid", ids.diffid), P_NUM("publinkid", ids.publinkid), P_NUM("uploadlinkid", ids.uploadlinkid)};
|
|
return send_command_no_res(sock, "subscribe", diffparams)?0:-1;
|
|
} else {
|
|
binparam diffparams[]={P_STR("subscribefor", "diff,publinks,uploadlinks,contacts"), P_STR("timeformat", "timestamp"), P_NUM("difflimit", PSYNC_DIFF_LIMIT),
|
|
P_NUM("diffid", ids.diffid), P_NUM("publinkid", ids.publinkid), P_NUM("uploadlinkid", ids.uploadlinkid)};
|
|
return send_command_no_res(sock, "subscribe", diffparams)?0:-1;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void handle_exception(psync_socket **sock, subscribed_ids *ids, char ex){
|
|
if (ex=='c'){
|
|
if (last_event>=psync_timer_time()-1)
|
|
return;
|
|
if (psync_select_in(&(*sock)->sock, 1, 1000)!=0){
|
|
debug(D_NOTICE, "got a psync_diff_wake() but no diff events in one second, closing socket");
|
|
psync_socket_close(*sock);
|
|
if (psync_status_get(PSTATUS_TYPE_AUTH)!=PSTATUS_AUTH_PROVIDED)
|
|
ids->notificationid=0;
|
|
debug(D_NOTICE, "waiting for new socket");
|
|
*sock=get_connected_socket();
|
|
debug(D_NOTICE, "got new socket");
|
|
psync_set_status(PSTATUS_TYPE_ONLINE, PSTATUS_ONLINE_ONLINE);
|
|
psync_syncer_check_delayed_syncs();
|
|
ids->diffid=psync_sql_cellint("SELECT value FROM setting WHERE id='diffid'", 0);
|
|
send_diff_command(*sock, *ids);
|
|
}
|
|
return;
|
|
}
|
|
debug(D_NOTICE, "exception handler %c", ex);
|
|
if (ex=='r' ||
|
|
psync_status_get(PSTATUS_TYPE_RUN)==PSTATUS_RUN_STOP ||
|
|
psync_status_get(PSTATUS_TYPE_AUTH)!=PSTATUS_AUTH_PROVIDED ||
|
|
psync_setting_get_bool(_PS(usessl))!=psync_socket_isssl(*sock)){
|
|
psync_socket_close(*sock);
|
|
if (psync_status_get(PSTATUS_TYPE_AUTH)!=PSTATUS_AUTH_PROVIDED)
|
|
ids->notificationid=0;
|
|
debug(D_NOTICE, "waiting for new socket");
|
|
*sock=get_connected_socket();
|
|
debug(D_NOTICE, "got new socket");
|
|
psync_set_status(PSTATUS_TYPE_ONLINE, PSTATUS_ONLINE_ONLINE);
|
|
psync_syncer_check_delayed_syncs();
|
|
ids->diffid=psync_sql_cellint("SELECT value FROM setting WHERE id='diffid'", 0);
|
|
send_diff_command(*sock, *ids);
|
|
}
|
|
else if (ex=='e'){
|
|
binparam diffparams[]={P_STR("id", "ignore")};
|
|
if (!send_command_no_res(*sock, "nop", diffparams) || psync_select_in(&(*sock)->sock, 1, PSYNC_SOCK_TIMEOUT_ON_EXCEPTION*1000)!=0){
|
|
const char *prefixes[]={"API:", "HTTP"};
|
|
debug(D_NOTICE, "reconnecting diff");
|
|
psync_socket_close_bad(*sock);
|
|
psync_cache_clean_starting_with_one_of(prefixes, ARRAY_SIZE(prefixes));
|
|
*sock=get_connected_socket();
|
|
psync_set_status(PSTATUS_TYPE_ONLINE, PSTATUS_ONLINE_ONLINE);
|
|
psync_syncer_check_delayed_syncs();
|
|
send_diff_command(*sock, *ids);
|
|
}
|
|
else{
|
|
debug(D_NOTICE, "diff socket seems to be alive");
|
|
(*sock)->pending=1;
|
|
}
|
|
}
|
|
}
|
|
|
|
static int cmp_folderid(const void *ptr1, const void *ptr2){
|
|
psync_folderid_t *folderid1=(psync_folderid_t *)ptr1;
|
|
psync_folderid_t *folderid2=(psync_folderid_t *)ptr2;
|
|
if (folderid1<folderid2)
|
|
return -1;
|
|
else if (folderid1>folderid2)
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
typedef struct {
|
|
psync_folderid_t *refresh_folders;
|
|
uint32_t refresh_last;
|
|
} refresh_folders_ptr_t;
|
|
|
|
static psync_folderid_t *refresh_folders=NULL;
|
|
static uint32_t refresh_allocated=0;
|
|
static uint32_t refresh_last=0;
|
|
|
|
static void psync_diff_refresh_fs_add_folder(psync_folderid_t folderid){
|
|
if (psync_fs_need_per_folder_refresh()){
|
|
if (refresh_allocated==refresh_last){
|
|
if (refresh_allocated)
|
|
refresh_allocated*=2;
|
|
else
|
|
refresh_allocated=8;
|
|
refresh_folders=(psync_folderid_t *)psync_realloc(refresh_folders, sizeof(psync_folderid_t)*refresh_allocated);
|
|
}
|
|
refresh_folders[refresh_last++]=folderid;
|
|
}
|
|
}
|
|
|
|
static void psync_diff_refresh_thread(void *ptr){
|
|
refresh_folders_ptr_t *fr;
|
|
psync_folderid_t lastfolderid;
|
|
uint32_t i;
|
|
psync_milisleep(1000);
|
|
fr=(refresh_folders_ptr_t *)ptr;
|
|
qsort(fr->refresh_folders, fr->refresh_last, sizeof(psync_folderid_t), cmp_folderid);
|
|
lastfolderid=(psync_folderid_t)-1;
|
|
for (i=0; i<fr->refresh_last; i++)
|
|
if (fr->refresh_folders[i]!=lastfolderid){
|
|
psync_fs_refresh_folder(fr->refresh_folders[i]);
|
|
lastfolderid=fr->refresh_folders[i];
|
|
}
|
|
psync_free(fr->refresh_folders);
|
|
psync_free(fr);
|
|
}
|
|
|
|
static void psync_diff_refresh_fs(const binresult *entries){
|
|
if (psync_fs_need_per_folder_refresh()){
|
|
const binresult *meta;
|
|
refresh_folders_ptr_t *ptr;
|
|
psync_folderid_t folderid, lastfolderid;
|
|
uint32_t i;
|
|
lastfolderid=(psync_folderid_t)-1;
|
|
for (i=0; i<entries->length; i++){
|
|
meta=psync_check_result(entries->array[i], "metadata", PARAM_HASH);
|
|
if (!meta)
|
|
continue;
|
|
meta=psync_check_result(meta, "parentfolderid", PARAM_NUM);
|
|
if (!meta)
|
|
continue;
|
|
folderid=meta->num;
|
|
if (folderid==lastfolderid)
|
|
continue;
|
|
psync_diff_refresh_fs_add_folder(folderid);
|
|
lastfolderid=folderid;
|
|
}
|
|
if (!refresh_last)
|
|
return;
|
|
ptr=psync_new(refresh_folders_ptr_t);
|
|
ptr->refresh_folders=refresh_folders;
|
|
ptr->refresh_last=refresh_last;
|
|
psync_run_thread1("fs folder refresh", psync_diff_refresh_thread, ptr);
|
|
refresh_folders=NULL;
|
|
refresh_allocated=0;
|
|
refresh_last=0;
|
|
}
|
|
}
|
|
|
|
static void psync_run_analyze_if_needed(){
|
|
if (psync_timer_time()>psync_sql_cellint("SELECT value FROM setting WHERE id='lastanalyze'", 0)+24*3600){
|
|
static const char *skiptables[]={"pagecache", "sqlite_stat1"};
|
|
psync_sql_res *res;
|
|
psync_uint_row row;
|
|
psync_str_row srow;
|
|
char **tablenames;
|
|
char *sql;
|
|
size_t tablecnt, i;
|
|
debug(D_NOTICE, "running ANALYZE on tables");
|
|
res=psync_sql_query_rdlock("SELECT COUNT(*) FROM sqlite_master WHERE type='table'");
|
|
if ((row=psync_sql_fetch_rowint(res)))
|
|
tablecnt=row[0];
|
|
else
|
|
tablecnt=0;
|
|
psync_sql_free_result(res);
|
|
tablenames=psync_new_cnt(char *, tablecnt);
|
|
res=psync_sql_query_rdlock("SELECT name FROM sqlite_master WHERE type='table' LIMIT ?");
|
|
psync_sql_bind_uint(res, 1, tablecnt);
|
|
tablecnt=0;
|
|
while ((srow=psync_sql_fetch_rowstr(res))){
|
|
for (i=0; i<ARRAY_SIZE(skiptables); i++)
|
|
if (!strcmp(srow[0], skiptables[i]))
|
|
goto skip;
|
|
tablenames[tablecnt++]=psync_strdup(srow[0]);
|
|
skip:;
|
|
}
|
|
psync_sql_free_result(res);
|
|
|
|
while (tablecnt){
|
|
--tablecnt;
|
|
debug(D_NOTICE, "running ANALYZE on %s", tablenames[tablecnt]);
|
|
sql=psync_strcat("ANALYZE ", tablenames[tablecnt], ";", NULL);
|
|
psync_free(tablenames[tablecnt]);
|
|
psync_sql_statement(sql);
|
|
psync_free(sql);
|
|
debug(D_NOTICE, "table done");
|
|
psync_milisleep(5);
|
|
}
|
|
psync_free(tablenames);
|
|
res=psync_sql_prep_statement("REPLACE INTO setting (id, value) VALUES (?, ?)");
|
|
psync_sql_bind_string(res, 1, "lastanalyze");
|
|
psync_sql_bind_uint(res, 2, psync_timer_time());
|
|
psync_sql_run_free(res);
|
|
debug(D_NOTICE, "done running ANALYZE on tables");
|
|
}
|
|
}
|
|
|
|
static int psync_diff_check_quota(psync_socket *sock){
|
|
binparam diffparams[]={P_STR("timeformat", "timestamp"), P_BOOL("getapiserver", 1)};
|
|
binresult *res;
|
|
const binresult *uq;
|
|
uint64_t oused_quota, result;
|
|
oused_quota=used_quota;
|
|
res=send_command(sock, "userinfo", diffparams);
|
|
if (!res)
|
|
return -1;
|
|
result=psync_find_result(res, "result", PARAM_NUM)->num;
|
|
if (unlikely(result))
|
|
debug(D_WARNING, "userinfo returned error %u: %s", (unsigned)result, psync_find_result(res, "error", PARAM_STR)->str);
|
|
else{
|
|
uq=psync_check_result(res, "usedquota", PARAM_NUM);
|
|
if (likely_log(uq))
|
|
used_quota=uq->num;
|
|
}
|
|
if (used_quota!=oused_quota){
|
|
debug(D_WARNING, "corrected locally calculated quota from %lu to %lu", (unsigned long)oused_quota, (unsigned long)used_quota);
|
|
psync_set_uint_value("usedquota", used_quota);
|
|
psync_send_eventid(PEVENT_USEDQUOTA_CHANGED);
|
|
}
|
|
uq=psync_find_result(psync_find_result(res, "apiserver", PARAM_HASH), "binapi", PARAM_ARRAY);
|
|
if (uq->length)
|
|
psync_apipool_set_server(uq->array[0]->str);
|
|
psync_free(res);
|
|
return 0;
|
|
}
|
|
|
|
static void psync_cache_contacts(){
|
|
if (psync_is_business){
|
|
cache_account_emails();
|
|
cache_account_teams();
|
|
cache_ba_my_teams();
|
|
}
|
|
cache_links_all();
|
|
cache_contacts();
|
|
cache_shares();
|
|
psync_notify_cache_change(PACCOUNT_CHANGE_ALL);
|
|
}
|
|
|
|
static void psync_diff_adapter_hash(void *out){
|
|
psync_fast_hash256_ctx ctx;
|
|
psync_interface_list_t *list;
|
|
list=psync_list_ip_adapters();
|
|
/* if (IS_DEBUG){
|
|
char buffa[NI_MAXHOST], buffb[NI_MAXHOST], buffn[NI_MAXHOST];
|
|
size_t i;
|
|
for (i=0; i<list->interfacecnt; i++) {
|
|
getnameinfo((struct sockaddr *)&list->interfaces[i].address, list->interfaces[i].addrsize, buffa, sizeof(buffa), NULL, 0, NI_NUMERICHOST);
|
|
getnameinfo((struct sockaddr *)&list->interfaces[i].broadcast, list->interfaces[i].addrsize, buffb, sizeof(buffb), NULL, 0, NI_NUMERICHOST);
|
|
getnameinfo((struct sockaddr *)&list->interfaces[i].netmask, list->interfaces[i].addrsize, buffn, sizeof(buffn), NULL, 0, NI_NUMERICHOST);
|
|
debug(D_NOTICE, "%s %s %s", buffa, buffb, buffn);
|
|
}
|
|
debug(D_NOTICE, "list end");
|
|
} */
|
|
psync_fast_hash256_init(&ctx);
|
|
psync_fast_hash256_update(&ctx, list->interfaces, list->interfacecnt*sizeof(psync_interface_t));
|
|
psync_fast_hash256_final(out, &ctx);
|
|
psync_free(list);
|
|
}
|
|
|
|
static void psync_diff_adapter_timer(psync_timer_t timer, void *ptr){
|
|
unsigned char hash[PSYNC_FAST_HASH256_LEN];
|
|
psync_diff_adapter_hash(hash);
|
|
if (memcmp(adapter_hash, hash, PSYNC_FAST_HASH256_LEN)){
|
|
memcpy(adapter_hash, hash, PSYNC_FAST_HASH256_LEN);
|
|
debug(D_NOTICE, "network adapter list changed, sending exception");
|
|
psync_pipe_write(exceptionsockwrite, "e", 1);
|
|
}
|
|
}
|
|
|
|
void psync_diff_wake(){
|
|
if (last_event>=psync_timer_time()-1)
|
|
return;
|
|
psync_pipe_write(exceptionsockwrite, "c", 1);
|
|
}
|
|
|
|
static void psync_diff_thread(){
|
|
psync_socket *sock;
|
|
binresult *res;
|
|
const binresult *entries;
|
|
uint64_t newdiffid, result;
|
|
psync_socket_t exceptionsock, socks[2];
|
|
subscribed_ids ids = {0, 0, 0, 0};
|
|
int sel, ret=0;
|
|
char ex;
|
|
char *err=NULL;
|
|
psync_set_status(PSTATUS_TYPE_ONLINE, PSTATUS_ONLINE_CONNECTING);
|
|
psync_send_status_update();
|
|
restart:
|
|
psync_set_status(PSTATUS_TYPE_ONLINE, PSTATUS_ONLINE_CONNECTING);
|
|
sock=get_connected_socket();
|
|
debug(D_NOTICE, "connected");
|
|
psync_set_status(PSTATUS_TYPE_ONLINE, PSTATUS_ONLINE_SCANNING);
|
|
ids.diffid=psync_sql_cellint("SELECT value FROM setting WHERE id='diffid'", 0);
|
|
if (ids.diffid == 0) {
|
|
initialdownload=1;
|
|
}
|
|
used_quota=psync_sql_cellint("SELECT value FROM setting WHERE id='usedquota'", 0);
|
|
do{
|
|
binparam diffparams[]={P_STR("timeformat", "timestamp"), P_NUM("limit", PSYNC_DIFF_LIMIT), P_NUM("diffid", ids.diffid)};
|
|
if (!psync_do_run)
|
|
break;
|
|
res=send_command(sock, "diff", diffparams);
|
|
if (!res){
|
|
psync_socket_close(sock);
|
|
goto restart;
|
|
}
|
|
result=psync_find_result(res, "result", PARAM_NUM)->num;
|
|
if (unlikely(result)){
|
|
debug(D_ERROR, "diff returned error %u: %s", (unsigned int)result, psync_find_result(res, "error", PARAM_STR)->str);
|
|
psync_free(res);
|
|
psync_socket_close(sock);
|
|
psync_milisleep(PSYNC_SLEEP_BEFORE_RECONNECT);
|
|
goto restart;
|
|
}
|
|
entries=psync_find_result(res, "entries", PARAM_ARRAY);
|
|
if (entries->length){
|
|
newdiffid=psync_find_result(res, "diffid", PARAM_NUM)->num;
|
|
debug(D_NOTICE, "processing diff with %u entries", (unsigned)entries->length);
|
|
ids.diffid=process_entries(entries, newdiffid);
|
|
// psync_diff_refresh_fs(entries); -- don't do this for initial loading
|
|
debug(D_NOTICE, "got diff with %u entries, new diffid %lu", (unsigned)entries->length, (unsigned long)ids.diffid);
|
|
}
|
|
result=entries->length;
|
|
psync_free(res);
|
|
} while (result);
|
|
psync_fs_refresh_folder(0);
|
|
debug(D_NOTICE, "initial sync finished");
|
|
if (psync_diff_check_quota(sock)){
|
|
psync_socket_close(sock);
|
|
psync_milisleep(PSYNC_SLEEP_BEFORE_RECONNECT);
|
|
goto restart;
|
|
}
|
|
check_overquota();
|
|
psync_set_status(PSTATUS_TYPE_ONLINE, PSTATUS_ONLINE_ONLINE);
|
|
initialdownload=0;
|
|
psync_run_analyze_if_needed();
|
|
psync_syncer_check_delayed_syncs();
|
|
exceptionsock=setup_exeptions();
|
|
if (unlikely(exceptionsock==INVALID_SOCKET)){
|
|
debug(D_ERROR, "could not create pipe");
|
|
psync_socket_close(sock);
|
|
return;
|
|
}
|
|
socks[0]=exceptionsock;
|
|
socks[1]=sock->sock;
|
|
psync_diff_adapter_hash(adapter_hash);
|
|
psync_timer_register(psync_diff_adapter_timer, PSYNC_DIFF_CHECK_ADAPTER_CHANGE_SEC, NULL);
|
|
send_diff_command(sock, ids);
|
|
psync_milisleep(50);
|
|
last_event=0;
|
|
while (psync_do_run){
|
|
if (unlinked){
|
|
unlinked=0;
|
|
initialdownload=1;
|
|
}
|
|
if(psync_recache_contacts){
|
|
psync_cache_contacts();
|
|
psync_recache_contacts=0;
|
|
}
|
|
if (psync_socket_pendingdata(sock))
|
|
sel=1;
|
|
else
|
|
sel=psync_select_in(socks, 2, -1);
|
|
if (sel==0){
|
|
if (!psync_do_run)
|
|
break;
|
|
if (psync_pipe_read(exceptionsock, &ex, 1)!=1)
|
|
continue;
|
|
handle_exception(&sock, &ids, ex);
|
|
while (psync_select_in(socks, 1, 0)==0 && psync_pipe_read(exceptionsock, &ex, 1)==1);
|
|
socks[1]=sock->sock;
|
|
}
|
|
else if (sel==1){
|
|
sock->pending=1;
|
|
res=get_result(sock);
|
|
if (unlikely_log(!res)){
|
|
psync_timer_notify_exception();
|
|
handle_exception(&sock, &ids, 'r');
|
|
socks[1]=sock->sock;
|
|
last_event=0;
|
|
continue;
|
|
}
|
|
last_event=psync_timer_time();
|
|
result=psync_find_result(res, "result", PARAM_NUM)->num;
|
|
if (unlikely(result)){
|
|
if (result==6003 || result==6002){ // timeout or cancel
|
|
debug(D_NOTICE, "got \"%s\" from the socket", psync_find_result(res, "error", PARAM_STR)->str);
|
|
psync_free(res);
|
|
send_diff_command(sock, ids);
|
|
continue;
|
|
}
|
|
debug(D_ERROR, "diff returned error %u: %s", (unsigned int)result, psync_find_result(res, "error", PARAM_STR)->str);
|
|
psync_free(res);
|
|
handle_exception(&sock, &ids, 'r');
|
|
socks[1]=sock->sock;
|
|
continue;
|
|
}
|
|
entries=psync_check_result(res, "from", PARAM_STR);
|
|
if (entries){
|
|
if (entries->length==4 && !strcmp(entries->str, "diff")){
|
|
entries=psync_find_result(res, "entries", PARAM_ARRAY);
|
|
if (entries->length){
|
|
newdiffid=psync_find_result(res, "diffid", PARAM_NUM)->num;
|
|
ids.diffid=process_entries(entries, newdiffid);
|
|
psync_diff_refresh_fs(entries);
|
|
psync_diff_check_quota(sock);
|
|
check_overquota();
|
|
if (initialdownload)
|
|
initialdownload=0;
|
|
}
|
|
else
|
|
debug(D_NOTICE, "diff with 0 entries, did we send a nop recently?");
|
|
psync_free(res);
|
|
}
|
|
else if (entries->length==13 && !strcmp(entries->str, "notifications")){
|
|
ids.notificationid=psync_find_result(res, "notificationid", PARAM_NUM)->num;
|
|
// do not free res
|
|
psync_notifications_notify(res);
|
|
}
|
|
else if (entries->length==8 && !strcmp(entries->str, "publinks")){
|
|
ids.publinkid=psync_find_result(res, "publinkid", PARAM_NUM)->num;
|
|
ret = cache_links(&err);
|
|
if (ret < 0)
|
|
debug(D_ERROR, "Cacheing links faild with err %s", err);
|
|
else
|
|
psync_notify_cache_change(PACCOUNT_CHANGE_LINKS);
|
|
}
|
|
else if (entries->length==11 && !strcmp(entries->str, "uploadlinks")){
|
|
ids.uploadlinkid=psync_find_result(res, "uploadlinkid", PARAM_NUM)->num;
|
|
ret = cache_upload_links(&err);
|
|
if (ret < 0)
|
|
debug(D_ERROR, "Cacheing upload links failed with err %s", err);
|
|
else
|
|
psync_notify_cache_change(PACCOUNT_CHANGE_LINKS);
|
|
|
|
}
|
|
else if (entries->length==5 && !strcmp(entries->str, "teams")){
|
|
cache_account_teams();
|
|
cache_ba_my_teams();
|
|
psync_notify_cache_change(PACCOUNT_CHANGE_TEAMS);
|
|
}
|
|
else if (entries->length==5 && !strcmp(entries->str, "users")){
|
|
cache_account_emails();
|
|
psync_notify_cache_change(PACCOUNT_CHANGE_EMAILS);
|
|
}
|
|
else if (entries->length==8 && !strcmp(entries->str, "contacts")){
|
|
cache_contacts();
|
|
psync_notify_cache_change(PACCOUNT_CHANGE_CONTACTS);
|
|
}
|
|
else{
|
|
debug(D_NOTICE, "got no from, did we send a nop recently?");
|
|
psync_free(res);
|
|
}
|
|
send_diff_command(sock, ids);
|
|
}
|
|
else{
|
|
psync_free(res);
|
|
debug(D_NOTICE, "got no from, did we send a nop recently?");
|
|
}
|
|
}
|
|
}
|
|
psync_socket_close(sock);
|
|
psync_pipe_close(exceptionsock);
|
|
psync_pipe_close(exceptionsockwrite);
|
|
}
|
|
|
|
void psync_diff_init(){
|
|
psync_run_thread("diff", psync_diff_thread);
|
|
}
|