lenc 1.1.3 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,21 +14,15 @@ module RepoInternal
14
14
  def initialize
15
15
  @dirOnly, @negated, @pathMode, @rexp, @dbPattern = nil
16
16
  end
17
-
18
- def inspect
19
- to_s
20
- end
21
- def to_s
22
- s = "Ign<"
23
- s << df(@dirOnly,"dirOnly") << "expr: " << @rexp.to_s << ">"
24
- s
25
- end
26
17
  end
27
18
  end
28
19
 
29
20
 
30
21
  module LEnc
31
22
 
23
+ KEY_LEN_MIN = 8
24
+ KEY_LEN_MAX = 56
25
+
32
26
  class DecryptionError < Exception
33
27
  end
34
28
 
@@ -113,19 +107,51 @@ module LEnc
113
107
  end
114
108
  end
115
109
 
116
-
110
+ # If a password hasn't been defined, ask user for one.
111
+ # Also, pad password out to some minimum size
112
+ #
113
+ def define_password(pwd)
114
+ if !pwd
115
+
116
+ if true
117
+
118
+ # Use the 'highline' gem to allow typing password without echo to screen
119
+ require 'rubygems'
120
+ require 'highline/import'
121
+ pwd = ask("Password: ") {|q| q.echo = false}
122
+
123
+ else
124
+ printf("Password: ")
125
+ pwd = gets
126
+ end
127
+
128
+ if pwd
129
+ pwd.strip!
130
+ pwd = nil if pwd.size == 0
131
+ end
132
+ if !pwd
133
+ raise DecryptionError, "No password given"
134
+ end
135
+ end
136
+
137
+ while pwd.size < KEY_LEN_MIN
138
+ pwd *= 2
139
+ end
140
+ pwd
141
+ end
142
+
143
+
117
144
  # Create a new encryption repository, and open it.
118
145
  #
119
- # @param repo_dir directory of new repository (nil for current directory)
120
- # @param key encryption key, a string from 8 to 56 characters in length
121
- # @param enc_dir directory to store encrypted files; must not yet exist, and must
122
- # not represent a directory lying within the repo_dir tree
123
- # @param original_names if true, the filenames are not encrypted, only the file contents
124
- # @param store_key if true, the key is written to the repository configuration file; otherwise,
125
- # user must supply the key every time the repository is updated
146
+ # @param repo_dir directory of new repository (nil for current directory)
147
+ # @param key encryption key, a string from KEY_LEN_MIN to KEY_LEN_MAX characters in length
148
+ # @param enc_dir if not nil, directory to store encrypted files; must not yet exist, and must
149
+ # not represent a directory lying within the repo_dir tree;
150
+ # if nil, repository will be encrypted in-place
151
+ # @param original_names if true, the filenames are not encrypted, only the file contents
126
152
  # @raise ArgumentError if appropriate
127
153
  #
128
- def create(repo_dir, key, enc_dir, original_names=false, store_key=true)
154
+ def create(repo_dir, key, enc_dir, original_names=false)
129
155
  raise IllegalStateException if @state != STATE_CLOSED
130
156
 
131
157
  db = warndb 0
@@ -149,28 +175,34 @@ module LEnc
149
175
 
150
176
  @orignames = original_names
151
177
 
152
- edir = File.absolute_path(enc_dir)
153
178
  @confFile.set('orignames', @orignames)
154
179
 
155
- if @verbosity >= 0
180
+ if @verbosity >= 1
156
181
  pr("Creating encryption repository %s\n", @confFile.path)
157
182
  end
158
183
 
159
- pp = verifyDirsDistinct([repo_dir, edir])
160
-
161
- if pp
162
- raise ArgumentError, "Directory " + pp[0] + \
163
- " is a subdirectory of " + pp[1]
164
- end
184
+ edir = nil
185
+ if enc_dir
186
+ edir = File.absolute_path(enc_dir)
187
+ pp = verifyDirsDistinct([repo_dir, edir])
188
+
189
+ if pp
190
+ raise ArgumentError, "Directory " + pp[0] + \
191
+ " is a subdirectory of " + pp[1]
192
+ end
165
193
 
