55import fnmatch
66import os
77import subprocess
8+ import shutil
9+ from pathlib import Path
810# global variables (change to suit your needs)
911inputfolderpath = '~' # set to import folder path
1012outputpath = '~' # set to output folder (must exist)
@@ -26,32 +28,67 @@ def find_files(directory, pattern):
2628 for filename in find_files (inputfolderpath , '*.djvu' ):
2729 print (f"[*] Processing DJVU to PDF for { filename } ..." )
2830 i = i + 1
29- inputfull = inputfolderpath + filename
30- outputfilename = filename [:- 4 ]+ i + 'pdf' # make filename unique
31- outputfilepath = outputpath
32- p = subprocess .Popen (["djvu2pdf" , inputfull ], stdout = subprocess .PIPE )
31+ inputfull = os .path .join (inputfolderpath , filename )
32+ # Validate that the file exists and is a regular file
33+ if not os .path .isfile (inputfull ):
34+ print (f"[!] Skipping { filename } - not a valid file" )
35+ continue
36+ outputfilename = f"{ filename [:- 5 ]} _{ i } .pdf" # make filename unique
37+ outputfilepath = os .path .join (outputpath , outputfilename )
38+ # Use list for subprocess to avoid shell injection
39+ p = subprocess .Popen (
40+ ["djvu2pdf" , inputfull ],
41+ stdout = subprocess .PIPE ,
42+ stderr = subprocess .PIPE
43+ )
3344 output , err = p .communicate ()
34- subprocess .call (["mv" , outputfilename , outputfilepath ])
45+ # Use shutil.move instead of shell command for better security
46+ if p .returncode == 0 and os .path .exists (outputfilename ):
47+ shutil .move (outputfilename , outputfilepath )
3548 print ('[-] Processing finished for %s' % filename )
3649 print (f"[--] processed { i } file(s) [--]" )
3750 exit ('\n \" Sanity is madness put to good uses.\" - George Santayana\n ' )
3851
3952elif operationtype == '2' :
4053 filename = input ('What filename to process? (leave blank for example): ' )
41- if 'djvu' in filename :
54+ if filename and 'djvu' in filename :
55+ # Validate filename to prevent path traversal
56+ safe_path = Path (filename ).resolve ()
57+ if not safe_path .is_file () or not str (safe_path ).endswith ('.djvu' ):
58+ print ('[!] Invalid file or not a .djvu file' )
59+ exit ('Invalid input' )
4260 print ('Processing DJVU to PDF...' )
43- p = subprocess .Popen (["djvu2pdf" , filename ], stdout = subprocess .PIPE )
61+ p = subprocess .Popen (
62+ ["djvu2pdf" , str (safe_path )],
63+ stdout = subprocess .PIPE ,
64+ stderr = subprocess .PIPE
65+ )
4466 output , err = p .communicate ()
45- print ('Processing finished' )
46- exit ('Completed sucessfully' )
67+ if p .returncode == 0 :
68+ print ('Processing finished' )
69+ exit ('Completed successfully' )
70+ else :
71+ print (f'[!] Error processing file: { err .decode () if err else "Unknown error" } ' )
72+ exit ('Failed' )
4773 else :
4874 print ('No djvu file to process, running sample' )
4975 print ('Processing DJVU to PDF...' )
50- p = subprocess .Popen (["djvu2pdf" , "assets/example.djvu" ],
51- stdout = subprocess .PIPE )
76+ sample_file = Path ("assets/example.djvu" )
77+ if not sample_file .is_file ():
78+ print ('[!] Sample file not found' )
79+ exit ('Sample file missing' )
80+ p = subprocess .Popen (
81+ ["djvu2pdf" , str (sample_file )],
82+ stdout = subprocess .PIPE ,
83+ stderr = subprocess .PIPE
84+ )
5285 output , err = p .communicate ()
53- print ('Processing finished' )
54- exit ('Completed sucessfully' )
86+ if p .returncode == 0 :
87+ print ('Processing finished' )
88+ exit ('Completed successfully' )
89+ else :
90+ print (f'[!] Error: { err .decode () if err else "Unknown error" } ' )
91+ exit ('Failed' )
5592
5693
5794elif operationtype == '' :
0 commit comments