imap-backup 9.1.1 → 9.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f5cf8072ca8c7a95ca74edc961352099b468a287e846c71c0243d5c2fc285e17
4
- data.tar.gz: 8b66b63ed93044a9fe019ce5af838f165589a9f7b1eebe0751cc804891dacab2
3
+ metadata.gz: 2817e61358b848f7dbef08e1a16562def8cd364e66d317e4dac56c1f5e62f958
4
+ data.tar.gz: ec0e2d2963e863b204b0529ca3746492703486e8f77a9e7c08bc301b203249de
5
5
  SHA512:
6
- metadata.gz: 79a410fe6b307969a27cafed38cd145951016c86c45f62033b91dd6b9df289993f4e134c42bd6ddabbb8b4a523534fdad18ea4b71cd40aa6656375c750c4aaf6
7
- data.tar.gz: baf5eb4583afe8263f54cede96ad308f1b0ce507987b10adfba337eb899ecc456f22c9895cb18805a87ef486ba3712f150af17ca21beed5160081b3eb4c07ffe
6
+ metadata.gz: 66871fce3faebbcbd87737fef230803b46f32025b28753fe4f83813e652ef14817fce302da0570000f0d0ecb582862589a84f535a94aa1fa7cc1578eaf30591c
7
+ data.tar.gz: 274cfc47767322e31eb1e7206c3d1d449b2098ba1a65073c80aa5010c06924abfc7a952aeace01436715a7f95599503d86bcecbbdf210f7c8b5529bf7bee4fdf
@@ -2,7 +2,7 @@ require "logger"
2
2
  require "singleton"
3
3
 
4
4
  require "imap/backup/configuration"
5
- require "imap/backup/sanitizer"
5
+ require "text/sanitizer"
6
6
 
7
7
  module Imap::Backup
8
8
  class Logger
@@ -33,7 +33,7 @@ module Imap::Backup
33
33
  end
34
34
 
35
35
  def self.sanitize_stderr
36
- sanitizer = Sanitizer.new($stdout)
36
+ sanitizer = Text::Sanitizer.new($stdout)
37
37
  previous_stderr = $stderr
38
38
  $stderr = sanitizer
39
39
  yield