166
- if (key.size < 8 || key.size > 56)
194
+ if File.exists?(edir)
195
+ raise ArgumentError, \
196
+ "Encryption directory or file already exists: '#{edir}'"
197
+ end
198
+ @confFile.set('enc_dir', edir)
199
+ end
200
+
201
+ key = define_password(key)
202
+ if (key.size < KEY_LEN_MIN || key.size > KEY_LEN_MAX)
167
203
  raise ArgumentError, "Password length " + key.size.to_s \
168
204
  + " is illegal"
169
205
  end
170
-
171
- if store_key
172
- @confFile.set('key', key)
173
- end
174
206
 
175
207
  # Construct a string that verifies the password is correct
176
208
  en = MyAES.new(true, key )
@@ -181,17 +213,10 @@ module LEnc
181
213
  vs2 = Base64.urlsafe_encode64(verifier_string)
182
214
  @confFile.set('key_verifier', vs2)
183
215
 
184
-
185
- # Create encryption directory
186
- if File.exists?(edir)
187
- raise ArgumentError, \
188
- "Encryption directory or file already exists: '#{edir}'"
189
- end
190
-
191
- @confFile.set('enc_dir', edir)
192
-
193
216
  if not @dryrun
194
- Dir.mkdir(edir)
217
+ if edir
218
+ Dir.mkdir(edir)
219
+ end
195
220
  @confFile.write()
196
221
  end
197
222
 
@@ -208,9 +233,9 @@ module LEnc
208
233
  # @raise IllegalStateException if repository is already open
209
234
  # @raise ArgumentError if directory doesn't exist, or does not lie in a repository
210
235
  #
211
- def open(startDirectory=nil, password = nil)
236
+ def open(startDirectory = nil, password = nil)
212
237
  db = warndb 0
213
- !db || pr("Repo.open startDir=%s\n",d(startDirectory))
238
+ !db || pr("Repo.open startDir=%s, password=%s\n",d(startDirectory),d(password))
214
239
 
215
240
  raise IllegalStateException if @state != STATE_CLOSED
216
241
 
@@ -242,18 +267,7 @@ module LEnc
242
267
 
243
268
  # Read values from configuration to instance vars
244
269
  @encrDir = @confFile.val('enc_dir')
245
- pwd = @confFile.val('key') || password
246
- if !pwd
247
- printf("Password: ")
248
- pwd = gets
249
- if pwd
250
- pwd.strip!
251
- pwd = nil if pwd.size == 0
252
- end
253
- if !pwd
254
- raise DecryptionError, "No password given"
255
- end
256
- end
270
+ pwd = define_password(password)
257
271
 
258
272
  @orignames = @confFile.val('orignames')
259
273
  @encrKey = pwd
@@ -277,29 +291,57 @@ module LEnc
277
291
  reset_state()
278
292
  end
279
293
 
280
- # Update the repository. Finds files that need to be re-encrypted and does so.
294
+ # Encrypt repository's files.
295
+ # If repo is dual, finds files that need to be re-encrypted and does so.
296
+ # If singular, encrypts all those files that are not yet encrypted.
297
+ #
281
298
  # Repository must be open.
282
- #
283
- # @param verifyEncryption for debug purposes; if true, each file that is encrypted is tested to confirm that
284
- # it decrypts correctly.
285
299
  #
286
300
  # @raise IllegalStateException if repository isn't open.
287
301
  #
288
- def perform_update(verifyEncryption=false)
302
+ def perform_encrypt()
289
303
  raise IllegalStateException if @state != STATE_OPEN
290
304
 
291
- setInputOutputDirs(@startDir,@encrDir)
305
+ enc_dir = @encrDir
306
+ if in_place?
307
+ enc_dir = @repoBaseDir
308
+ end
309
+
310
+ setInputOutputDirs(@startDir,enc_dir)
292
311
 
293
- @verifyEncryption = verifyEncryption
312
+ # If encrypting singular repository, ignore all .lencignore files
313
+ if in_place?
314
+ pushIgnoreList('', Repo.parseIgnoreList(".lencignore"))
315
+ end
294
316
 
295
317
  puts("Encrypting...") if @verbosity >= 1
296
318
 
297
319
  begin
298
- encryptDir(@repoBaseDir, @encrDir)
320
+ ecrypt_directory_contents(@repoBaseDir, enc_dir)
299
321
  puts("...done.") if @verbosity >= 1
300
322
  end
301
323
  end
302
324
 
