diff --git a/src/delagent/agent/delagent.c b/src/delagent/agent/delagent.c index abd36339..b6d905a1 100644 --- a/src/delagent/agent/delagent.c +++ b/src/delagent/agent/delagent.c @@ -1,179 +1,259 @@ /******************************************************** delagent: Remove an upload from the DB and repository Copyright (C) 2007-2013 Hewlett-Packard Development Company, L.P. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ********************************************************/ /** * \file delagent.c * \brief main for delagent * * delagent: Remove an upload from the DB and repository */ #include "delagent.h" #ifdef COMMIT_HASH_S char BuildVersion[]="delagent build version: " VERSION_S " r(" COMMIT_HASH_S ").\n"; #else char BuildVersion[]="delagent build version: NULL.\n"; #endif +/*********************************************** + Usage(): + Command line options allow you to write the agent so it works + stand alone, in addition to working with the scheduler. + This simplifies code development and testing. + So if you have options, have a Usage(). + Here are some suggested options (in addition to the program + specific options you may already have). + ***********************************************/ +void Usage (char *Name) +{ + fprintf(stderr,"Usage: %s [options]\n",Name); + fprintf(stderr," List or delete uploads.\n"); + fprintf(stderr," Options\n"); + fprintf(stderr," -i :: Initialize the DB, then exit.\n"); + fprintf(stderr," -u :: List uploads IDs.\n"); + fprintf(stderr," -U # :: Delete upload ID.\n"); + //fprintf(stderr," -L # :: Delete ALL licenses associated with upload ID.\n"); + fprintf(stderr," -f :: List folder IDs.\n"); + fprintf(stderr," -F # :: Delete folder ID and all uploads under this folder.\n"); + fprintf(stderr," Folder '1' is the default folder. '-F 1' will delete\n"); + fprintf(stderr," every upload and folder in the navigation tree.\n"); + fprintf(stderr," -s :: Run from the scheduler.\n"); + fprintf(stderr," -T :: TEST -- do not update the DB or delete any files (just pretend)\n"); + fprintf(stderr," -v :: Verbose (-vv for more verbose)\n"); + fprintf(stderr," -c # :: Specify the directory for the system configuration\n"); + fprintf(stderr," -V :: print the version info, then exit.\n"); + fprintf(stderr," --user|-n # :: user name\n"); + fprintf(stderr," --password|-p # :: password\n"); +} /* Usage() */ + +void writeMessageAfterDelete(char *kind, long id, char *user_name, int returnedCode) +{ + if (1 == returnedCode) + { + fprintf(stdout, "The %s '%ld' is deleted by the user '%s'.\n", kind, id, user_name); + } + else + { + LOG_FATAL("You '%s' does not have the permsssion to delete the %s '%ld', or the %s '%ld' does not exist.\n", user_name, kind, id, kind, id); + exit(returnedCode); + } +} + /** * \brief main function for the delagent * * There are 2 ways to use the delagent agent: * 1. Command Line :: delete/list upload from the command line * 2. Agent Based :: run from the scheduler * * +-----------------------+ * | Command Line Analysis | * +-----------------------+ * * List or delete uploads. * -h :: help (print this message), then exit. * -i :: Initialize the DB * -u :: List uploads IDs. * -U # :: Delete upload ID. * -L # :: Delete ALL licenses associated with upload ID. * -f :: List folder IDs. * -F # :: Delete folder ID and all uploads under this folder. * -T :: TEST -- do not update the DB or delete any files (just pretend). * -v :: Verbose (-vv for more verbose). * -V :: print the version info, then exit. * -c SYSCONFDIR :: Specify the directory for the system configuration. * --user # :: user name * --password # :: password * * +----------------------+ * | Agent Based Analysis | * +----------------------+ * * To run the delagent as an agent * -s :: Run from the scheduler * * * \param argc the number of command line arguments * \param argv the command line arguments * \return 0 on a successful program execution */ int main (int argc, char *argv[]) { int c; int ListProj=0, ListFolder=0; long DelUpload=0, DelFolder=0, DelLicense=0; int Scheduler=0; /* should it run from the scheduler? */ int GotArg=0; char *agent_desc = "Deletes upload. Other list/delete options available from the command line."; - char *Parm = NULL; //int Agent_pk = 0; char *COMMIT_HASH; char *VERSION; char agent_rev[myBUFSIZ]; int option_index = 0; char *user_name = NULL; char *password = NULL; int user_id = -1; int user_perm = -1; + int returnedCode = 0; - fo_scheduler_connect(&argc, argv, &db_conn); + fo_scheduler_connect(&argc, argv, &db_conn); - static struct option long_options[] = + static struct option long_options[] = { {"user", required_argument, 0, 'n'}, {"password", required_argument, 0, 'p'}, {0, 0, 0, 0} }; - + while ((c = getopt_long (argc, argv, "n:p:ifF:lL:sTuU:vVc:h", long_options, &option_index)) != -1) { switch (c) { - case 'n': + case 'n': user_name = optarg; - break; + break; case 'p': password = optarg; break; case 'i': PQfinish(db_conn); return(0); - case 'f': ListFolder=1; GotArg=1; break; - case 'F': DelFolder=atol(optarg); GotArg=1; break; - case 'L': DelLicense=atol(optarg); GotArg=1; break; - case 's': Scheduler=1; GotArg=1; break; - case 'T': Test++; break; - case 'u': ListProj=1; GotArg=1; break; - case 'U': DelUpload=atol(optarg); GotArg=1; break; - case 'v': Verbose++; break; - case 'c': GotArg=1; break; /* handled by fo_scheduler_connect() */ - case 'V': printf("%s", BuildVersion); PQfinish(db_conn); return(0); - default: Usage(argv[0]); exit(-1); + case 'f': + ListFolder=1; + GotArg=1; + break; + case 'F': + DelFolder=atol(optarg); + GotArg=1; + break; + case 'L': + DelLicense=atol(optarg); + GotArg=1; + break; + case 's': + Scheduler=1; + GotArg=1; + break; + case 'T': + Test++; + break; + case 'u': + ListProj=1; + GotArg=1; + break; + case 'U': + DelUpload=atol(optarg); + GotArg=1; + break; + case 'v': + Verbose++; + break; + case 'c': + GotArg=1; + break; /* handled by fo_scheduler_connect() */ + case 'V': + printf("%s", BuildVersion); + PQfinish(db_conn); + return(0); + default: + Usage(argv[0]); + exit(-1); } } if (!GotArg) { Usage(argv[0]); exit(-1); } - if (Scheduler != 1 && 1 != authentication(user_name, password, &user_id, &user_perm)) - { - LOG_FATAL("User name or password is invalid.\n"); - exit(-1); - } - - COMMIT_HASH = fo_sysconfig("delagent", "COMMIT_HASH"); - VERSION = fo_sysconfig("delagent", "VERSION"); - sprintf(agent_rev, "%s.%s", VERSION, COMMIT_HASH); - /* Get the Agent Key from the DB */ - fo_GetAgentKey(db_conn, basename(argv[0]), 0, agent_rev, agent_desc); - - if (ListProj) ListUploads(user_id, user_perm); - if (ListFolder) ListFolders(user_id); - - alarm(60); /* from this point on, handle the alarm */ - if (DelUpload) + if (Scheduler != 1) { - if (1 != check_permission_del(DelUpload, user_id, user_perm)) + if (1 != authentication(user_name, password, &user_id, &user_perm)) { - LOG_FATAL("You '%s' does not have the permsssion to delete the upload '%ld', or the upload '%ld' does not exist.\n", user_name, DelUpload, DelUpload); + LOG_FATAL("User name or password is invalid.\n"); exit(-1); } - DeleteUpload(DelUpload); - fprintf(stdout, "The upload '%ld' is deleted by the user '%s'.\n", DelUpload, user_name); - } - if (DelFolder) { DeleteFolder(DelFolder); } - if (DelLicense) { DeleteLicense(DelLicense); } - /* process from the scheduler */ - if (Scheduler) - { - while(fo_scheduler_next()) + COMMIT_HASH = fo_sysconfig("delagent", "COMMIT_HASH"); + VERSION = fo_sysconfig("delagent", "VERSION"); + sprintf(agent_rev, "%s.%s", VERSION, COMMIT_HASH); + /* Get the Agent Key from the DB */ + fo_GetAgentKey(db_conn, basename(argv[0]), 0, agent_rev, agent_desc); + + if (ListProj) { - Parm = fo_scheduler_current(); - - if (ReadParameter(Parm) < 0) - exit(-1); + ListUploads(user_id, user_perm); + } + if (ListFolder) + { + ListFolders(user_id, user_perm); + } + + alarm(60); /* from this point on, handle the alarm */ + if (DelUpload) + { + returnedCode = DeleteUpload(DelUpload, user_id, user_perm); + + writeMessageAfterDelete("upload", DelUpload, user_name, returnedCode); + } + if (DelFolder) + { + returnedCode = DeleteFolder(DelFolder, user_id, user_perm); + + writeMessageAfterDelete("folder", DelFolder, user_name, returnedCode); + } + if (DelLicense) + { + returnedCode = DeleteLicense(DelLicense, user_perm); + + writeMessageAfterDelete("license", DelLicense, user_name, returnedCode); } } + else + { + /* process from the scheduler */ + DoSchedulerTasks(); + } + fo_scheduler_disconnect(0); - PQfinish(db_conn); - fo_scheduler_disconnect(0); + PQfinish(db_conn); return(0); } /* main() */ - diff --git a/src/delagent/agent/delagent.h b/src/delagent/agent/delagent.h index 4fcaaeec..e2fbfc1c 100644 --- a/src/delagent/agent/delagent.h +++ b/src/delagent/agent/delagent.h @@ -1,59 +1,69 @@ /******************************************************** Copyright (C) 2007-2012 Hewlett-Packard Development Company, L.P. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ********************************************************/ #ifndef _DELAGENT_H #define _DELAGENT_H 1 #include #include #include #include #include #include #include #include #include #include #include #include #include "libfossology.h" extern int Verbose; extern int Test; /* for DB */ extern PGconn* db_conn; #define MAXSQL 1024 #define MAXLINE 1024 #define myBUFSIZ 2048 -#define ADMIN_PERM 10 - -void DeleteLicense(long UploadId); -void DeleteUpload(long UploadId); -void ListFoldersRecurse(long Parent, int Depth, long Row, int DelFlag); -int UnlinkContent (long child, long parent, int mode); -void ListFolders(int user_id); -void ListUploads (int user_id, int user_perm); -void DeleteFolder(long FolderId); -int ReadParameter(char *Parm); -void Usage(char *Name); + +/* authentication and permission checking */ int authentication(char *user, char * password, int *user_id, int *user_perm); -int check_permission_del(long upload_id, int user_id, int user_perm); + +int check_permission_upload(long upload_id, int user_id, int user_perm); +int check_permission_folder(long folder_id, int user_id, int user_perm); +int check_permission_license(long license_id, int user_id, int user_perm); + +/* functions that list things */ +void ListFolders(int user_id, int user_perm); +void ListUploads(int user_id, int user_perm); + +/* function that delete actual things */ +int DeleteLicense(long UploadId, int user_perm); +int DeleteUpload(long UploadId, int user_id, int user_perm); +int DeleteFolder(long FolderId, int user_id, int user_perm); + +/* for usage from scheduler */ +void DoSchedulerTasks(); +int ReadParameter(char *Parm, int user_id, int user_perm); + +/* misc */ +void Usage(char *Name); #endif /* _DELAGENT_H */ diff --git a/src/delagent/agent/util.c b/src/delagent/agent/util.c index ffa62468..d7236507 100644 --- a/src/delagent/agent/util.c +++ b/src/delagent/agent/util.c @@ -1,988 +1,1230 @@ /******************************************************** Copyright (C) 2007-2013 Hewlett-Packard Development Company, L.P. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ********************************************************/ /** * \file util.c * \brief local function of delagent * * delagent: Remove an upload from the DB and repository * */ #include "delagent.h" int Verbose = 0; int Test = 0; PGconn* db_conn = NULL; // the connection to Database +int verbosePrintf (const char *format, ...) +{ + va_list arg; + int done = 0; + + if (Verbose) + { + va_start (arg, format); + done = vprintf(format, arg); + va_end (arg); + } + + return done; +} + +/** + * \brief if this account is valid + * + * \param char *user - user name + * \param char *password - password + * \param int *user_id - will be set to the id of the user + * \param int *user_perm - will be set to the permission level of the user + * + * \return 1: yes, valid; -1: failure; 0: invalid + */ +int authentication(char *user, char *password, int *user_id, int *user_perm) +{ + if (NULL == user || NULL == password) + { + return 0; + } + char SQL[MAXSQL] = {0}; + PGresult *result; + char user_seed[myBUFSIZ] = {0}; + char pass_hash_valid[myBUFSIZ] = {0}; + unsigned char hash_value[myBUFSIZ] = {0}; + char pass_hash_actual[myBUFSIZ] = {0}; + + /** get user_seed, user_pass on one specified user */ + snprintf(SQL,sizeof(SQL),"SELECT user_seed, user_pass, user_perm, user_pk from users where user_name='%s';", user); + result = PQexec(db_conn, SQL); + if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) + { + return -1; + } + if (!PQntuples(result)){ + return 0; + } + strcpy(user_seed, PQgetvalue(result, 0, 0)); + strcpy(pass_hash_valid, PQgetvalue(result, 0, 1)); + *user_perm = atoi(PQgetvalue(result, 0, 2)); + *user_id = atoi(PQgetvalue(result, 0, 3)); + PQclear(result); + if (user_seed[0] && pass_hash_valid[0]) + { + strcat(user_seed, password); // get the hash code on seed+pass + SHA1((unsigned char *)user_seed, strlen(user_seed), hash_value); + if (!hash_value[0]) + { + LOG_FATAL("ERROR, failed to get sha1 value\n"); + return -1; + } + } + else + { + return -1; + } + int i = 0; + char temp[256] = {0}; + for (i = 0; i < strlen((char *)hash_value); i++) + { + sprintf(temp, "%02x", hash_value[i]); + strcat(pass_hash_actual, temp); + } + if (strcmp(pass_hash_valid, pass_hash_actual) == 0) + { + return 1; + } + else + { + return -1; + } +} + +/** + * \brief check if the upload can be deleted, that is the user have + * the permission to delete this upload + * + * \param long upload_id - upload id + * \param char *user_name - user name + * + * \return 1: yes, can be deleted; + * 0: can not be deleted + * -1: failure; + * -2: does not exist; + */ +int check_permission_upload(long upload_id, int user_id, int user_perm) +{ + char SQL[MAXSQL] = {0};; + PGresult *result = NULL; + int count = 0; + + snprintf(SQL,sizeof(SQL),"SELECT count(*) FROM upload join users on (users.user_pk = upload.user_fk or users.user_perm = 10) where upload_pk = %ld and users.user_pk = %d;", upload_id, user_id); + result = PQexec(db_conn, SQL); + if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) return -1; + count = atoi(PQgetvalue(result, 0, 0)); + if (count == 0) return -2; // this upload does not exist + + /* Check Permissions */ + if (GetUploadPerm(db_conn, upload_id, user_id) < PERM_WRITE) + { + LOG_ERROR("You have no update permissions on upload %ld", upload_id); + return 0; // can not be deleted + } + + return 1; // can be deleted +} + +/** + * \brief check if the upload can be deleted, that is the user have + * the permission to delete this upload + * + * \param long upload_id - upload id + * \param char *user_name - user name + * + * \return 1: yes, can be deleted; + * 0: can not be deleted + * -1: failure; + * -2: does not exist; + */ +int check_permission_folder(long folder_id, int user_id, int user_perm) +{ + char SQL[MAXSQL]; + PGresult *result; + int count = 0; + + memset(SQL,'\0',sizeof(SQL)); + snprintf(SQL,sizeof(SQL),"SELECT count(*) FROM folder join users on (users.user_pk = folder.user_fk or users.user_perm = 10) where folder_pk = %ld and users.user_pk = %d;",parent,user_id); + result = PQexec(db_conn, SQL); + if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1); + count = atol(PQgetvalue(result,0,0)); + if(count == 0){ + return 0; // can not be deleted + } + return 1; // can be deleted +} + +/** + * \brief check if the upload can be deleted, that is the user have + * the permissoin to delete this upload + * + * \param long upload_id - upload id + * \param char *user_name - user name + * + * \return 1: yes, can be deleted; + * 0: can not be deleted + * -1: failure; + * -2: does not exist; + */ +int check_permission_license(long license_id, int user_id, int user_perm) +{ + + if (user_perm != PERM_ADMIN) + { + /* if (Verbose) { printf("only admin is allowed to delete licenses\n"); } */ + return 0; // can not be deleted + } + return 1; // can be deleted +} + + /** * \brief DeleteLicense() - * + * * Given an upload ID, delete all licenses associated with it. * The DoBegin flag determines whether BEGIN/COMMIT should be called. * Do this if you want to reschedule license analysis. * * \param long UploadId the upload id + * + * \return 1: success; 0: fail */ -void DeleteLicense (long UploadId) +int DeleteLicense (long UploadId, int user_perm) { char TempTable[256]; char SQL[MAXSQL]; PGresult *result; long items=0; + if (1 != check_permission_upload(UploadId, user_perm)) + { + return 0; + } + if (Verbose) { printf("Deleting licenses for upload %ld\n",UploadId); } result = PQexec(db_conn, "SET statement_timeout = 0;"); /* no timeout */ - if (fo_checkPQcommand(db_conn, result, "SET statement_timeout = 0;", __FILE__, __LINE__)) exit(-1); - PQclear(result); + if (fo_checkPQcommand(db_conn, result, "SET statement_timeout = 0;", __FILE__, __LINE__)) + { + exit(-1); + } + PQclear(result); result = PQexec(db_conn, "BEGIN;"); - if (fo_checkPQcommand(db_conn, result, "BEGIN;", __FILE__, __LINE__)) exit(-1); + if (fo_checkPQcommand(db_conn, result, "BEGIN;", __FILE__, __LINE__)) + { + exit(-1); + } PQclear(result); - + memset(TempTable,'\0',sizeof(TempTable)); snprintf(TempTable,sizeof(TempTable),"DelLic_%ld",UploadId); /* Create the temp table */ - if (Verbose) { printf("# Creating temp table: %s\n",TempTable); } + verbosePrintf("# Creating temp table: %s\n",TempTable); /* Get the list of pfiles to process */ memset(SQL,'\0',sizeof(SQL)); snprintf(SQL,sizeof(SQL),"SELECT DISTINCT(pfile_fk) FROM uploadtree WHERE upload_fk = '%ld' ;",UploadId); result = PQexec(db_conn, SQL); - if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1); + if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) + { + exit(-1); + } items = PQntuples(result); PQclear(result); /***********************************************/ /* delete pfile licenses */ - if (Verbose) { printf("# Deleting licenses\n"); } + verbosePrintf("# Deleting licenses\n"); memset(SQL,'\0',sizeof(SQL)); snprintf(SQL,sizeof(SQL),"DELETE FROM licterm_name WHERE pfile_fk IN (SELECT pfile_fk FROM uploadtree WHERE upload_fk = '%ld');",UploadId); result = PQexec(db_conn, SQL); - if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1); + if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__)) + { + exit(-1); + } PQclear(result); memset(SQL,'\0',sizeof(SQL)); snprintf(SQL,sizeof(SQL),"DELETE FROM agent_lic_status WHERE pfile_fk IN (SELECT pfile_fk FROM uploadtree WHERE upload_fk = '%ld');",UploadId); result = PQexec(db_conn, SQL); - if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1); + if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__)) + { + exit(-1); + } PQclear(result); memset(SQL,'\0',sizeof(SQL)); snprintf(SQL,sizeof(SQL),"DELETE FROM agent_lic_meta WHERE pfile_fk IN (SELECT pfile_fk FROM uploadtree WHERE upload_fk = '%ld');",UploadId); result = PQexec(db_conn, SQL); - if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1); + if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__)) + { + exit(-1); + } PQclear(result); fo_scheduler_heart(items); /***********************************************/ /* Commit the change! */ - if (Verbose) { printf("# Delete completed\n"); } + verbosePrintf("# Delete completed\n"); if (Test) { result = PQexec(db_conn, "ROLLBACK;"); - if (fo_checkPQcommand(db_conn, result, "ROLLBACK", __FILE__, __LINE__)) exit(-1); + if (fo_checkPQcommand(db_conn, result, "ROLLBACK", __FILE__, __LINE__)) + { + exit(-1); + } PQclear(result); } else { result = PQexec(db_conn, "COMMIT;"); - if (fo_checkPQcommand(db_conn, result, "COMMIT", __FILE__, __LINE__)) exit(-1); + if (fo_checkPQcommand(db_conn, result, "COMMIT", __FILE__, __LINE__)) + { + exit(-1); + } PQclear(result); -#if 0 - /** Disabled: DB will take care of this **/ - if (Verbose) { printf("# Running vacuum and analyze\n"); } - MyDBaccess(DB,"VACUUM ANALYZE agent_lic_status;"); - MyDBaccess(DB,"VACUUM ANALYZE agent_lic_meta;"); -#endif } result = PQexec(db_conn, "SET statement_timeout = 120000;"); - if (fo_checkPQcommand(db_conn, result, "SET statement_timeout = 120000;", __FILE__, __LINE__)) exit(-1); + if (fo_checkPQcommand(db_conn, result, "SET statement_timeout = 120000;", __FILE__, __LINE__)) + { + exit(-1); + } PQclear(result); - if (Verbose) { printf("Deleted licenses for upload %ld\n",UploadId); } + verbosePrintf("Deleted licenses for upload %ld\n",UploadId); + + return 1; /* success */ } /* DeleteLicense() */ /** * \brief DeleteUpload() - * + * * Given an upload ID, delete it. * * param long UploadId the upload id + * + * \return 1: success; 0: fail */ -void DeleteUpload (long UploadId) +int DeleteUpload (long UploadId, int user_id, int user_perm) { char *S; int Row,MaxRow; char TempTable[256]; PGresult *result, *pfile_result; char SQL[MAXSQL]; + if (1 != check_permission_upload(UploadId, user_id, user_perm)) + { + return 0; + } + if (Verbose) { printf("Deleting upload %ld\n",UploadId); } result = PQexec(db_conn, "SET statement_timeout = 0;"); /* no timeout */ - if (fo_checkPQcommand(db_conn, result, "SET statement_timeout = 0;", __FILE__, __LINE__)) exit(-1); + if (fo_checkPQcommand(db_conn, result, "SET statement_timeout = 0;", __FILE__, __LINE__)) + { + exit(-1); + } PQclear(result); result = PQexec(db_conn, "BEGIN;"); - if (fo_checkPQcommand(db_conn, result, "BEGIN;", __FILE__, __LINE__)) exit(-1); + if (fo_checkPQcommand(db_conn, result, "BEGIN;", __FILE__, __LINE__)) + { + exit(-1); + } PQclear(result); - + memset(TempTable,'\0',sizeof(TempTable)); snprintf(TempTable,sizeof(TempTable),"DelUp_%ld",UploadId); /***********************************************/ /*** Delete everything that impacts the UI ***/ /***********************************************/ /***********************************************/ /* Delete the upload from the folder-contents table */ /* memset(SQL,'\0',sizeof(SQL)); if (Verbose) { printf("# Deleting foldercontents\n"); } snprintf(SQL,sizeof(SQL),"DELETE FROM foldercontents WHERE (foldercontents_mode & 2) != 0 AND child_id = %ld;",UploadId); result = PQexec(db_conn, SQL); if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1); PQclear(result); */ - + if (!Test) { /* The UI depends on uploadtree and folders for navigation. Delete them now to block timeouts from the UI. */ - if (Verbose) { printf("# COMMIT;\n"); } + if (Verbose) + { + printf("# COMMIT;\n"); + } result = PQexec(db_conn, "COMMIT;"); - if (fo_checkPQcommand(db_conn, result, "COMMIT;", __FILE__, __LINE__)) exit(-1); + if (fo_checkPQcommand(db_conn, result, "COMMIT;", __FILE__, __LINE__)) + { + exit(-1); + } PQclear(result); //if (Verbose) { printf("# BEGIN;\n"); } //result = PQexec(db_conn, "BEGIN;"); //if (fo_checkPQcommand(db_conn, result, "BEGIN;", __FILE__, __LINE__)) exit(-1); //PQclear(result); } /***********************************************/ /*** Begin complicated stuff ***/ /***********************************************/ /* Get the list of pfiles to delete */ /** These are all pfiles in the upload_fk that only appear once. **/ memset(SQL,'\0',sizeof(SQL)); if (Verbose) { printf("# Getting list of pfiles to delete\n"); } snprintf(SQL,sizeof(SQL),"SELECT DISTINCT pfile_pk,pfile_sha1 || '.' || pfile_md5 || '.' || pfile_size AS pfile INTO %s_pfile FROM uploadtree INNER JOIN pfile ON upload_fk = %ld AND pfile_fk = pfile_pk;",TempTable,UploadId); result = PQexec(db_conn, SQL); - if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1); + if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__)) + { + exit(-1); + } PQclear(result); /* Remove pfiles with reuse */ memset(SQL,'\0',sizeof(SQL)); snprintf(SQL,sizeof(SQL),"DELETE FROM %s_pfile USING uploadtree WHERE pfile_pk = uploadtree.pfile_fk AND uploadtree.upload_fk != %ld;",TempTable,UploadId); result = PQexec(db_conn, SQL); - if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1); + if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__)) + { + exit(-1); + } PQclear(result); memset(SQL,'\0',sizeof(SQL)); snprintf(SQL,sizeof(SQL),"SELECT COUNT(*) FROM %s_pfile;",TempTable); result = PQexec(db_conn, SQL); - if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1); + if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) + { + exit(-1); + } if (Verbose) { printf("# Created pfile table: %ld entries\n",atol(PQgetvalue(result,0,0))); } PQclear(result); /* Get the file listing -- needed for deleting pfiles from the repository. */ memset(SQL,'\0',sizeof(SQL)); snprintf(SQL,sizeof(SQL),"SELECT * FROM %s_pfile ORDER BY pfile_pk;",TempTable); pfile_result = PQexec(db_conn, SQL); - if (fo_checkPQresult(db_conn, pfile_result, SQL, __FILE__, __LINE__)) exit(-1); + if (fo_checkPQresult(db_conn, pfile_result, SQL, __FILE__, __LINE__)) + { + exit(-1); + } MaxRow = PQntuples(pfile_result); /***********************************************/ /* Now to delete the actual pfiles from the repository before remove the DB. */ if (Test <= 1) { for(Row=0; Row1 && !Test) + { + memset(SQL,'\0',sizeof(SQL)); + snprintf(SQL,sizeof(SQL),"DELETE FROM foldercontents WHERE foldercontents_mode=%d AND child_id =%ld AND parent_fk=%ld",mode,child,parent); + result = PQexec(db_conn, SQL); + if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__)) + { + exit(-1); + } + PQclear(result); + return 1; + } + return 0; +} + /** * \brief ListFoldersRecurse(): Draw folder tree. - * + * * if DelFlag is set, then all child uploads are * deleted and the folders are deleted. * * \param long Parent the parent folder id * \param int Depth * \param long Row grandparent (used to unlink if multiple grandparents) * \param int DelFlag 0=no del, 1=del if unique parent, 2=del unconditional * + * \return 1: success; 0: fail + * */ -void ListFoldersRecurse (long Parent, int Depth, long Row, int DelFlag) +int ListFoldersRecurse (long Parent, int Depth, long Row, int DelFlag, int user_id, int user_perm) { int r,MaxRow; long Fid; int i; char *Desc; PGresult *result; char SQL[MAXSQL]; + if(DelFlag && 0 >= check_permission_folder(Parent, user_id, user_perm)){ + return 0; + } + /* Find all folders with this parent and recurse */ memset(SQL,'\0',sizeof(SQL)); snprintf(SQL,sizeof(SQL),"SELECT folder_pk,foldercontents_mode,name,description,upload_pk FROM folderlist " "WHERE parent=%ld " "ORDER BY name,parent,folder_pk",Parent); result = PQexec(db_conn, SQL); - if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1); + if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) + { + exit(-1); + } MaxRow = PQntuples(result); for(r=0; r < MaxRow; r++) { if (atol(PQgetvalue(result,r,0)) == Parent) { continue; } if (!DelFlag) { for(i=0; i1 && !Test) - { - memset(SQL,'\0',sizeof(SQL)); - snprintf(SQL,sizeof(SQL),"DELETE FROM foldercontents WHERE foldercontents_mode=%d AND child_id =%ld AND parent_fk=%ld",mode,child,parent); - result = PQexec(db_conn, SQL); - if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1); - PQclear(result); - return 1; - } - return 0; -} + return 1; /* success */ +} /* ListFoldersRecurse() */ /** * \brief ListFolders(): List every folder. */ -void ListFolders (int user_id) +void ListFolders (int user_id, int user_perm) { int i,j,MaxRow; long Fid; /* folder ids */ int DetachFlag=0; int Match; char *Desc; char SQL[MAXSQL]; PGresult *result; int cnt = 0; memset(SQL,'\0',sizeof(SQL)); snprintf(SQL,sizeof(SQL),"select count(*) from users where user_pk = %d and user_perm >= 1;",user_id); result = PQexec(db_conn, SQL); - if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1); + if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) + { + exit(-1); + } cnt = atol(PQgetvalue(result,0,0)); - if(user_id != 0 && cnt == 0){ + if(user_id != 0 && cnt == 0){ LOG_FATAL("user does not have the permsssion to view the folder list.\n"); exit(-1); } printf("# Folders\n"); memset(SQL,'\0',sizeof(SQL)); snprintf(SQL,sizeof(SQL),"SELECT folder_name from folder where folder_pk =1;"); result = PQexec(db_conn, SQL); - if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1); + if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) + { + exit(-1); + } printf("%4d :: %s\n", 1, PQgetvalue(result,0,0)); PQclear(result); memset(SQL,'\0',sizeof(SQL)); snprintf(SQL,sizeof(SQL),"SELECT folder_pk,parent,name,description,upload_pk FROM folderlist ORDER BY name,parent,folder_pk;"); result = PQexec(db_conn, SQL); - if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1); - ListFoldersRecurse(1,1,-1,0); + if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) + { + exit(-1); + } + ListFoldersRecurse(1,1,-1,0,user_id,user_perm); /* Find detached folders */ MaxRow = PQntuples(result); DetachFlag=0; for(i=0; i < MaxRow; i++) { Fid = atol(PQgetvalue(result,i,1)); if (Fid == 1) continue; /* skip default parent */ Match=0; for(j=0; (j= 0) { char *S; printf("%ld :: %s",NewPid,PQgetvalue(result,Row,2)); S = PQgetvalue(result,Row,1); if (S && S[0]) printf(" (%s)",S); printf("\n"); } } PQclear(result); } /* ListUploads() */ /** * \brief DeleteFolder() * * Given a folder ID, delete it AND recursively delete everything below it! * This includes upload deletion! - * + * * \param long FolderId the fold id to delete + * + * \return 1: success; 0: fail + * **/ -void DeleteFolder (long FolderId) +int DeleteFolder (long FolderId, int user_id, int user_perm) { - ListFoldersRecurse(FolderId,0,-1,2); -#if 0 - /** Disabled: Database will take care of this **/ - MyDBaccess(DB,"VACUUM ANALYZE foldercontents;"); - MyDBaccess(DB,"VACUUM ANALYZE folder;"); -#endif + return ListFoldersRecurse(FolderId,0,-1,2,user_id,user_perm); } /* DeleteFolder() */ /**********************************************************************/ +void DoSchedulerTasks(){ + char *Parm = NULL; + char SQL[MAXSQL]; + PGresult *result; + int user_id = -1; + int user_perm = -1; + + while(fo_scheduler_next()) + { + Parm = fo_scheduler_current(); + user_id = fo_scheduler_userID(); + + /* get perm level of user */ + snprintf(SQL,sizeof(SQL),"SELECT user_perm from users where user_pk='%d';", user_id); + result = PQexec(db_conn, SQL); + if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) + { + exit(-1); + } + if (!PQntuples(result)) + { + exit(-1); + } + user_perm = atoi(PQgetvalue(result, 0, 0)); + + if (ReadParameter(Parm, user_id, user_perm) < 0) + { + exit(-1); + } + } +} + /** * \brief ReadParameter() - * + * * Read Parameter from scheduler. * Process line elements. * * \param char *Parm the parameter string - * + * * \return 0 on OK, -1 on failure. * **/ -int ReadParameter (char *Parm) +int ReadParameter (char *Parm, int user_id, int user_perm) { char FullLine[MAXLINE]; char *L; int rc=0; /* assume no data */ int Type=0; /* 0=undefined; 1=delete; 2=list */ int Target=0; /* 0=undefined; 1=upload; 2=license; 3=folder */ long Id; memset(FullLine,0,MAXLINE); if (!Parm) { return(-1); } if (Verbose > 1) fprintf(stderr,"DEBUG: Line='%s'\n",Parm); /* process the string. */ L = Parm; while(isspace(L[0])) L++; /** Get the type of command: delete or list **/ if (!strncasecmp(L,"DELETE",6) && isspace(L[6])) { Type=1; /* delete */ L+=6; } else if (!strncasecmp(L,"LIST",4) && isspace(L[4])) { Type=2; /* list */ L+=4; } while(isspace(L[0])) L++; /** Get the target **/ if (!strncasecmp(L,"UPLOAD",6) && (isspace(L[6]) || !L[6])) { Target=1; /* upload */ L+=6; } else if (!strncasecmp(L,"LICENSE",7) && (isspace(L[7]) || !L[7])) { Target=2; /* license */ L+=7; } else if (!strncasecmp(L,"FOLDER",6) && (isspace(L[6]) || !L[6])) { Target=3; /* folder */ L+=6; } while(isspace(L[0])) L++; Id = atol(L); /* Handle the request */ - if ((Type==1) && (Target==1)) { DeleteUpload(Id); rc=1; } - else if ((Type==1) && (Target==2)) { DeleteLicense(Id); rc=1; } - else if ((Type==1) && (Target==3)) { DeleteFolder(Id); rc=1; } - else if ((Type==2) && (Target==1)) { ListUploads(0, ADMIN_PERM); rc=1; } - else if ((Type==2) && (Target==2)) { ListUploads(0, ADMIN_PERM); rc=1; } - else if ((Type==2) && (Target==3)) { ListFolders(0); rc=1; } + if ((Type==1) && (Target==1)) + { + rc = DeleteUpload(Id, user_id, user_perm); + } + else if ((Type==1) && (Target==2)) + { + rc = DeleteLicense(Id, user_perm); + } + else if ((Type==1) && (Target==3)) + { + rc = DeleteFolder(Id, user_id, user_perm); + } + else if (((Type==2) && (Target==1)) || ((Type==2) && (Target==2))) + { + ListUploads(0, PERM_ADMIN); + rc = 1; + } + else if ((Type==2) && (Target==3)) + { + ListFolders(user_id, user_perm); + rc = 1; + } else { LOG_FATAL("Unknown command: '%s'\n",Parm); } return(rc); } /* ReadParameter() */ - -/** - * \brief check if the upload can be deleted, that is the user have - * the permissin to delte this upload - * - * \param long upload_id - upload id - * \param char *user_name - user name - * - * \return 1: yes, can be deleted; -1: failure; 0: can not be deleted - */ -int check_permission_del(long upload_id, int user_id, int user_perm) -{ - char SQL[MAXSQL] = {0};; - PGresult *result = NULL; - int count = 0; - - snprintf(SQL,sizeof(SQL),"SELECT count(*) FROM upload join users on (users.user_pk = upload.user_fk or users.user_perm = 10) where upload_pk = %ld and users.user_pk = %d;", upload_id, user_id); - result = PQexec(db_conn, SQL); - if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) return -1; - count = atoi(PQgetvalue(result, 0, 0)); - if (count == 0) return -2; // this upload does not exist - - /* Check Permissions */ - if (GetUploadPerm(db_conn, upload_id, user_id) < PERM_WRITE) - { - LOG_ERROR("You have no update permissions on upload %ld", upload_id); - return 0; - } - - return 1; // can be deleted -} - -/** - * \brief if this account is valid - * - * \param char *user - ussr name - * \param char *password - password - * - * \return 1: yes, valid; -1: failure; 0: invalid - */ -int authentication(char *user, char * password, int *user_id, int *user_perm) -{ - if (NULL == user || NULL == password) return 0; - char SQL[MAXSQL] = {0}; - PGresult *result; - char user_seed[myBUFSIZ] = {0}; - char pass_hash_valid[myBUFSIZ] = {0}; - unsigned char hash_value[myBUFSIZ] = {0}; - char pass_hash_actual[myBUFSIZ] = {0}; - - /** get user_seed, user_pass on one specified user */ - snprintf(SQL,sizeof(SQL),"SELECT user_seed, user_pass, user_perm, user_pk from users where user_name='%s';", user); - result = PQexec(db_conn, SQL); - if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) return -1; - if (!PQntuples(result)){ - return 0; - } - strcpy(user_seed, PQgetvalue(result, 0, 0)); - strcpy(pass_hash_valid, PQgetvalue(result, 0, 1)); - *user_perm = atoi(PQgetvalue(result, 0, 2)); - *user_id = atoi(PQgetvalue(result, 0, 3)); - PQclear(result); - if (user_seed[0] && pass_hash_valid[0]) - { - strcat(user_seed, password); // get the hash code on seed+pass - SHA1((unsigned char *)user_seed, strlen(user_seed), hash_value); - if (!hash_value[0]) - { - LOG_FATAL("ERROR, failed to get sha1 value\n"); - return -1; - } - } - else return -1; - int i = 0; - char temp[256] = {0}; - for (i = 0; i < strlen((char *)hash_value); i++) - { - sprintf(temp, "%02x", hash_value[i]); - strcat(pass_hash_actual, temp); - } - if (strcmp(pass_hash_valid, pass_hash_actual) == 0) - { - return 1; - } - else return -1; -} - -/*********************************************** - Usage(): - Command line options allow you to write the agent so it works - stand alone, in addition to working with the scheduler. - This simplifies code development and testing. - So if you have options, have a Usage(). - Here are some suggested options (in addition to the program - specific options you may already have). - ***********************************************/ -void Usage (char *Name) -{ - fprintf(stderr,"Usage: %s [options]\n",Name); - fprintf(stderr," List or delete uploads.\n"); - fprintf(stderr," Options\n"); - fprintf(stderr," -i :: Initialize the DB, then exit.\n"); - fprintf(stderr," -u :: List uploads IDs.\n"); - fprintf(stderr," -U # :: Delete upload ID.\n"); - //fprintf(stderr," -L # :: Delete ALL licenses associated with upload ID.\n"); - fprintf(stderr," -f :: List folder IDs.\n"); - fprintf(stderr," -F # :: Delete folder ID and all uploads under this folder.\n"); - fprintf(stderr," Folder '1' is the default folder. '-F 1' will delete\n"); - fprintf(stderr," every upload and folder in the navigation tree.\n"); - fprintf(stderr," -s :: Run from the scheduler.\n"); - fprintf(stderr," -T :: TEST -- do not update the DB or delete any files (just pretend)\n"); - fprintf(stderr," -v :: Verbose (-vv for more verbose)\n"); - fprintf(stderr," -c # :: Specify the directory for the system configuration\n"); - fprintf(stderr," -V :: print the version info, then exit.\n"); - fprintf(stderr," --user|-n # :: user name\n"); - fprintf(stderr," --password|-p # :: password\n"); -} /* Usage() */ diff --git a/src/www/ui/admin-folder-delete.php b/src/delagent/ui/admin-folder-delete.php similarity index 99% rename from src/www/ui/admin-folder-delete.php rename to src/delagent/ui/admin-folder-delete.php index 29338359..a13c17ef 100644 --- a/src/www/ui/admin-folder-delete.php +++ b/src/delagent/ui/admin-folder-delete.php @@ -1,135 +1,135 @@ Name = "admin_folder_delete"; $this->Title = TITLE_admin_folder_delete; $this->MenuList = "Organize::Folders::Delete Folder"; $this->Dependency = array(); $this->DBaccess = PLUGIN_DB_WRITE; parent::__construct(); $this->dbManager = $GLOBALS['container']->get('db.manager'); } /** * \brief Delete * Creates a job to detele the folder * * \param $folderpk - the folder_pk to remove * \return NULL on success, string on failure. */ function Delete($folderpk, $userId) { /* Can't remove top folder */ if ($folderpk == FolderGetTop()) { $text = _("Can Not Delete Root Folder"); return ($text); } /* Get the folder's name */ $FolderName = FolderGetName($folderpk); /* Prepare the job: job "Delete" */ $groupId = Auth::getGroupId(); $jobpk = JobAddJob($userId, $groupId, "Delete Folder: $FolderName"); if (empty($jobpk) || ($jobpk < 0)) { $text = _("Failed to create job record"); return ($text); } /* Add job: job "Delete" has jobqueue item "delagent" */ $jqargs = "DELETE FOLDER $folderpk"; $jobqueuepk = JobQueueAdd($jobpk, "delagent", $jqargs, NULL, NULL); if (empty($jobqueuepk)) { $text = _("Failed to place delete in job queue"); return ($text); } /* Tell the scheduler to check the queue. */ $success = fo_communicate_with_scheduler("database", $output, $error_msg); if (!$success) return $error_msg . "\n" . $output; return (NULL); } // Delete() /** * \brief Generate the text for this plugin. */ public function Output() { /* If this is a POST, then process the request. */ $folder = GetParm('folder', PARM_INTEGER); if (!empty($folder)) { $userId = Auth::getUserId(); - $sql = "SELECT folder_name FROM folder join users on (users.user_pk = folder.user_fk or users.user_perm = 10) where folder_pk = '$1' and users.user_pk = $2;"; + $sql = "SELECT folder_name FROM folder join users on (users.user_pk = folder.user_fk or users.user_perm = 10) where folder_pk = $1 and users.user_pk = $2;"; $Folder = $this->dbManager->getSingleRow($sql,array($folder,$userId),__METHOD__."GetRowWithFolderName"); if(!empty($Folder['folder_name'])){ $rc = $this->Delete($folder, $userId); if (empty($rc)) { /* Need to refresh the screen */ $text = _("Deletion of folder "); $text1 = _(" added to job queue"); $this->vars['message'] = $text . $Folder['folder_name'] . $text1; }else{ $text = _("Deletion of "); $text1 = _(" failed: "); $this->vars['message'] = $text . $Folder['folder_name'] . $text1 . $rc; } }else{ $text = _("Cannot delete this folder :: Permission denied"); $this->vars['message'] = $text; } } $V= "
\n"; // no url = this url $text = _("Select the folder to"); $text1 = _("delete"); $V.= "$text $text1.\n"; $V.= "
    \n"; $text = _("This will"); $text1 = _("delete"); $text2 = _("the folder, all subfolders, and all uploaded files stored within the folder!"); $V.= "
  • $text $text1 $text2\n"; $text = _("Be very careful with your selection since you can delete a lot of work!"); $V.= "
  • $text\n"; $text = _("All analysis only associated with the deleted uploads will also be deleted."); $V.= "
  • $text\n"; $text = _("THERE IS NO UNDELETE. When you select something to delete, it will be removed from the database and file repository."); $V.= "
  • $text\n"; $V.= "
\n"; $text = _("Select the folder to delete: "); $V.= "

$text\n"; $V.= "

\n"; $text = _("Delete"); $V.= "\n"; $V.= "

\n"; return $V; } } $NewPlugin = new admin_folder_delete;