diff --git a/src/delagent/agent/delagent.c b/src/delagent/agent/delagent.c index b74ab809..2053b201 100644 --- a/src/delagent/agent/delagent.c +++ b/src/delagent/agent/delagent.c @@ -1,263 +1,263 @@ /******************************************************** delagent: Remove an upload from the DB and repository Copyright (C) 2007-2013 Hewlett-Packard Development Company, L.P. Copyright (C) 2015-2016 Siemens AG 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(): + 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(). + 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) +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() */ +} /* 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 if (2 == returnedCode) { fprintf(stdout, "The %s '%ld' could not be found by the user '%s'.\n", kind, id, user_name); } else { fprintf(stdout, "Deletion failed: user '%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(-1); } } /** * \brief main function for the delagent * * There are 2 ways to use the delagent agent: * 1. Command Line :: delete/list upload/folder/license 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; + 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 *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); 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': user_name = optarg; break; case 'p': password = optarg; break; case 'i': PQfinish(db_conn); return(0); case 'f': - ListFolder=1; - GotArg=1; + listFolder=1; + gotArg=1; break; case 'F': - DelFolder=atol(optarg); - GotArg=1; + delFolder=atol(optarg); + gotArg=1; break; case 'L': - DelLicense=atol(optarg); - GotArg=1; + delLicense=atol(optarg); + gotArg=1; break; case 's': - Scheduler=1; - GotArg=1; + scheduler=1; + gotArg=1; break; case 'T': Test++; break; case 'u': - ListProj=1; - GotArg=1; + listProj=1; + gotArg=1; break; case 'U': - DelUpload=atol(optarg); - GotArg=1; + delUpload=atol(optarg); + gotArg=1; break; case 'v': Verbose++; break; case 'c': - GotArg=1; + gotArg=1; break; /* handled by fo_scheduler_connect() */ case 'V': printf("%s", BuildVersion); PQfinish(db_conn); return(0); default: - Usage(argv[0]); + usage(argv[0]); exit(-1); } } - if (!GotArg) + if (!gotArg) { - Usage(argv[0]); + usage(argv[0]); exit(-1); } - if (Scheduler != 1) + if (scheduler != 1) { if (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) + if (listProj) { - ListUploads(user_id, user_perm); + listUploads(user_id, user_perm); } - if (ListFolder) + if (listFolder) { - ListFolders(user_id, user_perm); + listFolders(user_id, user_perm); } alarm(60); /* from this point on, handle the alarm */ - if (DelUpload) + if (delUpload) { - returnedCode = DeleteUpload(DelUpload, user_id, user_perm); + returnedCode = deleteUpload(delUpload, user_id, user_perm); - writeMessageAfterDelete("upload", DelUpload, user_name, returnedCode); + writeMessageAfterDelete("upload", delUpload, user_name, returnedCode); } - if (DelFolder) + if (delFolder) { - returnedCode = DeleteFolder(DelFolder, user_id, user_perm); + returnedCode = deleteFolder(delFolder, user_id, user_perm); - writeMessageAfterDelete("folder", DelFolder, user_name, returnedCode); + writeMessageAfterDelete("folder", delFolder, user_name, returnedCode); } - if (DelLicense) + if (delLicense) { - returnedCode = DeleteLicense(DelLicense, user_perm); + returnedCode = deleteLicense(delLicense, user_perm); - writeMessageAfterDelete("license", DelLicense, user_name, returnedCode); + writeMessageAfterDelete("license", delLicense, user_name, returnedCode); } } else { /* process from the scheduler */ - DoSchedulerTasks(); + doSchedulerTasks(); } 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 f1cb83df..99479b35 100644 --- a/src/delagent/agent/delagent.h +++ b/src/delagent/agent/delagent.h @@ -1,71 +1,71 @@ /******************************************************** Copyright (C) 2007-2012 Hewlett-Packard Development Company, L.P. Copyright (C) 2015-2016 Siemens AG 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 /* authentication and permission checking */ int authentication(char *user, char * password, int *user_id, int *user_perm); int check_permission_upload(int wantedPermissions, long upload_id, int user_id, int user_perm); int check_read_permission_upload(long upload_id, int user_id, int user_perm); int check_write_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_perm); /* functions that list things */ -void ListFolders(int user_id, int user_perm); -void ListUploads(int user_id, int user_perm); +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); +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(); +void doSchedulerTasks(); /* misc */ -void Usage(char *Name); +void usage(char *Name); #endif /* _DELAGENT_H */ diff --git a/src/delagent/agent/util.c b/src/delagent/agent/util.c index b51581a6..d95b268b 100644 --- a/src/delagent/agent/util.c +++ b/src/delagent/agent/util.c @@ -1,981 +1,981 @@ /******************************************************** Copyright (C) 2007-2013 Hewlett-Packard Development Company, L.P. Copyright (C) 2015-2016 Siemens AG 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, ...) +int printfInCaseOfVerbosity (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 PQexecCheck() * * simple wrapper which includes PQexec and fo_checkPQcommand * */ PGresult * PQexecCheck(const char *desc, char *SQL, char *file, const int line) { PGresult *result; if(desc == NULL) { - verbosePrintf("# %s:%i: %s\n", file, line, SQL); + printfInCaseOfVerbosity("# %s:%i: %s\n", file, line, SQL); } else { - verbosePrintf("# %s:%i: %s (%s)\n", file, line, desc, SQL); + printfInCaseOfVerbosity("# %s:%i: %s (%s)\n", file, line, desc, SQL); } result = PQexec(db_conn, SQL); if (fo_checkPQcommand(db_conn, result, SQL, file, line)) { exit(-1); } return result; } void PQexecCheckClear(const char *desc, char *SQL, char *file, const int line) { PGresult *result; result = PQexecCheck(desc, SQL, file, line); PQclear(result); } /** * \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; * 0: invalid; * -1: failure */ 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[41] = {0}; unsigned char pass_hash_actual_raw[21] = {0}; char pass_hash_actual[41] = {0}; /** get user_seed, user_pass on one specified user */ snprintf(SQL,MAXSQL,"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), pass_hash_actual_raw); } else { return -1; } int i = 0; char temp[256] = {0}; for (i = 0; i < 20; i++) { snprintf(temp, 256, "%02x", pass_hash_actual_raw[i]); strcat(pass_hash_actual, temp); } return strcmp(pass_hash_valid, pass_hash_actual) == 0; } /** * \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, you have the needed permissions; * 0: no; * -1: failure; * -2: does not exist */ int check_permission_upload(int wanted_permissions, long upload_id, int user_id, int user_perm) { - int perms = GetUploadPermP(db_conn, upload_id, user_id, user_perm); + int perms = getEffectivePermissionOnUpload(db_conn, upload_id, user_id, user_perm); if (perms > 0) { if (perms < wanted_permissions) { return 0; } else { return 1; } } return perms; } int check_read_permission_upload(long upload_id, int user_id, int user_perm) { return check_permission_upload(PERM_READ, upload_id, user_id, user_perm); } int check_write_permission_upload(long upload_id, int user_id, int user_perm) { return check_permission_upload(PERM_WRITE, upload_id, user_id, user_perm); } /** * \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; */ int check_write_permission_folder(long folder_id, int user_id, int user_perm) { char SQL[MAXSQL]; PGresult *result; int count = 0; if (user_perm < PERM_WRITE) { return 0; // can not be deleted } snprintf(SQL,MAXSQL,"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;",folder_id,user_id); result = PQexec(db_conn, SQL); if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) { return -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; */ int check_write_permission_license(long license_id, int user_perm) { if (user_perm != PERM_ADMIN) { - verbosePrintf("only admin is allowed to delete licenses\n"); + printfInCaseOfVerbosity("only admin is allowed to delete licenses\n"); return 0; // can not be deleted } return 1; // can be deleted } /** - * \brief DeleteLicense() + * \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: yes, success; * 0: can not be deleted; * -1: failure; * -2: does not exist */ -int DeleteLicense (long UploadId, int user_perm) +int deleteLicense (long UploadId, int user_perm) { char SQL[MAXSQL]; PGresult *result; long items=0; int permission_license = check_write_permission_license(UploadId, user_perm); if (1 != permission_license) { return permission_license; } - verbosePrintf("Deleting licenses for upload %ld\n",UploadId); + printfInCaseOfVerbosity("Deleting licenses for upload %ld\n",UploadId); PQexecCheckClear(NULL, "SET statement_timeout = 0;", __FILE__, __LINE__); PQexecCheckClear(NULL, "BEGIN;", __FILE__, __LINE__); /* Get the list of pfiles to process */ snprintf(SQL,MAXSQL,"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); } items = PQntuples(result); PQclear(result); /***********************************************/ /* delete pfile licenses */ - verbosePrintf("# Deleting licenses\n"); + printfInCaseOfVerbosity("# Deleting licenses\n"); snprintf(SQL,MAXSQL,"DELETE FROM licterm_name WHERE pfile_fk IN (SELECT pfile_fk FROM uploadtree WHERE upload_fk = '%ld');",UploadId); PQexecCheckClear(NULL, SQL, __FILE__, __LINE__); snprintf(SQL,MAXSQL,"DELETE FROM agent_lic_status WHERE pfile_fk IN (SELECT pfile_fk FROM uploadtree WHERE upload_fk = '%ld');",UploadId); PQexecCheckClear(NULL, SQL, __FILE__, __LINE__); snprintf(SQL,MAXSQL,"DELETE FROM agent_lic_meta WHERE pfile_fk IN (SELECT pfile_fk FROM uploadtree WHERE upload_fk = '%ld');",UploadId); PQexecCheckClear(NULL, SQL, __FILE__, __LINE__); fo_scheduler_heart(items); /***********************************************/ /* Commit the change! */ - verbosePrintf("# Delete completed\n"); + printfInCaseOfVerbosity("# Delete completed\n"); if (Test) { PQexecCheckClear(NULL, "ROLLBACK;", __FILE__, __LINE__); } else { PQexecCheckClear(NULL, "COMMIT;", __FILE__, __LINE__); } PQexecCheckClear(NULL, "SET statement_timeout = 120000;", __FILE__, __LINE__); - verbosePrintf("Deleted licenses for upload %ld\n",UploadId); + printfInCaseOfVerbosity("Deleted licenses for upload %ld\n",UploadId); return 1; /* success */ -} /* DeleteLicense() */ +} /* deleteLicense() */ /** - * \brief DeleteUpload() + * \brief deleteUpload() * * Given an upload ID, delete it. * * param long UploadId the upload id * * \return 1: yes, can is deleted; * 0: can not be deleted; * -1: failure; * -2: does not exist */ -int DeleteUpload (long UploadId, int user_id, int user_perm) +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], desc[myBUFSIZ]; int permission_upload = check_write_permission_upload(UploadId, user_id, user_perm); if(1 != permission_upload) { return permission_upload; } snprintf(TempTable,sizeof(TempTable),"DelUp_%ld_pfile",UploadId); snprintf(SQL,MAXSQL,"DROP TABLE IF EXISTS %s;",TempTable); PQexecCheckClear(NULL, SQL, __FILE__, __LINE__); snprintf(desc, myBUFSIZ, "Deleting upload %ld",UploadId); PQexecCheckClear(desc, "SET statement_timeout = 0;", __FILE__, __LINE__); PQexecCheckClear(NULL, "BEGIN;", __FILE__, __LINE__); /***********************************************/ /*** Delete everything that impacts the UI ***/ /***********************************************/ if (!Test) { /* The UI depends on uploadtree and folders for navigation. Delete them now to block timeouts from the UI. */ PQexecCheckClear(NULL, "COMMIT;", __FILE__, __LINE__); } /***********************************************/ /*** Begin complicated stuff ***/ /***********************************************/ /* Get the list of pfiles to delete */ /** These are all pfiles in the upload_fk that only appear once. **/ snprintf(SQL,MAXSQL,"SELECT DISTINCT pfile_pk,pfile_sha1 || '.' || pfile_md5 || '.' || pfile_size AS pfile INTO %s FROM uploadtree INNER JOIN pfile ON upload_fk = %ld AND pfile_fk = pfile_pk;",TempTable,UploadId); PQexecCheckClear("Getting list of pfiles to delete", SQL, __FILE__, __LINE__); /* Remove pfiles with reuse */ snprintf(SQL,MAXSQL,"DELETE FROM %s USING uploadtree WHERE pfile_pk = uploadtree.pfile_fk AND uploadtree.upload_fk != %ld;",TempTable,UploadId); PQexecCheckClear(NULL, SQL, __FILE__, __LINE__); if (Verbose) { snprintf(SQL,MAXSQL,"SELECT COUNT(*) FROM %s;",TempTable); result = PQexec(db_conn, SQL); if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) { exit(-1); } printf("# Created pfile table %s with %ld entries\n", TempTable, atol(PQgetvalue(result,0,0))); PQclear(result); } /***********************************************/ /* Now to delete the actual pfiles from the repository before remove the DB. */ /* Get the file listing -- needed for deleting pfiles from the repository. */ snprintf(SQL,MAXSQL,"SELECT * FROM %s ORDER BY pfile_pk;",TempTable); pfile_result = PQexec(db_conn, SQL); if (fo_checkPQresult(db_conn, pfile_result, SQL, __FILE__, __LINE__)) { exit(-1); } if (Test <= 1) { MaxRow = PQntuples(pfile_result); for(Row=0; Row1 && !Test) { snprintf(SQL,MAXSQL,"DELETE FROM foldercontents WHERE foldercontents_mode=%d AND child_id =%ld AND parent_fk=%ld",mode,child,parent); PQexecCheckClear(NULL, SQL, __FILE__, __LINE__); return 1; } return 0; } /** - * \brief ListFoldersRecurse(): Draw folder tree. + * \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 * */ -int ListFoldersRecurse (long Parent, int Depth, long Row, int DelFlag, int user_id, int user_perm) +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]; int rc; if(DelFlag && 0 >= check_write_permission_folder(Parent, user_id, user_perm)){ return 0; } /* Find all folders with this parent and recurse */ snprintf(SQL,MAXSQL,"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); } MaxRow = PQntuples(result); for(r=0; r < MaxRow; r++) { if (atol(PQgetvalue(result,r,0)) == Parent) { continue; } Fid = atol(PQgetvalue(result,r,0)); if (Fid != 0) { if (!DelFlag) { for(i=0; i= 0 && (user_perm == PERM_ADMIN || check_read_permission_upload(NewPid, user_id, user_perm))) { 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() */ +} /* listUploads() */ /** - * \brief DeleteFolder() + * \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 * **/ -int DeleteFolder(long FolderId, int user_id, int user_perm) +int deleteFolder(long FolderId, int user_id, int user_perm) { - return ListFoldersRecurse(FolderId,0,-1,2,user_id,user_perm); -} /* DeleteFolder() */ + return listFoldersRecurse(FolderId,0,-1,2,user_id,user_perm); +} /* deleteFolder() */ /**********************************************************************/ /** - * \brief ReadAndProcessParameter() + * \brief readAndProcessParameter() * * Read Parameter from scheduler. * Process line elements. * * \param char *Parm the parameter string * * \return 1: yes, can is deleted; * 0: can not be deleted; * -1: failure; * -2: does not exist * **/ -int ReadAndProcessParameter (char *Parm, int user_id, int user_perm) +int readAndProcessParameter (char *Parm, int user_id, int user_perm) { 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; 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)) { - rc = DeleteUpload(Id, user_id, user_perm); + rc = deleteUpload(Id, user_id, user_perm); } else if ((Type==1) && (Target==2)) { - rc = DeleteLicense(Id, user_perm); + rc = deleteLicense(Id, user_perm); } else if ((Type==1) && (Target==3)) { - rc = DeleteFolder(Id, user_id, user_perm); + rc = deleteFolder(Id, user_id, user_perm); } else if (((Type==2) && (Target==1)) || ((Type==2) && (Target==2))) { - ListUploads(0, PERM_ADMIN); + listUploads(0, PERM_ADMIN); rc = 1; } else if ((Type==2) && (Target==3)) { - ListFolders(user_id, user_perm); + listFolders(user_id, user_perm); rc = 1; } else { LOG_ERROR("Unknown command: '%s'\n",Parm); } return(rc); -} /* ReadAndProcessParameter() */ +} /* readAndProcessParameter() */ -void DoSchedulerTasks() +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,MAXSQL,"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__) || !PQntuples(result)) { exit(0); } user_perm = atoi(PQgetvalue(result, 0, 0)); PQclear(result); - int returnCode = ReadAndProcessParameter(Parm, user_id, user_perm); + int returnCode = readAndProcessParameter(Parm, user_id, user_perm); if (returnCode <= 0) { /* Loglevel is to high, but scheduler expects FATAL log message before exit */ LOG_FATAL("Due to permission problems, the delagent was not able to delete the requested objects or the object did not exist."); exit(returnCode); } } } diff --git a/src/lib/c/libfossagent.c b/src/lib/c/libfossagent.c index b3aea81c..8eb47e99 100644 --- a/src/lib/c/libfossagent.c +++ b/src/lib/c/libfossagent.c @@ -1,387 +1,387 @@ /*************************************************************** libfossagent: Set of generic functions handy for agent development. Copyright (C) 2009-2013 Hewlett-Packard Development Company, L.P. Copyright (C) 2015 Siemens AG 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 libfossagent.c * \brief libfossagent.c contains general use functions for agents. */ #include "libfossology.h" #define FUNCTION char* getUploadTreeTableName(fo_dbManager* dbManager, int uploadId) { char* result; PGresult* resTableName = fo_dbManager_ExecPrepared( fo_dbManager_PrepareStamement( dbManager, "getUploadTreeTableName", "SELECT uploadtree_tablename from upload where upload_pk=$1 limit 1", int), uploadId ); if (!resTableName) { result = g_strdup("uploadtree"); return result; } if (PQntuples(resTableName) == 0) { PQclear(resTableName); result = g_strdup("uploadtree"); return result; } result = g_strdup(PQgetvalue(resTableName, 0, 0)); PQclear(resTableName); return result; } PGresult* queryFileIdsForUpload(fo_dbManager* dbManager, int uploadId) { PGresult* result; char* uploadtreeTableName = getUploadTreeTableName(dbManager, uploadId); if (strcmp(uploadtreeTableName, "uploadtree_a") == 0) { char* queryName = g_strdup_printf("queryFileIdsForUpload.%s", uploadtreeTableName); char* sql; sql = g_strdup_printf("select distinct(pfile_fk) from %s where upload_fk=$1 and (ufile_mode&x'3C000000'::int)=0", uploadtreeTableName); result = fo_dbManager_ExecPrepared( fo_dbManager_PrepareStamement( dbManager, queryName, sql, int), uploadId ); g_free(sql); g_free(queryName); } else { result = fo_dbManager_Exec_printf(dbManager, "select distinct(pfile_fk) from %s where (ufile_mode&x'3C000000'::int)=0", uploadtreeTableName ); } g_free(uploadtreeTableName); return result; } char* queryPFileForFileId(fo_dbManager* dbManager, long fileId) { PGresult* fileNameResult = fo_dbManager_ExecPrepared( fo_dbManager_PrepareStamement( dbManager, "queryPFileForFileId", "select pfile_sha1 || '.' || pfile_md5 ||'.'|| pfile_size AS pfilename from pfile where pfile_pk=$1", long), fileId ); if (PQntuples(fileNameResult) == 0) { PQclear(fileNameResult); return NULL; } char* pFile = g_strdup(PQgetvalue(fileNameResult, 0, 0)); PQclear(fileNameResult); return pFile; } /*! \brief Get the latest enabled agent key (agent_pk) from the database. \param pgConn Database connection object pointer. \param agent_name Name of agent to look up. \param Upload_pk is no longer used. \param rev agent revision, if given this is the exact revision of the agent being requested. \param agent_desc Description of the agent. Used to write a new agent record in the case where no enabled agent records exist for this agent_name. \return On success return agent_pk. On sql failure, return 0, and the error will be written to stdout. \todo This function is not checking if the agent is enabled. And it is not setting agent version when an agent record is inserted. */ FUNCTION int fo_GetAgentKey(PGconn* pgConn, const char* agent_name, long Upload_pk, const char* rev, const char* agent_desc) { int Agent_pk = -1; /* agent identifier */ char sql[256]; char sqlselect[256]; char sqlupdate[256]; PGresult* result; /* get the exact agent rec requested */ sprintf(sqlselect, "SELECT agent_pk,agent_desc FROM agent WHERE agent_name ='%s' order by agent_ts desc limit 1", agent_name); result = PQexec(pgConn, sqlselect); if (fo_checkPQresult(pgConn, result, sqlselect, __FILE__, __LINE__)) return 0; if (PQntuples(result) == 0) { PQclear(result); /* no match, so add an agent rec */ sprintf(sql, "INSERT INTO agent (agent_name,agent_desc,agent_enabled,agent_rev) VALUES ('%s',E'%s','%d', '%s')", agent_name, agent_desc, 1, rev); result = PQexec(pgConn, sql); if (fo_checkPQcommand(pgConn, result, sqlselect, __FILE__, __LINE__)) return 0; result = PQexec(pgConn, sqlselect); if (fo_checkPQresult(pgConn, result, sqlselect, __FILE__, __LINE__)) return 0; } Agent_pk = atol(PQgetvalue(result, 0, 0)); /* Compare agent_desc */ if(!(strcmp(PQgetvalue(result, 0, 1),agent_desc) == 0)){ PQclear(result); sprintf(sqlupdate, "UPDATE agent SET agent_desc = E'%s' where agent_pk = '%d'",agent_desc, Agent_pk); result = PQexec(pgConn, sqlupdate); } PQclear(result); return Agent_pk; } /* fo_GetAgentKey() */ /** \brief Write ars record If the ars table does not exist, one is created by inheriting the ars_master table. The new table is called {tableName}. For example, "unpack_ars". If ars_pk is zero a new ars record will be created. Otherwise, it is updated. \param pgConn Database connection object pointer. \param ars_pk If zero, a new record will be created. \param upload_pk \parm agent_pk Agents should get this from fo_GetAgentKey() \param tableName ars table name \parm ars_status Status to update ars_status. May be null. \parm ars_success Automatically set to false if ars_pk is zero. \return On success write the ars record and return the ars_pk. On sql failure, return 0, and the error will be written to stdout. */ FUNCTION int fo_WriteARS(PGconn* pgConn, int ars_pk, int upload_pk, int agent_pk, const char* tableName, const char* ars_status, int ars_success) { char sql[1024]; PGresult* result; /* does ars table exist? If not, create it. */ if (!fo_CreateARSTable(pgConn, tableName)) return (0); /* If ars_pk is null, * write the ars_status=false record * and return the ars_pk. */ if (!ars_pk) { snprintf(sql, sizeof(sql), "insert into %s (agent_fk, upload_fk) values(%d,%d)", tableName, agent_pk, upload_pk); result = PQexec(pgConn, sql); if (fo_checkPQcommand(pgConn, result, sql, __FILE__, __LINE__)) return 0; /* get primary key */ snprintf(sql, sizeof(sql), "SELECT currval('nomos_ars_ars_pk_seq')"); result = PQexec(pgConn, sql); if (fo_checkPQresult(pgConn, result, sql, __FILE__, __LINE__)) return (0); ars_pk = atoi(PQgetvalue(result, 0, 0)); PQclear(result); } else { /* If ars_pk is not null, update success, status and endtime */ if (ars_status) { snprintf(sql, sizeof(sql), "update %s set ars_success=%s, ars_status='%s',ars_endtime=now() where ars_pk = %d", tableName, ars_success ? "True" : "False", ars_status, ars_pk); } else { snprintf(sql, sizeof(sql), "update %s set ars_success=%s, ars_endtime=now() where ars_pk = %d", tableName, ars_success ? "True" : "False", ars_pk); } result = PQexec(pgConn, sql); if (fo_checkPQcommand(pgConn, result, sql, __FILE__, __LINE__)) return 0; } return (ars_pk); } /* fo_WriteARS() */ /** \brief Create ars table if it doesn't already exist. \param pgConn Database connection object pointer. \param tableName ars table name \return 0 on failure */ FUNCTION int fo_CreateARSTable(PGconn* pgConn, const char* tableName) { char sql[1024]; PGresult* result; if (fo_tableExists(pgConn, tableName)) return 1; // table already exists snprintf(sql, sizeof(sql), "create table %s() inherits(ars_master);\ ALTER TABLE ONLY %s ADD CONSTRAINT %s_agent_fk_fkc FOREIGN KEY (agent_fk) REFERENCES agent(agent_pk);\ ALTER TABLE ONLY %s ADD CONSTRAINT %s_upload_fk_fkc FOREIGN KEY (upload_fk) REFERENCES upload(upload_pk) ON DELETE CASCADE;", tableName, tableName, tableName, tableName, tableName); /* ALTER TABLE ONLY %s ADD CONSTRAINT %s_pkey1 PRIMARY KEY (ars_pk); \ */ result = PQexec(pgConn, sql); if (fo_checkPQcommand(pgConn, result, sql, __FILE__, __LINE__)) return 0; return 1; /* success */ } /* fo_CreateARSTable() */ FUNCTION int max(int permGroup, int permPublic) { return ( permGroup > permPublic ) ? permGroup : permPublic; } FUNCTION int min(int user_perm, int permExternal) { return ( user_perm < permExternal ) ? user_perm: permExternal; } /** * \brief Get users permission to this upload * * \param pgConn Database connection object pointer. * \param long upload_pk * \param user_pk * \param user_perm * * \return permission (PERM_) this user has for UploadPk */ -FUNCTION int GetUploadPermP(PGconn* pgConn, long UploadPk, int user_pk, int user_perm) +FUNCTION int getEffectivePermissionOnUpload(PGconn* pgConn, long UploadPk, int user_pk, int user_perm) { PGresult* result; char SQL[1024]; int permGroup=0, permPublic=0; /* Get the user permission level for this upload */ snprintf(SQL, sizeof(SQL), "select max(perm) as perm \ from perm_upload, group_user_member \ where perm_upload.upload_fk=%ld \ and user_fk=%d \ and group_user_member.group_fk=perm_upload.group_fk", UploadPk, user_pk); result = PQexec(pgConn, SQL); if (!fo_checkPQresult(pgConn, result, SQL, __FILE__, __LINE__) && PQntuples(result) > 0) { permGroup = atoi(PQgetvalue(result, 0, 0)); } PQclear(result); /* Get the public permission level */ snprintf(SQL, sizeof(SQL), "select public_perm \ from upload \ where upload_pk=%ld", UploadPk); result = PQexec(pgConn, SQL); fo_checkPQresult(pgConn, result, SQL, __FILE__, __LINE__); if (!fo_checkPQresult(pgConn, result, SQL, __FILE__, __LINE__) && PQntuples(result) > 0) { permPublic = atoi(PQgetvalue(result, 0, 0)); } PQclear(result); return min(user_perm, max(permGroup, permPublic)); } /** * \brief Get users permission to this upload * * \param pgConn Database connection object pointer. * \param long upload_pk * \param user_pk * * \return permission (PERM_) this user has for UploadPk */ FUNCTION int GetUploadPerm(PGconn* pgConn, long UploadPk, int user_pk) { PGresult* result; char SQL[1024]; int user_perm; /* Check the users PLUGIN_DB level. PLUGIN_DB_ADMIN are superusers. */ snprintf(SQL, sizeof(SQL), "select user_perm from users where user_pk='%d'", user_pk); result = PQexec(pgConn, SQL); fo_checkPQresult(pgConn, result, SQL, __FILE__, __LINE__); if (PQntuples(result) < 1) { LOG_ERROR("No records returned in %s", SQL); return PERM_NONE; } user_perm = atoi(PQgetvalue(result, 0, 0)); PQclear(result); if (user_perm >= PLUGIN_DB_ADMIN) { return PERM_ADMIN; } - return GetUploadPermP(pgConn, UploadPk, user_pk, user_perm); + return getEffectivePermissionOnUpload(pgConn, UploadPk, user_pk, user_perm); } /** * \brief Get the uploadtree table name for this upload_pk * If upload_pk does not exist, return "uploadtree". * * \param pgConn Database connection object pointer. * \param upload_pk * * \return uploadtree table name, or null if upload_pk does not exist. * Caller must free the (non-null) returned value. */ FUNCTION char* GetUploadtreeTableName(PGconn* pgConn, int upload_pk) { PGresult* result; char* uploadtree_tablename = 0; char SQL[1024]; /* Get the uploadtree table name from the upload table */ snprintf(SQL, sizeof(SQL), "select uploadtree_tablename from upload where upload_pk='%d'", upload_pk); result = PQexec(pgConn, SQL); fo_checkPQresult(pgConn, result, SQL, __FILE__, __LINE__); if (PQntuples(result) == 1) uploadtree_tablename = g_strdup(PQgetvalue(result, 0, 0)); PQclear(result); return (uploadtree_tablename); } diff --git a/src/lib/c/libfossagent.h b/src/lib/c/libfossagent.h index 8293ccdc..ac882ed6 100644 --- a/src/lib/c/libfossagent.h +++ b/src/lib/c/libfossagent.h @@ -1,38 +1,38 @@ /************************************************************** Copyright (C) 20011 Hewlett-Packard Development Company, L.P. Copyright (C) 2015 Siemens AG This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 2.1 as published by the Free Software Foundation. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc.0 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA **************************************************************/ #ifndef LIBFOSSAGENT_H #define LIBFOSSAGENT_H #include #include #include #include "libfossdbmanager.h" char* getUploadTreeTableName(fo_dbManager* dbManager, int uploadId); PGresult* queryFileIdsForUpload(fo_dbManager* dbManager, int uploadId); char* queryPFileForFileId(fo_dbManager* dbManager, long int fileId); int fo_GetAgentKey(PGconn* pgConn, const char* agent_name, long unused, const char* cpunused, const char* agent_desc); int fo_WriteARS(PGconn* pgConn, int ars_pk, int upload_pk, int agent_pk, const char* tableName, const char* ars_status, int ars_success); int fo_CreateARSTable(PGconn* pgConn, const char* table_name); -int GetUploadPermP(PGconn* pgConn, long UploadPk, int user_pk, int user_perm); +int getEffectivePermissionOnUpload(PGconn* pgConn, long UploadPk, int user_pk, int user_perm); int GetUploadPerm(PGconn* pgConn, long UploadPk, int user_pk); char* GetUploadtreeTableName(PGconn* pgConn, int upload_pk); #endif