325
+ # Decrypt files within singular repository.
326
+ # Repository must be open.
327
+ #
328
+ # @raise IllegalStateException if repository isn't open.
329
+ #
330
+ def perform_decrypt()
331
+ raise IllegalStateException if (@state != STATE_OPEN || !in_place?)
332
+
333
+ enc_dir = @repoBaseDir
334
+
335
+ setInputOutputDirs(enc_dir,enc_dir)
336
+
337
+ puts("Decrypting...") if @verbosity >= 1
338
+
339
+ begin
340
+ decrypt_directory_contents(enc_dir)
341
+ puts("...done.") if @verbosity >= 1
342
+ end
343
+ end
344
+
303
345
 
304
346
  # Recover files from a repository's encryption folder.
305
347
  #
@@ -316,6 +358,7 @@ module LEnc
316
358
 
317
359
  ret = nil
318
360
 
361
+ key = define_password(key)
319
362
  @encrKey = key
320
363
 
321
364
  rd = File.absolute_path(rDir)
@@ -526,6 +569,10 @@ module LEnc
526
569
  initIgnoreList()
527
570
  end
528
571
 
572
+ def in_place?
573
+ !@encrDir
574
+ end
575
+
529
576
  # Construct the initial ignore list.
530
577
  #
531
578
  # We maintain a stack of these lists, and subsequent operations can push and pop
@@ -580,7 +627,9 @@ module LEnc
580
627
  #
581
628
  # Encrypted filenames are also given a prefix to distinguish them
582
629
  # from files not created by this program (or filenames that have not been encrypted)
583
- #
630
+ # If the given filename already has this prefix, it is assumed that the filename has
631
+ # already been encrypted.
632
+ #
584
633
  # If filenames are not encrypted in this repository, returns filename unchanged.
585
634
  #
586
635
  def encryptFilename(s)
@@ -590,6 +639,8 @@ module LEnc
590
639
 
591
640
  return s if @orignames
592
641
 
642
+ return s if s.start_with?(ENCRFILENAMEPREFIX)
643
+
593
644
  nonce = OpenSSL::Digest::SHA1.new(s).digest
594
645
  !db || pr(" SHA1 applied, nonce=%s\n",dt(nonce))
595
646
  !db || hex_dump(nonce,"SHA1 nonce")
@@ -645,7 +696,7 @@ module LEnc
645
696
  !db || pr("verify_encrypt_pwd key %s, verifier %s\n",d(key),hex_dump_to_string(key_verifier))
646
697
 
647
698
  if !MyAES.is_string_encrypted(key, key_verifier)
648
- raise(DecryptionError, "#{key} is not the correct password for this repository")
699
+ raise(DecryptionError, "incorrect password")
649
700
  end
650
701
  end
651
702
 
@@ -674,14 +725,23 @@ module LEnc
674
725
 
675
726
 
676
727
  # Update a single source file if necessary (not a directory)
728
+ # @param sourceFile absolute path of source file
729
+ # @param encryptFile absolute path of encrypted file
730
+ #
677
731
  def encrypt_file(sourceFile, encryptFile)
678
732
 
679
- # If encrypted file is a directory, delete it
733
+ db = warndb 0
734
+ !db || pr("encrypt_file\n source=#{sourceFile}\n encrypt=#{encryptFile}\n")
735
+
736
+ # If encrypted file is a directory, delete it. This can only occur if it's a dual repository.
680
737
  if File.directory?(encryptFile)
738
+ raise IllegalStateError if in_place?
739
+
681
740
  pth = rel_path(encryptFile, @outputDir)
682
741
 
683
742
  if @verbosity >= 1
684
- msg = "Encrypting file " + rel_path(sourceFile, @inputDir) + " is overwriting existing directory: " + pth
743
+ msg = "Encrypting file " + rel_path(sourceFile, @inputDir) \
744
+ + " is overwriting existing directory: " + pth
685
745
  end
686
746
 
687
747
  if not @dryrun
@@ -690,9 +750,9 @@ module LEnc
690
750
  end
691
751
 
692
752
  # Determine if existing encrypted version exists
693
- # and is up to date
694
- mustUpdate = (not File.file?(encryptFile)) \
695
- or (File.mtime(encryptFile) < File.mtime(sourceFile))
753
+ # and is up to date; only if not in-place
754
+ mustUpdate = in_place? || ((not File.file?(encryptFile)) \
755
+ or (File.mtime(encryptFile) < File.mtime(sourceFile)))
696
756
 