@@ -0,0 +1,25 @@
1
+ module Imap::Backup
2
+ class Naming
3
+ INVALID_FILENAME_CHARACTERS = ":%;".freeze
4
+ INVALID_FILENAME_CHARACTER_MATCH = /([#{INVALID_FILENAME_CHARACTERS}])/.freeze
5
+
6
+ # `*_path` functions treat `/` as an acceptable character
7
+ def self.to_local_path(name)
8
+ name.gsub(INVALID_FILENAME_CHARACTER_MATCH) do |character|
9
+ hex =
10
+ character.
11
+ codepoints[0].
12
+ to_s(16)
13
+ "%#{hex};"
14
+ end
15
+ end
16
+
17
+ def self.from_local_path(name)
18
+ name.gsub(/%(.*?);/) do
19
+ ::Regexp.last_match(1).
20
+ to_i(16).
21
+ chr("UTF-8")
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,4 +1,6 @@
1
1
  module Imap::Backup
2
+ class Serializer; end
3
+
2
4
  class Serializer::Appender
3
5
  attr_reader :imap
4
6
  attr_reader :folder
@@ -1,6 +1,7 @@
1
1
  require "forwardable"
2
2
 
3
3
  require "email/mboxrd/message"
4
+ require "imap/backup/naming"
4
5
  require "imap/backup/serializer/appender"
5
6
  require "imap/backup/serializer/imap"
6
7
  require "imap/backup/serializer/message"
@@ -72,7 +73,7 @@ module Imap::Backup
72
73
  def append(uid, message, flags)
73
74
  validate!
74
75
 
75
- appender = Serializer::Appender.new(folder: folder, imap: imap, mbox: mbox)
76
+ appender = Serializer::Appender.new(folder: sanitized, imap: imap, mbox: mbox)
76
77
  appender.run(uid: uid, message: message, flags: flags)
77
78
  end
78
79
 
@@ -116,14 +117,16 @@ module Imap::Backup
116
117
  end
117
118
 
118
119
  def folder_path
119
- self.class.folder_path_for(path: path, folder: folder)
120
+ self.class.folder_path_for(path: path, folder: sanitized)
120
121
  end
121
122
 
122
123
  private
123
124
 
124
125
  def rename(new_name)
125
126
  destination = self.class.folder_path_for(path: path, folder: new_name)
126
- ensure_containing_directory(new_name)
127
+ relative = File.dirname(new_name)
128
+ directory = Serializer::Directory.new(path, relative)
129
+ directory.ensure_exists
127
130
  mbox.rename destination
128
131
  imap.rename destination
129
132
  end
@@ -136,7 +139,7 @@ module Imap::Backup
136
139
  def mbox
137
140
  @mbox ||=
138
141
  begin
139
- ensure_containing_directory(folder)
142
+ ensure_containing_directory
140
143
  Serializer::Mbox.new(folder_path)
141
144
  end
142
145
  end
@@ -144,11 +147,15 @@ module Imap::Backup
144
147
  def imap
145
148
  @imap ||=
146
149
  begin
147
- ensure_containing_directory(folder)
150
+ ensure_containing_directory
148
151
  Serializer::Imap.new(folder_path)
149
152
  end
150
153
  end
151
154
 
155
+ def sanitized
156
+ @sanitized ||= Naming.to_local_path(folder)
157
+ end
158
+
152
159
  def optionally_migrate2to3
153
160
  migrator = Version2Migrator.new(folder_path)
154
161
  return if !migrator.required?
@@ -162,8 +169,8 @@ module Imap::Backup
162
169
  migrator.run
163
170
  end
164
171
 
165
- def ensure_containing_directory(folder)
166
- relative = File.dirname(folder)
172
+ def ensure_containing_directory
173
+ relative = File.dirname(sanitized)
167
174
  directory = Serializer::Directory.new(path, relative)
168
175
  directory.ensure_exists
169
176
  end
@@ -2,8 +2,8 @@ module Imap; end
2
2
 
3
3
  module Imap::Backup
4
4
  MAJOR = 9
5
- MINOR = 1
6
- REVISION = 1
5
+ MINOR = 2
6
+ REVISION = 0
7
7
  PRE = nil
8
8
  VERSION = [MAJOR, MINOR, REVISION, PRE].compact.map(&:to_s).join(".")
9
9
  end
@@ -0,0 +1,46 @@
1
+ require "forwardable"
2
+
3
+ module Text; end
4
+
5
+ class Text::Sanitizer
6
+ extend Forwardable
7
+
8
+ attr_reader :output
9
+
10
+ delegate puts: :output
11
+ delegate write: :output
12
+
13
+ def initialize(output)
14
+ @output = output
15
+ @current = ""
16
+ end
17
+
18
+ def print(*args)
19
+ @current << args.join
20
+ loop do
21
+ line, newline, rest = @current.partition("\n")
22
+ break if newline != "\n"
23
+
24
+ clean = sanitize(line)
25
+ output.puts clean
26
+ @current = rest
27
+ end
28
+ end
29
+
30
+ def flush
31
+ return if @current == ""
32
+
33
+ clean = sanitize(@current)
34
+ output.puts clean
35
+ end
36
+
37
+ private
38
+
39
+ def sanitize(text)
40
+ # Hide password in Net::IMAP debug output
41
+ text.gsub(
42
+ /\A(C: RUBY\d+ LOGIN \S+) \S+/,
43
+ "\\1 [PASSWORD REDACTED]"
44
+ )
45
+ end
46
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: imap-backup
3
3
  version: !ruby/object:Gem::Version
4
- version: 9.1.1
4
+ version: 9.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joe Yates
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-02-19 00:00:00.000000000 Z
11
+ date: 2023-03-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: highline
@@ -258,7 +258,7 @@ files:
258
258
  - lib/imap/backup/migrator.rb
259
259
  - lib/imap/backup/mirror.rb
260
260
  - lib/imap/backup/mirror/map.rb
261
- - lib/imap/backup/sanitizer.rb
261
+ - lib/imap/backup/naming.rb
262
262
  - lib/imap/backup/serializer.rb
263
263
  - lib/imap/backup/serializer/appender.rb
264
264
  - lib/imap/backup/serializer/directory.rb
@@ -282,6 +282,7 @@ files:
282
282
  - lib/imap/backup/utils.rb
283
283
  - lib/imap/backup/version.rb
284
284
  - lib/retry_on_error.rb
285
+ - lib/text/sanitizer.rb
285
286
  homepage: https://github.com/joeyates/imap-backup
286
287
  licenses:
287
288
  - MIT
@@ -1,46 +0,0 @@
1
- require "forwardable"
2
-
3
- module Imap::Backup
4
- class Sanitizer
5
- extend Forwardable
6
-
7
- attr_reader :output
8
-
9
- delegate puts: :output
10
- delegate write: :output
11
-
12
- def initialize(output)
13
- @output = output
14
- @current = ""
15
- end
16
-
17
- def print(*args)
18
- @current << args.join
19
- loop do
20
- line, newline, rest = @current.partition("\n")
21
- break if newline != "\n"
22
-
23
- clean = sanitize(line)
24
- output.puts clean
25
- @current = rest
26
- end
27
- end
28
-
29
- def flush
30
- return if @current == ""
31
-
32
- clean = sanitize(@current)
33
- output.puts clean
34
- end
35
-
36
- private
37
-
38
- def sanitize(text)
39
- # Hide password in Net::IMAP debug output
40
- text.gsub(
41
- /\A(C: RUBY\d+ LOGIN \S+) \S+/,
42
- "\\1 [PASSWORD REDACTED]"
43
- )
44
- end
45
- end
46
- end