diff --git a/src/delagent/agent/util.c b/src/delagent/agent/util.c index 01fbd2cf..79afd21e 100644 --- a/src/delagent/agent/util.c +++ b/src/delagent/agent/util.c @@ -1,1286 +1,1290 @@ /******************************************************** 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)){ + 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; - } + 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, 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; + 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 + 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;",folder_id,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); + } 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_perm) { if (user_perm != PERM_ADMIN) { - /* if (Verbose) { printf("only admin is allowed to delete licenses\n"); } */ + verbosePrintf("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 */ int DeleteLicense (long UploadId, int user_perm) { char TempTable[256]; char SQL[MAXSQL]; PGresult *result; long items=0; if (1 != check_permission_license(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); result = PQexec(db_conn, "BEGIN;"); 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 */ 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); } items = PQntuples(result); PQclear(result); /***********************************************/ /* delete pfile licenses */ 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); } 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); } 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); } PQclear(result); fo_scheduler_heart(items); /***********************************************/ /* Commit the change! */ verbosePrintf("# Delete completed\n"); if (Test) { result = PQexec(db_conn, "ROLLBACK;"); 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); } PQclear(result); } result = PQexec(db_conn, "SET statement_timeout = 120000;"); if (fo_checkPQcommand(db_conn, result, "SET statement_timeout = 120000;", __FILE__, __LINE__)) { exit(-1); } PQclear(result); 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 */ 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)) + int permission_upload = check_permission_upload(UploadId, user_id, user_perm); + if (permission_upload == -2) + { + return 1; + } + else if (1 != permission_upload) { 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); } PQclear(result); result = PQexec(db_conn, "BEGIN;"); 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"); } result = PQexec(db_conn, "COMMIT;"); 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); } 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); } 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 (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); } 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 * */ 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_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); } MaxRow = PQntuples(result); for(r=0; r < MaxRow; r++) { if (atol(PQgetvalue(result,r,0)) == Parent) { continue; } if (!DelFlag) { for(i=0; i= 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 * **/ int DeleteFolder(long FolderId, int user_id, int user_perm) { return ListFoldersRecurse(FolderId,0,-1,2,user_id,user_perm); } /* DeleteFolder() */ /**********************************************************************/ /** * \brief ReadAndProcessParameter() * * Read Parameter from scheduler. * Process line elements. * * \param char *Parm the parameter string * * \return 0 on OK, -1 on failure. * **/ int ReadAndProcessParameter (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)) { 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); } /* ReadAndProcessParameter() */ 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)) + if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__) || !PQntuples(result)) { exit(-1); } user_perm = atoi(PQgetvalue(result, 0, 0)); + PQclear(result); if (ReadAndProcessParameter(Parm, user_id, user_perm) < 0) { exit(-1); } } } diff --git a/src/delagent/ui/admin-upload-delete.php b/src/delagent/ui/admin-upload-delete.php index 7b735742..c7009013 100644 --- a/src/delagent/ui/admin-upload-delete.php +++ b/src/delagent/ui/admin-upload-delete.php @@ -1,173 +1,171 @@ Name = "admin_upload_delete"; $this->Title = TITLE_admin_upload_delete; $this->MenuList = "Organize::Uploads::Delete Uploaded File"; $this->DBaccess = PLUGIN_DB_WRITE; parent::__construct(); } /** * \brief Given a folder_pk, add a job. * \param $uploadpk - the upload(upload_id) you want to delete * \param $Depends - Depends is not used for now * * \return NULL on success, string on failure. */ function Delete($uploadpk, $Depends = NULL) { - global $SysConf; - /* Prepare the job: job "Delete" */ $user_pk = Auth::getUserId(); $group_pk = Auth::getGroupId(); $jobpk = JobAddJob($user_pk, $group_pk, "Delete", $uploadpk); if (empty($jobpk) || ($jobpk < 0)) { $text = _("Failed to create job record"); return ($text); } /* Add job: job "Delete" has jobqueue item "delagent" */ $jqargs = "DELETE UPLOAD $uploadpk"; $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) { $error_msg = _("Is the scheduler running? Your jobs have been added to job queue."); $URL = Traceback_uri() . "?mod=showjobs&upload=$uploadpk "; $LinkText = _("View Jobs"); $msg = "$error_msg $LinkText"; return $msg; } return (NULL); } // Delete() /** * \brief Generate the text for this plugin. */ public function Output() { $V = ""; /* If this is a POST, then process the request. */ $uploadpk = GetParm('upload', PARM_INTEGER); if (!empty($uploadpk)) { $rc = $this->Delete($uploadpk); if (empty($rc)) { /* Need to refresh the screen */ $URL = Traceback_uri() . "?mod=showjobs&upload=$uploadpk "; $LinkText = _("View Jobs"); $text=_("Deletion added to job queue."); $msg = "$text $LinkText"; $V.= displayMessage($msg); } else { $text=_("Deletion Scheduling failed: "); $V.= DisplayMessage($text.$rc); } } /* Create the AJAX (Active HTTP) javascript for doing the reply and showing the response. */ $V.= ActiveHTTPscript("Uploads"); $V.= "\n"; /* Build HTML form */ $V.= "
\n"; // no url = this url $text = _("Select the uploaded file to"); $text1 = _("delete"); $V.= "$text $text1\n"; $V.= "
    \n"; $text = _("This will"); $text1 = _("delete"); $text2 = _("the upload file!"); $V.= "
  • $text $text1 $text2\n"; $text = _("Be very careful with your selection since you can delete a lot of work!\n"); $V.= "
  • $text"; $text = _("All analysis only associated with the deleted upload file will also be deleted.\n"); $V.= "
  • $text"; $text = _("THERE IS NO UNDELETE. When you select something to delete, it will be removed from the database and file repository.\n"); $V.= "
  • $text"; $V.= "
\n"; $text = _("Select the uploaded file to delete:"); $V.= "

$text

\n"; $V.= "

    \n"; $text = _("Select the folder containing the file to delete: "); $V.= "
  1. $text"; $V.= "

    \n"; $text = _("Select the uploaded project to delete:"); $V.= "

  2. $text"; $V.= "
    \n"; $V.= "

    \n"; $V.= "

    \n"; $V.= "
\n"; $text = _("Delete"); $V.= "\n"; $V.= "
\n"; return $V; } } $NewPlugin = new admin_upload_delete;