697
757
  if mustUpdate
698
758
  showProgress = (@verbosity >= 0)
@@ -702,38 +762,36 @@ module LEnc
702
762
  pr("%s", srcDisp)
703
763
  end
704
764
 
705
- encPath = convertFile(sourceFile, true, showProgress, false)
706
- FileUtils.mv(encPath, encryptFile)
707
-
708
-
709
- if @verifyEncryption
710
- # Verify that the original and decoded files are identical
711
- decoded_file = convertFile(encryptFile, false, showProgress, true)
712
- files_match = FileUtils.compare_file(sourceFile, decoded_file.path)
713
- decoded_file.unlink
714
-
715
- if !files_match
716
- delete_file_or_dir(encryptFile)
717
- raise EncryptionVerificationException, \
718
- "File '#{srcDisp}' did not encrypt/decrypt correctly"
719
-
720
- end
721
- if @verbosity >= 0
722
- pr(" (file #{srcDisp} encrypted correctly)\n")
723
- end
765
+ temp_enc_path = convertFile(sourceFile, true, showProgress)
766
+ if not @dryrun
767
+ FileUtils.mv(temp_enc_path, encryptFile)
724
768
  end
769
+
725
770
  end
726
771
  end
727
772
 
728
773
  # Determine if a file matches one of the expressions in the ignore stack.
729
774
  # Searches the stack from top to bottom (i.e., the outermost elements are examined last)
730
- def shouldFileBeIgnored(f)
731
- db = false
732
- !db || pr("shouldFileBeIgnored? #{f}\n")
733
- f2 = f
775
+ # @param name_only filename, without path
776
+ # @param full_path full path of file
777
+ #
778
+ def should_file_be_ignored(name_only, full_path)
779
+ db = warndb 0
780
+ !db || pr("should_file_be_ignored? #{name_only}\n")
781
+
782
+ # Let f2 be the filename including the directories corresponding
783
+ # to the ignore stack
784
+
785
+ f2 = name_only
786
+
734
787
  @ignoreStack.reverse.each do |dir,ients|
735
788
  ients.each do |ient|
736
- fArg = ient.pathMode ? f2 : f
789
+
790
+ if ient.dirOnly && !File.directory?(full_path)
791
+ next
792
+ end
793
+
794
+ fArg = ient.pathMode ? f2 : name_only
737
795
 
738
796
  matches = ient.rexp.match(fArg)
739
797
  !db || pr(" ent path=#{ient.pathMode} rexp=#{ient.rexp} neg=#{ient.negated} matches=#{matches}\n")
@@ -742,7 +800,7 @@ module LEnc
742
800
  return !ient.negated
743
801
  end
744
802
  end
745
- f2 = dir + f2
803
+ f2 = File.join(dir,f2)
746
804
  end
747
805
 
748
806
  return false
@@ -760,8 +818,14 @@ module LEnc
760
818
 
761
819
  # Examine all files in repository; reencrypt those that have changed
762
820
  # (by comparing their time stamps with the time stamps of the encyrypted versions)
763
- def encryptDir(sourceDir, encryptDir)
764
- db = warndb 0
821
+ #
822
+ # @param sourceDir absolute path of source directory
823
+ # @param encryptDir absolute path of encryption directory
824
+ #
825
+ def ecrypt_directory_contents(sourceDir, encryptDir)
826
+
827
+ db = (warndb 0)
828
+
765
829
  !db || pr("\n\nencryptDir\n %s =>\n %s\n",d(sourceDir),d(encryptDir))
766
830
 
767
831
  # Add contents of .lencignore to stack. If none exists, treat as if empty
@@ -776,10 +840,14 @@ module LEnc
776
840
  # Create set of encrypted filenames that belong to this directory, so
777
841
  # we can delete encrypted versions of files that are no longer in the source
778
842
  # directory.
779
- encFilenameSet = Set.new
843
+ # Don't do this if repo is in-place.
844
+ encFilenameSet = nil
845
+ if !in_place?
846
+ in_place? || encFilenameSet = Set.new
847
+ end
780
848
 
781
849
  # If no encrypted directory exists, create one
782
- if not File.directory?(encryptDir)
850
+ if !in_place? && !File.directory?(encryptDir)
783
851
  if @verbosity >= 1
