FOSSology  4.4.0
Open Source License Compliance by Open Source Software
util.c
Go to the documentation of this file.
1 /*
2  SPDX-FileCopyrightText: © 2007-2013 Hewlett-Packard Development Company, L.P.
3  SPDX-FileCopyrightText: © 2015-2019 Siemens AG
4 
5  SPDX-License-Identifier: GPL-2.0-only
6 */
15 #include <crypt.h>
16 
17 #include "delagent.h"
18 
19 int Verbose = 0;
20 int Test = 0;
21 int Scheduler = 0;
22 PGconn* pgConn = NULL; // the connection to Database
23 
30 int printfInCaseOfVerbosity (const char *format, ...)
31 {
32  va_list arg;
33  int done = 0;
34 
35  if (Verbose)
36  {
37  va_start (arg, format);
38  done = vprintf(format, arg);
39  va_end (arg);
40  }
41  return done;
42 }
43 
54 PGresult * PQexecCheck(const char *desc, char *SQL, char *file, const int line)
55 {
56  PGresult *result;
57 
58  if(desc == NULL)
59  {
60  printfInCaseOfVerbosity("# %s:%i: %s\n", file, line, SQL);
61  }
62  else
63  {
64  printfInCaseOfVerbosity("# %s:%i: %s (%s)\n", file, line, desc, SQL);
65  }
66 
67  result = PQexec(pgConn, SQL);
68  if (fo_checkPQcommand(pgConn, result, SQL, file, line))
69  {
70  exitNow(-1);
71  }
72  return result;
73 }
74 
85 PGresult * PQexecCheckResult(const char *desc, char *SQL, char *file, const int line)
86 {
87  PGresult *result;
88 
89  if(desc == NULL)
90  {
91  printfInCaseOfVerbosity("# %s:%i: %s\n", file, line, SQL);
92  }
93  else
94  {
95  printfInCaseOfVerbosity("# %s:%i: %s (%s)\n", file, line, desc, SQL);
96  }
97 
98  result = PQexec(pgConn, SQL);
99  if (fo_checkPQresult(pgConn, result, SQL, file, line))
100  {
101  exitNow(-1);
102  }
103  return result;
104 }
105 
110 void PQexecCheckClear(const char *desc, char *SQL, char *file, const int line)
111 {
112  PGresult *result;
113  result = PQexecCheck(desc, SQL, file, line);
114  PQclear(result);
115 }
116 
129 int authentication(char *user, char *password, int *userId, int *userPerm)
130 {
131  if (NULL == user || NULL == password)
132  {
133  return 1;
134  }
135  char SQL[MAXSQL] = {0};
136  PGresult *result;
137  char user_seed[myBUFSIZ] = {0};
138  char pass_hash_valid[myBUFSIZ] = {0};
139  unsigned char pass_hash_actual_raw[21] = {0};
140  char pass_hash_actual[41] = {0};
141 
143  snprintf(SQL,MAXSQL,"SELECT user_seed, user_pass, user_perm, user_pk from users where user_name=$1;");
144  const char *values[1] = {user};
145  int lengths[1] = {strlen(user)};
146  int binary[1] = {0};
147  result = PQexecParams(pgConn, SQL, 1, NULL, values, lengths, binary, 0);
148  if (fo_checkPQresult(pgConn, result, SQL, __FILE__, __LINE__))
149  {
150  return -1;
151  }
152  if (!PQntuples(result))
153  {
154  return 1;
155  }
156  strcpy(user_seed, PQgetvalue(result, 0, 0));
157  strcpy(pass_hash_valid, PQgetvalue(result, 0, 1));
158  *userPerm = atoi(PQgetvalue(result, 0, 2));
159  *userId = atoi(PQgetvalue(result, 0, 3));
160  PQclear(result);
161  if (pass_hash_valid[0] &&
162  strcmp(crypt(password, pass_hash_valid), pass_hash_valid) == 0)
163  {
164  return 0;
165  }
166  if (user_seed[0] && pass_hash_valid[0])
167  {
168  strcat(user_seed, password); // get the hash code on seed+pass
169  gcry_md_hash_buffer(GCRY_MD_SHA1, pass_hash_actual_raw, user_seed,
170  strlen(user_seed));
171  }
172  else
173  {
174  return -1;
175  }
176  int i = 0;
177  char temp[256] = {0};
178  for (i = 0; i < 20; i++)
179  {
180  snprintf(temp, 256, "%02x", pass_hash_actual_raw[i]);
181  strcat(pass_hash_actual, temp);
182  }
183  return (strcmp(pass_hash_valid, pass_hash_actual) == 0) ? 0 : 1;
184 }
185 
198 int check_permission_upload(int wanted_permissions, long uploadId, int userId, int userPerm)
199 {
200  int perms = getEffectivePermissionOnUpload(pgConn, uploadId, userId, userPerm);
201  if (perms > 0)
202  {
203  if (perms < wanted_permissions)
204  {
205  return 1;
206  }
207  else
208  {
209  return 0;
210  }
211  }
212  else if (perms == 0)
213  {
214  return 1;
215  }
216  return perms;
217 }
218 
229 int check_read_permission_upload(long uploadId, int userId, int userPerm)
230 {
231  return check_permission_upload(PERM_READ, uploadId, userId, userPerm);
232 }
233 
244 int check_write_permission_upload(long uploadId, int userId, int userPerm)
245 {
246  return check_permission_upload(PERM_WRITE, uploadId, userId, userPerm);
247 }
248 
261 int check_write_permission_folder(long folder_id, int userId, int userPerm)
262 {
263  char SQL[MAXSQL];
264  PGresult *result;
265  int count = 0;
266 
267  if (userPerm < PERM_WRITE)
268  {
269  return 1; // can not be deleted
270  }
271 
272  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,userId);
273  result = PQexec(pgConn, SQL);
274  if (fo_checkPQresult(pgConn, result, SQL, __FILE__, __LINE__))
275  {
276  return -1;
277  }
278  count = atol(PQgetvalue(result,0,0));
279  if(count == 0)
280  {
281  return 1; // can not be deleted
282  }
283  return 0; // can be deleted
284 }
285 
296 int check_write_permission_license(long license_id, int userPerm)
297 {
298  if (userPerm != PERM_ADMIN)
299  {
300  printfInCaseOfVerbosity("only admin is allowed to delete licenses\n");
301  return 0; // can not be deleted
302  }
303  return 1; // can be deleted
304 }
305 
318 int deleteUpload (long uploadId, int userId, int userPerm)
319 {
320  char *S;
321  int Row,maxRow;
322  char tempTable[256];
323  PGresult *result, *pfileResult;
324  char SQL[MAXSQL], desc[myBUFSIZ];
325 
326  int permission_upload = check_write_permission_upload(uploadId, userId, userPerm);
327  if(0 != permission_upload) {
328  return permission_upload;
329  }
330 
331  snprintf(tempTable,sizeof(tempTable),"delup_%ld_pfile",uploadId);
332  snprintf(SQL,MAXSQL,"DROP TABLE IF EXISTS %s;",tempTable);
333  PQexecCheckClear(NULL, SQL, __FILE__, __LINE__);
334 
335  snprintf(desc, myBUFSIZ, "Deleting upload %ld",uploadId);
336  PQexecCheckClear(desc, "SET statement_timeout = 0;", __FILE__, __LINE__);
337  PQexecCheckClear(NULL, "BEGIN;", __FILE__, __LINE__);
338 
339  /* Delete everything that impacts the UI */
340  if (!Test) {
341  /* The UI depends on uploadtree and folders for navigation.
342  Delete them now to block timeouts from the UI. */
343  PQexecCheckClear(NULL, "COMMIT;", __FILE__, __LINE__);
344  }
345 
346  /* Begin complicated stuff */
347  /* Get the list of pfiles to delete */
348  /* These are all pfiles in the upload_fk that only appear once. */
349  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);
350  PQexecCheckClear("Getting list of pfiles to delete", SQL, __FILE__, __LINE__);
351 
352  /* Remove pfiles which are reused by other uploads */
353  snprintf(SQL, MAXSQL, "DELETE FROM %s WHERE pfile_pk IN (SELECT pfile_pk FROM %s INNER JOIN uploadtree ON pfile_pk = pfile_fk WHERE upload_fk != %ld)", tempTable, tempTable, uploadId);
354  PQexecCheckClear(NULL, SQL, __FILE__, __LINE__);
355 
356  if (Verbose) {
357  snprintf(SQL,MAXSQL,"SELECT COUNT(*) FROM %s;",tempTable);
358  result = PQexec(pgConn, SQL);
359  if (fo_checkPQresult(pgConn, result, SQL, __FILE__, __LINE__)) {
360  return -1;
361  }
362  printf("# Created pfile table %s with %ld entries\n", tempTable, atol(PQgetvalue(result,0,0)));
363  PQclear(result);
364  }
365 
366  /* Now to delete the actual pfiles from the repository before remove the DB. */
367  /* Get the file listing -- needed for deleting pfiles from the repository. */
368  snprintf(SQL,MAXSQL,"SELECT pfile FROM %s ORDER BY pfile_pk;",tempTable);
369  pfileResult = PQexecCheckResult("Get pfiles to delete from repo", SQL,
370  __FILE__, __LINE__);
371  if (fo_checkPQresult(pgConn, pfileResult, SQL, __FILE__, __LINE__))
372  {
373  return -1;
374  }
375 
376  if (Test <= 1) {
377  maxRow = PQntuples(pfileResult);
378  for(Row=0; Row<maxRow; Row++) {
379  S = PQgetvalue(pfileResult,Row,0); /* sha1.md5.len */
380  if (fo_RepExist("files",S)) {
381  if (Test) {
382  printf("TEST: Delete %s %s\n","files",S);
383  } else {
384  fo_RepRemove("files",S);
385  }
386  }
387  if (fo_RepExist("gold",S)) {
388  if (Test) {
389  printf("TEST: Delete %s %s\n","gold",S);
390  } else {
391  fo_RepRemove("gold",S);
392  }
393  }
394  if (Scheduler == 1)
395  {
397  }
398  }
399  }
400  PQclear(pfileResult);
401 
402  /*
403  This begins the slow part that locks the DB.
404  The problem is, we don't want to lock a critical row,
405  otherwise the scheduler will lock and/or fail.
406  */
407  if (!Test) {
408  PQexecCheckClear(NULL, "BEGIN;", __FILE__, __LINE__);
409  }
410  /* Delete the upload from the folder-contents table */
411  snprintf(SQL,MAXSQL,"DELETE FROM foldercontents WHERE (foldercontents_mode & 2) != 0 AND child_id = %ld;",uploadId);
412  PQexecCheckClear("Deleting foldercontents", SQL, __FILE__, __LINE__);
413 
414  /* Deleting the actual upload contents*/
415  /* Delete the bucket_container record as it can't be cascade delete with upload table */
416  snprintf(SQL,MAXSQL,"DELETE FROM bucket_container USING uploadtree WHERE uploadtree_fk = uploadtree_pk AND upload_fk = %ld;",uploadId);
417  PQexecCheckClear("Deleting bucket_container", SQL, __FILE__, __LINE__);
418 
419  /* Delete the tag_uploadtree record as it can't be cascade delete with upload table */
420  snprintf(SQL,MAXSQL,"DELETE FROM tag_uploadtree USING uploadtree WHERE uploadtree_fk = uploadtree_pk AND upload_fk = %ld;",uploadId);
421  PQexecCheckClear("Deleting tag_uploadtree", SQL, __FILE__, __LINE__);
422 
423  char uploadtree_tablename[1000];
424  snprintf(SQL,MAXSQL,"SELECT uploadtree_tablename FROM upload WHERE upload_pk = %ld;",uploadId);
425  result = PQexecCheckResult("Get uploadtree table name", SQL, __FILE__,
426  __LINE__);
427  if (fo_checkPQresult(pgConn, result, SQL, __FILE__, __LINE__)) {
428  return -1;
429  }
430  if (PQntuples(result)) {
431  strcpy(uploadtree_tablename, PQgetvalue(result, 0, 0));
432  }
433  else
434  {
435  // This should never happen, but upload table does not contain uploadId
436  strcpy(uploadtree_tablename, "uploadtree");
437  }
438  PQclear(result);
439 
440  printfInCaseOfVerbosity("Deleting local license decisions for upload %ld\n",
441  uploadId);
442  /* delete from clearing_event table. */
443  snprintf(SQL, MAXSQL, "WITH alld AS ("
444  "SELECT *, ROW_NUMBER() OVER "
445  "(PARTITION BY clearing_event_pk ORDER BY scope DESC) rnum "
446  "FROM clearing_event ce "
447  "INNER JOIN clearing_decision_event cde "
448  "ON cde.clearing_event_fk = ce.clearing_event_pk "
449  "INNER JOIN clearing_decision cd "
450  "ON cd.clearing_decision_pk = cde.clearing_decision_fk "
451  "AND cd.uploadtree_fk IN "
452  "(SELECT uploadtree_pk FROM %s WHERE upload_fk = %ld)) "
453  "DELETE FROM clearing_event ce USING alld AS ad "
454  "WHERE ad.rnum = 1 AND ad.scope = 0 " // Make sure not to delete global decisions
455  "AND ce.clearing_event_pk = ad.clearing_event_pk;",
456  uploadtree_tablename, uploadId);
457  PQexecCheckClear("Deleting from clearing_event", SQL, __FILE__, __LINE__);
458 
459  /* delete from clearing_decision_event table. */
460  snprintf(SQL, MAXSQL, "DELETE FROM clearing_decision_event AS cde "
461  "USING clearing_decision AS cd "
462  "WHERE cd.scope = 0 " // Make sure not to delete global decisions
463  "AND cd.uploadtree_fk IN "
464  "(SELECT uploadtree_pk FROM %s WHERE upload_fk = %ld) "
465  "AND cd.clearing_decision_pk = cde.clearing_decision_fk;",
466  uploadtree_tablename, uploadId);
467  PQexecCheckClear("Deleting from clearing_decision_event", SQL, __FILE__, __LINE__);
468 
469  /* delete from clearing_decision table. */
470  snprintf(SQL, MAXSQL, "DELETE FROM clearing_decision "
471  "WHERE scope = 0 AND uploadtree_fk IN "
472  "(SELECT uploadtree_pk FROM %s WHERE upload_fk = %ld);",
473  uploadtree_tablename, uploadId);
474  PQexecCheckClear("Deleting from clearing_decision", SQL, __FILE__, __LINE__);
475 
476  /* delete from license_ref_bulk table. */
477  snprintf(SQL, MAXSQL, "DELETE FROM license_ref_bulk "
478  "WHERE uploadtree_fk IN "
479  "(SELECT uploadtree_pk FROM %s WHERE upload_fk = %ld);",
480  uploadtree_tablename, uploadId);
481  PQexecCheckClear("Deleting from license_ref_bulk", SQL, __FILE__, __LINE__);
482 
483  /* delete from uploadtree table. */
484  snprintf(SQL, MAXSQL, "DELETE FROM %s WHERE upload_fk = %ld;",
485  uploadtree_tablename, uploadId);
486  PQexecCheckClear("Deleting from uploadtree", SQL, __FILE__, __LINE__);
487 
488  /* Delete uploadtree_nnn table */
489  if (strcasecmp(uploadtree_tablename, "uploadtree_a") != 0 &&
490  strcasecmp(uploadtree_tablename, "uploadtree") != 0)
491  {
492  snprintf(SQL,MAXSQL,"DROP TABLE %s;", uploadtree_tablename);
493  PQexecCheckClear(NULL, SQL, __FILE__, __LINE__);
494  }
495 
496  /* delete from pfile is SLOW due to constraint checking. Do it separately. */
497  snprintf(SQL,MAXSQL,"DELETE FROM pfile USING %s WHERE pfile.pfile_pk = %s.pfile_pk;",tempTable,tempTable);
498  PQexecCheckClear("Deleting from pfile", SQL, __FILE__, __LINE__);
499 
500  snprintf(SQL,MAXSQL,"DROP TABLE %s;",tempTable);
501  PQexecCheckClear(NULL, SQL, __FILE__, __LINE__);
502 
503  /* Mark upload deleted in upload table */
504  snprintf(SQL,MAXSQL,"UPDATE upload SET expire_action = 'd', "
505  "expire_date = now(), pfile_fk = NULL WHERE upload_pk = %ld;", uploadId);
506  PQexecCheckClear("Marking upload as deleted", SQL, __FILE__, __LINE__);
507 
508  PQexecCheckClear(NULL, "SET statement_timeout = 120000;", __FILE__, __LINE__);
509 
510  printfInCaseOfVerbosity("Deleted upload %ld from DB, now doing repository.\n",uploadId);
511 
512  if (Test) {
513  PQexecCheckClear(NULL, "ROLLBACK;", __FILE__, __LINE__);
514  } else {
515  PQexecCheckClear(NULL, "COMMIT;", __FILE__, __LINE__);
516  }
517 
518  printfInCaseOfVerbosity("Deleted upload %ld\n",uploadId);
519 
520  return 0; /* success */
521 } /* deleteUpload() */
522 
536 int unlinkContent (long child, long parent, int mode, int userId, int userPerm)
537 {
538  int cnt, cntUpload;
539  char SQL[MAXSQL];
540  PGresult *result;
541 
542  if(mode == 1){
543  snprintf(SQL,MAXSQL,"SELECT COUNT(DISTINCT parent_fk) FROM foldercontents WHERE foldercontents_mode=%d AND child_id=%ld",mode,child);
544  }
545  else{
546  snprintf(SQL,MAXSQL,"SELECT COUNT(parent_fk) FROM foldercontents WHERE foldercontents_mode=%d AND"
547  " child_id in (SELECT upload_pk FROM folderlist WHERE pfile_fk="
548  "(SELECT pfile_fk FROM folderlist WHERE upload_pk=%ld limit 1))",
549  mode,child);
550  }
551  result = PQexec(pgConn, SQL);
552  if (fo_checkPQresult(pgConn, result, SQL, __FILE__, __LINE__))
553  {
554  return -1;
555  }
556  cnt = atoi(PQgetvalue(result,0,0));
557  PQclear(result);
558  if(cnt>1 && !Test)
559  {
560  if(mode == 2){
561  snprintf(SQL,MAXSQL,"SELECT COUNT(DISTINCT parent_fk) FROM foldercontents WHERE foldercontents_mode=1 AND child_id=%ld",parent);
562  result = PQexec(pgConn, SQL);
563  if (fo_checkPQresult(pgConn, result, SQL, __FILE__, __LINE__))
564  {
565  return -1;
566  }
567  cntUpload = atoi(PQgetvalue(result,0,0));
568  PQclear(result);
569  if(cntUpload > 1){ // check for copied/duplicate folder
570  return 0;
571  }
572  }
573  snprintf(SQL,MAXSQL,"DELETE FROM foldercontents WHERE foldercontents_mode=%d AND child_id =%ld AND parent_fk=%ld",mode,child,parent);
574  PQexecCheckClear(NULL, SQL, __FILE__, __LINE__);
575  return 0;
576  }
577  return 1;
578 }
579 
598 int listFoldersRecurse (long Parent, int Depth, long Row, int DelFlag, int userId, int userPerm)
599 {
600  int r, i, rc, maxRow;
601  int count, resultUploadCount;
602  long Fid;
603  char *Desc;
604  char SQL[MAXSQL], SQLUpload[MAXSQL];
605  char SQLFolder[MAXSQLFolder];
606  PGresult *result, *resultUpload, *resultFolder;
607 
608  rc = check_write_permission_folder(Parent, userId, userPerm);
609  if(rc < 0)
610  {
611  return rc;
612  }
613  if(DelFlag && rc > 0){
614  return 1;
615  }
616 
617  snprintf(SQLFolder, MAXSQLFolder,"SELECT COUNT(*) FROM folderlist WHERE folder_pk=%ld",Parent);
618  resultFolder = PQexec(pgConn, SQLFolder);
619  count= atoi(PQgetvalue(resultFolder,0,0));
620  PQclear(resultFolder);
621 
622  /* Find all folders with this parent and recurse, but don't show uploads, if they also exist in other directories */
623  snprintf(SQL,MAXSQL,"SELECT folder_pk,foldercontents_mode,name,description,upload_pk,pfile_fk FROM folderlist WHERE parent=%ld"
624  " ORDER BY name,parent,folder_pk ", Parent);
625  result = PQexec(pgConn, SQL);
626  if (fo_checkPQresult(pgConn, result, SQL, __FILE__, __LINE__))
627  {
628  return -1;
629  }
630  maxRow = PQntuples(result);
631  for(r=0; r < maxRow; r++)
632  {
633  if (atol(PQgetvalue(result,r,0)) == Parent)
634  {
635  continue;
636  }
637 
638  Fid = atol(PQgetvalue(result,r,0));
639  if (Fid != 0)
640  {
641  if (!DelFlag)
642  {
643  for(i=0; i<Depth; i++)
644  {
645  fputs(" ",stdout);
646  }
647  printf("%4ld :: %s",Fid,PQgetvalue(result,r,2));
648  Desc = PQgetvalue(result,r,3);
649  if (Desc && Desc[0])
650  {
651  printf(" (%s)",Desc);
652  }
653  printf("\n");
654  }
655  rc = listFoldersRecurse(Fid,Depth+1,Parent,DelFlag,userId,userPerm);
656  if (rc < 0)
657  {
658  if (DelFlag)
659  {
660  printf("Deleting the folder failed.");
661  }
662  return 1;
663  }
664  }
665  else
666  {
667  if (DelFlag==1 && unlinkContent(Parent,Row,1,userId,userPerm)==0)
668  {
669  continue;
670  }
671  if (rc < 0)
672  {
673  return rc;
674  }
675  if (DelFlag)
676  {
677  snprintf(SQLUpload, MAXSQL,"SELECT COUNT(*) FROM folderlist WHERE pfile_fk=%ld", atol(PQgetvalue(result,r,5)));
678  resultUpload = PQexec(pgConn, SQLUpload);
679  resultUploadCount = atoi(PQgetvalue(resultUpload,0,0));
680  if(count < 2 && resultUploadCount < 2)
681  {
682  rc = deleteUpload(atol(PQgetvalue(result,r,4)),userId, userPerm);
683  if (rc < 0)
684  {
685  return rc;
686  }
687  if (rc != 0)
688  {
689  printf("Deleting the folder failed since it contains uploads you can't delete.");
690  return rc;
691  }
692  }
693  else{
694  rc = unlinkContent(atol(PQgetvalue(result,r,4)),Parent,2,userId,userPerm);
695  if(rc < 0){
696  return rc;
697  }
698  }
699  }
700  else
701  {
702  rc = check_read_permission_upload(atol(PQgetvalue(result,r,4)),userId,userPerm);
703  if (rc < 0)
704  {
705  return rc;
706  }
707  if (rc == 0)
708  {
709  for(i=0; i<Depth; i++)
710  {
711  fputs(" ",stdout);
712  }
713  printf("%4s :: Contains: %s\n","--",PQgetvalue(result,r,2));
714  }
715  }
716  }
717  }
718  PQclear(result);
719 
720  switch(Parent)
721  {
722  case 1: /* skip default parent */
723  if (DelFlag != 0)
724  {
725  printf("INFO: Default folder not deleted.\n");
726  }
727  break;
728  case 0: /* it's an upload */
729  break;
730  default: /* it's a folder */
731  if (DelFlag == 0)
732  {
733  break;
734  }
735  printf("INFO: folder id=%ld will be deleted with flag %d\n",Parent,DelFlag);
736  if (DelFlag==1)
737  {
738  rc = unlinkContent(Parent,Row,1,userId,userPerm);
739  if (rc == 0)
740  {
741  break;
742  }
743  if (rc < 0)
744  {
745  return rc;
746  }
747  }
748  if(Row > 0)
749  snprintf(SQL,MAXSQL,"DELETE FROM foldercontents WHERE foldercontents_mode=1 AND parent_fk=%ld AND child_id=%ld",Row,Parent);
750  else
751  snprintf(SQL,MAXSQL,"DELETE FROM foldercontents WHERE foldercontents_mode=1 AND child_id=%ld",Parent);
752  if (Test)
753  {
754  printf("TEST: %s\n",SQL);
755  }
756  else
757  {
758  PQexecCheckClear(NULL, SQL, __FILE__, __LINE__);
759  }
760  if(Row > 0)
761  snprintf(SQL,MAXSQL,"DELETE FROM folder f USING foldercontents fc WHERE f.folder_pk = fc.child_id AND fc.parent_fk='%ld' AND f.folder_pk = '%ld';",Row,Parent);
762  else
763  snprintf(SQL,MAXSQL,"DELETE FROM folder WHERE folder_pk = '%ld';",Parent);
764  if (Test)
765  {
766  printf("TEST: %s\n",SQL);
767  }
768  else
769  {
770  PQexecCheckClear(NULL, SQL, __FILE__, __LINE__);
771  }
772  } /* switch() */
773 
774  return 0; /* success */
775 } /* listFoldersRecurse() */
776 
786 int listFoldersFindDetatchedFolders(PGresult *result, int userId, int userPerm)
787 {
788  int DetachFlag=0;
789  int i,j;
790  int maxRow = PQntuples(result);
791  long Fid; /* folder ids */
792  int Match;
793  char *Desc;
794  int rc;
795 
796  /* Find detached folders */
797  for(i=0; i < maxRow; i++)
798  {
799  Fid = atol(PQgetvalue(result,i,1));
800  if (Fid == 1)
801  {
802  continue; /* skip default parent */
803  }
804  Match=0;
805  for(j=0; (j<maxRow) && !Match; j++)
806  {
807  if ((i!=j) && (atol(PQgetvalue(result,j,0)) == Fid)) Match=1;
808  }
809  if (!Match && !atol(PQgetvalue(result,i,4)))
810  {
811  if (!DetachFlag)
812  {
813  printf("# Unlinked folders\n");
814  DetachFlag=1;
815  }
816  printf("%4ld :: %s",Fid,PQgetvalue(result,i,2));
817  Desc = PQgetvalue(result,i,3);
818  if (Desc && Desc[0])
819  {
820  printf(" (%s)",Desc);
821  }
822  printf("\n");
823  rc = listFoldersRecurse(Fid,1,i,0,userId,userPerm);
824  if (rc < 0)
825  {
826  return rc;
827  }
828  }
829  }
830  return 0;
831 }
832 
840 int listFoldersFindDetatchedUploads(PGresult *result, int userId, int userPerm)
841 {
842  int DetachFlag=0;
843  int i,j;
844  int maxRow = PQntuples(result);
845  long Fid; /* folder ids */
846  int Match;
847  char *Desc;
848  /* Find detached uploads */
849  for(i=0; i < maxRow; i++)
850  {
851  Fid = atol(PQgetvalue(result,i,1));
852  if (Fid == 1)
853  {
854  continue; /* skip default parent */
855  }
856  Match=0;
857  for(j=0; (j<maxRow) && !Match; j++)
858  {
859  if ((i!=j) && (atol(PQgetvalue(result,j,0)) == Fid)) Match=1;
860  }
861  if (!Match && atol(PQgetvalue(result,i,4)))
862  {
863  if (!DetachFlag)
864  {
865  printf("# Unlinked uploads (uploads without folders)\n");
866  DetachFlag=1;
867  }
868  printf("%4s",PQgetvalue(result,i,4));
869  printf(" :: %s",PQgetvalue(result,i,2));
870  Desc = PQgetvalue(result,i,3);
871  if (Desc && Desc[0])
872  {
873  printf(" (%s)",Desc);
874  }
875  printf("\n");
876  }
877  }
878  return 0;
879 }
880 
889 int listFoldersFindDetatched(int userId, int userPerm)
890 {
891  char SQL[MAXSQL];
892  PGresult *result;
893  int rc;
894 
895  snprintf(SQL,MAXSQL,"SELECT folder_pk,parent,name,description,upload_pk FROM folderlist ORDER BY name,parent,folder_pk;");
896  result = PQexec(pgConn, SQL);
897  if (fo_checkPQresult(pgConn, result, SQL, __FILE__, __LINE__))
898  {
899  return -1;
900  }
901  rc = listFoldersFindDetatchedFolders(result, userId, userPerm);
902  if (rc < 0 )
903  {
904  PQclear(result);
905  return rc;
906  }
907  rc = listFoldersFindDetatchedUploads(result, userId, userPerm);
908  PQclear(result);
909  if (rc < 0 )
910  {
911  return rc;
912  }
913  return 0;
914 }
915 
921 int listFolders (int userId, int userPerm)
922 {
923  char SQL[MAXSQL];
924  PGresult *result;
925  int rc;
926 
927  if(userPerm == 0){
928  printf("you do not have the permsssion to view the folder list.\n");
929  return 1;
930  }
931 
932  printf("# Folders\n");
933  snprintf(SQL,MAXSQL,"SELECT folder_name from folder where folder_pk =1;");
934  result = PQexec(pgConn, SQL);
935  if (fo_checkPQresult(pgConn, result, SQL, __FILE__, __LINE__))
936  {
937  return -1;
938  }
939 
940  printf("%4d :: %s\n", 1, PQgetvalue(result,0,0));
941  PQclear(result);
942 
943  rc = listFoldersRecurse(1,1,-1,0,userId,userPerm);
944  if (rc < 0)
945  {
946  return rc;
947  }
948 
949  rc = listFoldersFindDetatched(userId, userPerm);
950  if (rc < 0)
951  {
952  return rc;
953  }
954  return 0;
955 } /* listFolders() */
956 
964 int listUploads (int userId, int userPerm)
965 {
966  int Row,maxRow;
967  long NewPid;
968  PGresult *result;
969  int rc;
970  char *SQL = "SELECT upload_pk,upload_desc,upload_filename FROM upload ORDER BY upload_pk;";
971  printf("# Uploads\n");
972  result = PQexec(pgConn, SQL);
973  if (fo_checkPQresult(pgConn, result, SQL, __FILE__, __LINE__))
974  {
975  exitNow(-1);
976  }
977 
978  /* list each value */
979  maxRow = PQntuples(result);
980  for(Row=0; Row < maxRow; Row++)
981  {
982  NewPid = atol(PQgetvalue(result,Row,0));
983  rc = check_read_permission_upload(NewPid, userId, userPerm);
984  if (rc < 0)
985  {
986  PQclear(result);
987  return rc;
988  }
989  if (NewPid >= 0 && (userPerm == PERM_ADMIN || rc == 0))
990  {
991  char *S;
992  printf("%ld :: %s",NewPid,PQgetvalue(result,Row,2));
993  S = PQgetvalue(result,Row,1);
994  if (S && S[0]) printf(" (%s)",S);
995  printf("\n");
996  }
997  }
998  PQclear(result);
999  return 0;
1000 } /* listUploads() */
1001 
1018 int deleteFolder(long cFolder, long pFolder, int userId, int userPerm)
1019 {
1020  if(pFolder == 0) pFolder= -1 ;
1021  return listFoldersRecurse(cFolder, 0,pFolder,2,userId,userPerm);
1022 } /* deleteFolder() */
1023 
1024 /**********************************************************************/
1025 
1042 int readAndProcessParameter (char *Parm, int userId, int userPerm)
1043 {
1044  char *L;
1045  int rc=0; /* assume no data */
1046  int Type=0; /* 0=undefined; 1=delete; 2=list */
1047  int Target=0; /* 0=undefined; 1=upload; 2=license; 3=folder */
1048  const char s[2] = " ";
1049  char *token;
1050  char a[15];
1051  long fd[2];
1052  int i = 0, len = 0;
1053 
1054  if (!Parm)
1055  {
1056  return(-1);
1057  }
1058  if (Verbose > 1) fprintf(stderr,"DEBUG: Line='%s'\n",Parm);
1059 
1060  /* process the string. */
1061  L = Parm;
1062  while(isspace(L[0])) L++;
1063 
1065  if (!strncasecmp(L,"DELETE",6) && isspace(L[6]))
1066  {
1067  Type=1; /* delete */
1068  L+=6;
1069  }
1070  else if (!strncasecmp(L,"LIST",4) && isspace(L[4]))
1071  {
1072  Type=2; /* list */
1073  L+=4;
1074  }
1075  while(isspace(L[0])) L++;
1077  if (!strncasecmp(L,"UPLOAD",6) && (isspace(L[6]) || !L[6]))
1078  {
1079  Target=1; /* upload */
1080  L+=6;
1081  }
1082  else if (!strncasecmp(L,"LICENSE",7) && (isspace(L[7]) || !L[7]))
1083  {
1084  Target=2; /* license */
1085  L+=7;
1086  }
1087  else if (!strncasecmp(L,"FOLDER",6) && (isspace(L[6]) || !L[6]))
1088  {
1089  Target=3; /* folder */
1090  L+=6;
1091  }
1092 
1093  len = strlen(L);
1094  memcpy(a, L,len);
1095  token = strtok(a, s);
1096 
1097  while( token != NULL )
1098  {
1099  fd[i] = atol(token);
1100  token = strtok(NULL, s);
1101  i++;
1102  }
1103 
1104  /* Handle the request */
1105  if ((Type==1) && (Target==1))
1106  {
1107  rc = deleteUpload(fd[0], userId, userPerm);
1108  }
1109  else if ((Type==1) && (Target==3))
1110  {
1111  rc = deleteFolder(fd[1],fd[0], userId, userPerm);
1112  }
1113  else if (((Type==2) && (Target==1)) || ((Type==2) && (Target==2)))
1114  {
1115  rc = listUploads(0, PERM_ADMIN);
1116  }
1117  else if ((Type==2) && (Target==3))
1118  {
1119  rc = listFolders(userId, userPerm);
1120  }
1121  else
1122  {
1123  LOG_ERROR("Unknown command: '%s'\n",Parm);
1124  }
1125 
1126  return rc;
1127 } /* readAndProcessParameter() */
1128 
1139 {
1140  char *Parm = NULL;
1141  char SQL[MAXSQL];
1142  PGresult *result;
1143  int userId = -1;
1144  int userPerm = -1;
1145 
1146  while(fo_scheduler_next())
1147  {
1148  Parm = fo_scheduler_current();
1149  userId = fo_scheduler_userID();
1150 
1151  /* get perm level of user */
1152  snprintf(SQL,MAXSQL,"SELECT user_perm FROM users WHERE user_pk='%d';", userId);
1153  result = PQexec(pgConn, SQL);
1154  if (fo_checkPQresult(pgConn, result, SQL, __FILE__, __LINE__) || !PQntuples(result))
1155  {
1156  exitNow(0);
1157  }
1158  userPerm = atoi(PQgetvalue(result, 0, 0));
1159  PQclear(result);
1160 
1161  int returnCode = readAndProcessParameter(Parm, userId, userPerm);
1162  if (returnCode != 0)
1163  {
1164  /* Loglevel is to high, but scheduler expects FATAL log message before exit */
1165  LOG_FATAL("Due to permission problems, the delagent was not able to list or delete the requested objects or they did not exist.");
1166  exitNow(returnCode);
1167  }
1168  }
1169 }
1177 void exitNow(int exitVal)
1178 {
1179  if (pgConn) PQfinish(pgConn);
1180 
1181  if (exitVal) LOG_ERROR("Exiting with status %d", exitVal);
1182 
1183  fo_scheduler_disconnect(exitVal);
1184  exit(exitVal);
1185 } /* exitNow() */
char SQL[256]
SQL query to execute.
Definition: adj2nest.c:78
char * uploadtree_tablename
upload.uploadtree_tablename
Definition: adj2nest.c:100
int listFoldersFindDetatchedUploads(PGresult *result, int userId, int userPerm)
Given a PGresult, find detached uploads.
Definition: util.c:840
int check_permission_upload(int wanted_permissions, long uploadId, int userId, int userPerm)
check if the upload can be deleted, that is the user have the permission to delete this upload
Definition: util.c:198
int unlinkContent(long child, long parent, int mode, int userId, int userPerm)
remove link between parent and (child,mode) if there are other parents
Definition: util.c:536
int readAndProcessParameter(char *Parm, int userId, int userPerm)
Parse parameters.
Definition: util.c:1042
void doSchedulerTasks()
process the jobs from scheduler
Definition: util.c:1138
int check_write_permission_folder(long folder_id, int userId, int userPerm)
check if the upload can be deleted, that is the user have the permission to delete this upload
Definition: util.c:261
int check_write_permission_license(long license_id, int userPerm)
check if the license can be deleted, that is the user have the permission to delete this license
Definition: util.c:296
int listFoldersRecurse(long Parent, int Depth, long Row, int DelFlag, int userId, int userPerm)
Draw folder tree.
Definition: util.c:598
int authentication(char *user, char *password, int *userId, int *userPerm)
if this account is valid
Definition: util.c:129
PGconn * pgConn
Database connection.
Definition: util.c:22
int printfInCaseOfVerbosity(const char *format,...)
If verbose is on, print to stdout.
Definition: util.c:30
void exitNow(int exitVal)
Exit function. This does all cleanup and should be used instead of calling exit() or main() return.
Definition: util.c:1177
void PQexecCheckClear(const char *desc, char *SQL, char *file, const int line)
Execute SQL query and create the result.
Definition: util.c:110
int Verbose
Verbose level.
Definition: util.c:19
PGresult * PQexecCheck(const char *desc, char *SQL, char *file, const int line)
simple wrapper which includes PQexec and fo_checkPQcommand for queries without result
Definition: util.c:54
int listUploads(int userId, int userPerm)
List every upload ID.
Definition: util.c:964
int listFoldersFindDetatched(int userId, int userPerm)
Given a user id, find detached folders and uploads.
Definition: util.c:889
int Test
Definition: util.c:20
int Scheduler
Definition: util.c:21
int listFolders(int userId, int userPerm)
List every folder.
Definition: util.c:921
int deleteUpload(long uploadId, int userId, int userPerm)
Given an upload ID, delete it.
Definition: util.c:318
int check_write_permission_upload(long uploadId, int userId, int userPerm)
check if the user has read permission on the given upload
Definition: util.c:244
PGresult * PQexecCheckResult(const char *desc, char *SQL, char *file, const int line)
simple wrapper which includes PQexec and fo_checkPQresult for queries with result
Definition: util.c:85
int deleteFolder(long cFolder, long pFolder, int userId, int userPerm)
recursively delete a folder
Definition: util.c:1018
int check_read_permission_upload(long uploadId, int userId, int userPerm)
check if the user has read permission on the given upload
Definition: util.c:229
int listFoldersFindDetatchedFolders(PGresult *result, int userId, int userPerm)
Given a PGresult, find detached folders.
Definition: util.c:786
int s
The socket that the CLI will use to communicate.
Definition: fo_cli.c:37
FUNCTION int getEffectivePermissionOnUpload(PGconn *pgConn, long UploadPk, int user_pk, int user_perm)
Get users permission to this upload.
Definition: libfossagent.c:321
int fo_checkPQresult(PGconn *pgConn, PGresult *result, char *sql, char *FileID, int LineNumb)
Check the result status of a postgres SELECT.
Definition: libfossdb.c:170
int fo_checkPQcommand(PGconn *pgConn, PGresult *result, char *sql, char *FileID, int LineNumb)
Check the result status of a postgres commands (not select) If an error occured, write the error to s...
Definition: libfossdb.c:204
#define PERM_WRITE
Read-Write permission.
Definition: libfossology.h:33
#define PERM_READ
Read-only permission.
Definition: libfossology.h:32
#define PERM_ADMIN
Administrator.
Definition: libfossology.h:34
int fo_RepExist(char *Type, char *Filename)
Determine if a file exists.
Definition: libfossrepo.c:486
int fo_RepRemove(char *Type, char *Filename)
Delete a repository file.
Definition: libfossrepo.c:568
void fo_scheduler_disconnect(int retcode)
Disconnect the scheduler connection.
void fo_scheduler_heart(int i)
This function must be called by agents to let the scheduler know they are alive and how many items th...
int fo_scheduler_userID()
Gets the id of the user that created the job that the agent is running.
char * fo_scheduler_current()
Get the last read string from the scheduler.
char * fo_scheduler_next()
Get the next data to process from the scheduler.
Definition: match.h:20