784
852
  puts("Creating encrypted directory: " + d(rel_path(encryptDir, @outputDir)))
785
853
  end
@@ -805,9 +873,6 @@ module LEnc
805
873
  # Convert string to ASCII-8BIT encoding.
806
874
  f = to_ascii8(f2)
807
875
 
808
- !db || pr(" testing if file should be ignored: #{f}\n")
809
- ignore = shouldFileBeIgnored(f)
810
-
811
876
  filePath = File.join(sourceDir,f)
812
877
 
813
878
  if File.symlink?(filePath)
@@ -817,81 +882,198 @@ module LEnc
817
882
  next
818
883
  end
819
884
 
820
- if ignore
885
+ !db || pr(" testing if file should be ignored: #{f}\n")
886
+ if should_file_be_ignored(f, filePath)
821
887
  !db || pr("(ignoring %s)\n", rel_path(filePath, @inputDir)) if @verbosity >= 1
822
888
  next
823
889
  end
824
890
 
825
- if f.start_with?(ENCRFILENAMEPREFIX)
826
- if @verbosity >= 0
827
- pr("(Omitting source file / dir with name that looks encrypted: #{d(f)})\n")
891
+ # If we're doing in-place encryption, file is not a directory, and it's already encrypted, ignore
892
+ if in_place?
893
+ next if (!File.directory?(filePath) && f.start_with?(ENCRFILENAMEPREFIX))
894
+ next if (@orignames && MyAES.is_file_encrypted(@encrKey,filePath))
895
+ else
896
+ if f.start_with?(ENCRFILENAMEPREFIX)
897
+ if @verbosity >= 0
898
+ pr("(Omitting source file / dir with name that looks encrypted: #{d(f)})\n")
899
+ end
900
+ next
828
901
  end
829
902
  end
830
903
 
831
- encrName = encryptFilename(f)
832
- !db || pr(" encrypted filename %s => %s\n",d(f),d(encrName))
833
904
 
834
- if @verifyEncryption
835
- decrName = decryptFilename(encrName, false)
836
- if !decrName || decrName != f
837
- !db || pr("decrName encoding=#{decrName.encoding}\n f encoding=#{f.encoding}\n")
838
- !db || hex_dump(decrName,"decrName")
839
- !db || hex_dump(f,"f")
840
-
841
- raise EncryptionVerificationException, \
842
- "Filename #{f} did not encrypt/decrypt properly"
905
+ if !in_place?
906
+ encrName = encryptFilename(f)
907
+ !db || pr(" encrypted filename %s => %s\n",d(f),d(encrName))
908
+ encFilenameSet.add(encrName)
909
+ encrPath = File.join(encryptDir, encrName)
910
+
911
+ if File.directory?(filePath)
912
+ ecrypt_directory_contents(filePath, encrPath)
913
+ else
914
+ !db || pr("...attempting to encrypt file #{filePath} to #{encrPath}...\n")
915
+ encrypt_file(filePath, encrPath)
843
916
  end
844
- pr(" (filename #{f} encrypted correctly)\n") if @verbosity >= 0
845
- end
846
-
847
- encFilenameSet.add(encrName)
848
- encrPath = File.join(encryptDir, encrName)
849
917
 
850
- if File.directory?(filePath)
851
- encryptDir(filePath, encrPath)
852
- else
853
- !db || pr("...attempting to encrypt file #{filePath} to #{encrPath}...\n")
854
- encrypt_file(filePath, encrPath)
918
+ else
919
+
920
+ encrPath = filePath
921
+ if !@origNames
922
+ encrName = encryptFilename(f)
923
+ encrPath = File.join(sourceDir, encrName)
924
+ end
925
+
926
+ if File.directory?(filePath)
927
+ ecrypt_directory_contents(filePath, filePath)
928
+ # Rename the directory to its encrypted form, if necessary
929
+ if filePath != encrPath
930
+ !db || pr(" renaming now-encrypted file from\n #{filePath}\n to\n #{encrPath}\n")
931
+ FileUtils.mv(filePath,encrPath)
932
+ end
933
+ else
934
+ encrypt_file(filePath, encrPath)
935
+ # Delete unencrypted file, if not using original names
936
+ if !@orignames && !@dryrun
937
+ FileUtils.rm(filePath)
938
+ end
939
+ end
855
940
  end
941
+
856
942
  end
857
943
 
858
944
  # Truncate global ignore list to original length
859
945
  popIgnoreList()
860
946
 
861
- # Examine every file in encrypted directory; delete those that don't correspond to source dir
862
-
863
- # (if doing dry run, encrypt dir may not exist)
864
-
865
- !db || pr("examining files in encrypted dir #{encryptDir} to delete ones that don't belong\n")
866
- if File.directory?(encryptDir)
867
- dire = dir_entries(encryptDir)
868
- else
869
- dire = []
947
+ if !in_place?
948
+ # Examine every file in encrypted directory; delete those that don't correspond to source dir
949
+
950
+ # (if doing dry run, encrypt dir may not exist)
951
+
952
+ !db || pr("examining files in encrypted dir #{encryptDir} to delete ones that don't belong\n")
953
+ if File.directory?(encryptDir)
954
+ dire = dir_entries(encryptDir)
955
+ else
956
+ dire = []
957
+ end
958
+
959
+ dire.each do |f|
960
+ next if not f.start_with?(ENCRFILENAMEPREFIX)
961
+
962
+ if not encFilenameSet.member? f
963
+ begin
964
+ orphanOrigName = decryptFilename(f)
965
+ next if !orphanOrigName
966
+ orphanPath = File.join(encryptDir, f)
967
+ if @verbosity >= 1
968
+ printf("Removing encrypted version of missing (or ignored) file " \
969
+ + rel_path(File.join(sourceDir, orphanOrigName), @inputDir) + ": " + orphanPath)
970
+ end
971
+ if !@dryrun
972
+ remove_file_or_dir(orphanPath)
973
+ end
974
+ rescue DecryptionError
975
+ # ignore...
976
+ end
977
+ end
978
+ end
870
979
  end
980
+ end
981
+
982
+ # Decrypt all files recursively within singular repository subdirectory
983
+ #
984
+ # @param encr_dir_path absolute path of encrypted directory
985
+ # @param decr_dir_name absolute path of directory after decrypting (used for display purposes only);
986
+ # if nil, uses encrypted directory name
987
+ #
988
+ def decrypt_directory_contents(encr_dir_path,decr_dir_name = nil)
989
+
990
+ decr_dir_name ||= encr_dir_path
871
991
 
872
- dire.each do |f|
873
- next if not f.start_with?(ENCRFILENAMEPREFIX)
874
-
875
- if not encFilenameSet.member? f
992
+ db = warndb 0
993
+
994
+ !db || pr("\n\ndecrypt_directory_contents: %s (orignames=#{@orignames})\n",d(encr_dir_path))
995
+
996
+ # Examine each file in source dir
997
+ dirc = dir_entries(encr_dir_path)
998
+
999
+ dirc.each do |f2|
1000
+ # Convert string to ASCII-8BIT encoding.
1001
+ f = to_ascii8(f2)
1002
+
1003
+ filePath = File.join(encr_dir_path,f)
1004
+ if File.symlink?(filePath)
1005
+ if @verbosity >= 0
1006
+ pr("Omitting symlink file '#{rel_path(filePath,@inputDir)}'\n")
1007
+ end
1008
+ next
1009
+ end
1010
+
1011
+ !db || pr(" filePath=#{filePath}\n")
1012
+ decrPath = filePath
1013
+ decrName = f
1014
+ if @orignames
1015
+ if File.file?(filePath)
1016
+ if !MyAES.is_file_encrypted(@encrKey,filePath)
1017
+ !db || pr(" file is not encrypted, skipping\n")
1018
+ next
1019
+ end
1020
+ end
1021
+ else
1022
+ next if !f.start_with?(ENCRFILENAMEPREFIX)
876
1023
  begin
877
- orphanOrigName = decryptFilename(f)
878
- next if !orphanOrigName
879
- orphanPath = File.join(encryptDir, f)
880
- if @verbosity >= 1
881
- printf("Removing encrypted version of missing (or ignored) file " \
882
- + rel_path(File.join(sourceDir, orphanOrigName), @inputDir) + ": " + orphanPath)
1024
+ decrName = decryptFilename(f)
1025
+ decrPath = File.join(encr_dir_path, decrName)
1026
+ rescue DecryptionError => e
1027
+ puts "Unable to decrypt filename #{f}"
1028
+ next
1029
+ end
1030
+ end
1031
+
1032
+ if File.directory?(filePath)
1033
+ decrypt_directory_contents(filePath, File.join(decr_dir_name, decrName))
1034
+ # Rename the directory to its decrypted form, if filenames are to be encrypted
1035
+ if !@orignames
1036
+ raise ArgumentError,"decrypted already exists: #{decrPath}" \
1037
+ if File.exist?(decrPath)
1038
+
1039
+ !db || pr(" renaming now-decrypted directory from\n #{filePath}\n to\n #{decrPath}\n")
1040
+ FileUtils.mv(filePath,decrPath)
1041
+ end
1042
+ else
1043
+ decrPathDisp = File.join(decr_dir_name,decrName)
1044
+ pth = rel_path(decrPathDisp, @repoBaseDir)
1045
+ showProgress = @verbosity >= 0
1046
+ if showProgress
1047
+ pr("%s", pth)
1048
+ end
1049
+ begin
1050
+ tmp_file = convertFile(filePath, false, showProgress)
1051
+ if !@orignames
1052
+ raise ArgumentError,"decrypted file or directory already exists: #{decrPath}" \
1053
+ if File.exist?(decrPath)
883
1054
  end
884
- if !@dryrun
885
- remove_file_or_dir(orphanPath)
1055
+
1056
+ if not @dryrun
1057
+ remove_file_or_dir(decrPath)
1058
+ FileUtils.mv(tmp_file.path, decrPath)
1059
+ # Remove the encrypted version, if we aren't using original names
1060
+ if !@orignames
1061
+ FileUtils.rm(filePath)
1062
+ end
1063
+ else
1064
+ tmp_file.unlink
1065
+ end
1066
+
1067
+ rescue DecryptionError => e
1068
+ if @verbosity >= 0
1069
+ msg = "Unable to decrypt file: #{pth} (cause: #{e.message})"
1070
+ pr("\n%s\n", msg)
886
1071
  end
887
- rescue DecryptionError
888
- # ignore...
889
1072
  end
890
1073
  end
891
1074
  end
892
1075
  end
893
-
894
-
1076
+
895
1077
  # Decrypt all files (and, recursively, folders) within a directory to _recover folder
896
1078
  def recover(encryptDir, recoverDir)
897
1079
  db = warndb 0
@@ -916,7 +1098,10 @@ module LEnc
916
1098
  dirc.each do |f|
917
1099
 
918
1100
  !db || pr("...file=%s\n",d(f))
919
- if shouldFileBeIgnored(f)
1101
+
1102
+ encrFullPath = File.join(encryptDir, f)
1103
+
1104
+ if should_file_be_ignored(f, encrFullPath)
920
1105
  if @verbosity >= 1
921
1106
  pr("(ignoring %s)\n", rel_path(f, @inputDir))
922
1107
  end
@@ -943,7 +1128,6 @@ module LEnc
943
1128
  origName = decrName
944
1129
  end
945
1130
  origPath = File.join(recoverDir, origName)
946
- encrFullPath = File.join(encryptDir, f)
947
1131
 
948
1132
 
949
1133
  # If decrypted version already exists, and is more recent than the
@@ -999,7 +1183,7 @@ module LEnc
999
1183
  # @param encrypt true if encrypting
1000
1184
  # @return temporary file containing modified file
1001
1185
  #
1002
- def convertFile(srcPath,encrypt, showProgress=false, verifying=false)
1186
+ def convertFile(srcPath,encrypt, showProgress=false)
1003
1187
 
1004
1188
  db = warndb 0
1005
1189
  !db||pr("\n\n\n\nconvertFile\n %s\n",d(srcPath))
@@ -1023,10 +1207,6 @@ module LEnc
1023
1207
  showDots = showProgress && chunksRemaining >= dotSize
1024
1208
  !db || (showDots = false)
1025
1209
 
1026
- if showDots and verifying
1027
- pr(" verifying:")
1028
- end
1029
-
1030
1210
  !db || pr("\n encrKey=%s\n",dt(@encrKey))
1031
1211
 
1032
1212
  bf = MyAES.new(encrypt, @encrKey)
@@ -1072,7 +1252,7 @@ module LEnc
1072
1252
 
1073
1253
  end
1074
1254
 
1075
- if showProgress and (showDots or not verifying)
1255
+ if showProgress
1076
1256
  pr("\n")
1077
1257
  end
1078
1258