imap-backup 9.1.0 → 9.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/imap/backup/cli.rb +12 -12
- data/lib/imap/backup/logger.rb +9 -4
- data/lib/imap/backup/naming.rb +25 -0
- data/lib/imap/backup/serializer/appender.rb +2 -0
- data/lib/imap/backup/serializer.rb +14 -7
- data/lib/imap/backup/version.rb +1 -1
- data/lib/text/sanitizer.rb +46 -0
- metadata +4 -3
- data/lib/imap/backup/sanitizer.rb +0 -46
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2817e61358b848f7dbef08e1a16562def8cd364e66d317e4dac56c1f5e62f958
|
4
|
+
data.tar.gz: ec0e2d2963e863b204b0529ca3746492703486e8f77a9e7c08bc301b203249de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 66871fce3faebbcbd87737fef230803b46f32025b28753fe4f83813e652ef14817fce302da0570000f0d0ecb582862589a84f535a94aa1fa7cc1578eaf30591c
|
7
|
+
data.tar.gz: 274cfc47767322e31eb1e7206c3d1d449b2098ba1a65073c80aa5010c06924abfc7a952aeace01436715a7f95599503d86bcecbbdf210f7c8b5529bf7bee4fdf
|
data/lib/imap/backup/cli.rb
CHANGED
@@ -54,8 +54,8 @@ module Imap::Backup
|
|
54
54
|
aliases: ["-r"]
|
55
55
|
)
|
56
56
|
def backup
|
57
|
-
Imap::Backup::Logger.setup_logging
|
58
|
-
Backup.new(
|
57
|
+
non_logging_options = Imap::Backup::Logger.setup_logging(options)
|
58
|
+
Backup.new(non_logging_options).run
|
59
59
|
end
|
60
60
|
|
61
61
|
desc "local SUBCOMMAND [OPTIONS]", "View local info"
|
@@ -111,8 +111,8 @@ module Imap::Backup
|
|
111
111
|
aliases: ["-s"]
|
112
112
|
)
|
113
113
|
def migrate(source_email, destination_email)
|
114
|
-
Imap::Backup::Logger.setup_logging
|
115
|
-
Migrate.new(source_email, destination_email, **
|
114
|
+
non_logging_options = Imap::Backup::Logger.setup_logging(options)
|
115
|
+
Migrate.new(source_email, destination_email, **non_logging_options).run
|
116
116
|
end
|
117
117
|
|
118
118
|
desc(
|
@@ -161,8 +161,8 @@ module Imap::Backup
|
|
161
161
|
aliases: ["-s"]
|
162
162
|
)
|
163
163
|
def mirror(source_email, destination_email)
|
164
|
-
Imap::Backup::Logger.setup_logging
|
165
|
-
Mirror.new(source_email, destination_email, **
|
164
|
+
non_logging_options = Imap::Backup::Logger.setup_logging(options)
|
165
|
+
Mirror.new(source_email, destination_email, **non_logging_options).run
|
166
166
|
end
|
167
167
|
|
168
168
|
desc "remote SUBCOMMAND [OPTIONS]", "View info about online accounts"
|
@@ -178,8 +178,8 @@ module Imap::Backup
|
|
178
178
|
quiet_option
|
179
179
|
verbose_option
|
180
180
|
def restore(email = nil)
|
181
|
-
Imap::Backup::Logger.setup_logging
|
182
|
-
Restore.new(email,
|
181
|
+
non_logging_options = Imap::Backup::Logger.setup_logging(options)
|
182
|
+
Restore.new(email, non_logging_options).run
|
183
183
|
end
|
184
184
|
|
185
185
|
desc "setup", "Configure imap-backup"
|
@@ -191,8 +191,8 @@ module Imap::Backup
|
|
191
191
|
quiet_option
|
192
192
|
verbose_option
|
193
193
|
def setup
|
194
|
-
Imap::Backup::Logger.setup_logging
|
195
|
-
Setup.new(
|
194
|
+
non_logging_options = Imap::Backup::Logger.setup_logging(options)
|
195
|
+
Setup.new(non_logging_options).run
|
196
196
|
end
|
197
197
|
|
198
198
|
desc "stats EMAIL [OPTIONS]", "Print stats for each account folder"
|
@@ -206,8 +206,8 @@ module Imap::Backup
|
|
206
206
|
quiet_option
|
207
207
|
verbose_option
|
208
208
|
def stats(email)
|
209
|
-
Imap::Backup::Logger.setup_logging
|
210
|
-
Stats.new(email,
|
209
|
+
non_logging_options = Imap::Backup::Logger.setup_logging(options)
|
210
|
+
Stats.new(email, non_logging_options).run
|
211
211
|
end
|
212
212
|
|
213
213
|
desc "utils SUBCOMMAND [OPTIONS]", "Various utilities"
|
data/lib/imap/backup/logger.rb
CHANGED
@@ -2,7 +2,7 @@ require "logger"
|
|
2
2
|
require "singleton"
|
3
3
|
|
4
4
|
require "imap/backup/configuration"
|
5
|
-
require "
|
5
|
+
require "text/sanitizer"
|
6
6
|
|
7
7
|
module Imap::Backup
|
8
8
|
class Logger
|
@@ -13,11 +13,14 @@ module Imap::Backup
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def self.setup_logging(options = {})
|
16
|
+
copy = options.clone
|
17
|
+
quiet = copy.delete(:quiet)
|
18
|
+
verbose = copy.delete(:verbose)
|
16
19
|
level =
|
17
20
|
case
|
18
|
-
when
|
21
|
+
when quiet
|
19
22
|
::Logger::Severity::UNKNOWN
|
20
|
-
when
|
23
|
+
when verbose
|
21
24
|
::Logger::Severity::DEBUG
|
22
25
|
else
|
23
26
|
::Logger::Severity::INFO
|
@@ -25,10 +28,12 @@ module Imap::Backup
|
|
25
28
|
logger.level = level
|
26
29
|
debug = level == ::Logger::Severity::DEBUG
|
27
30
|
Net::IMAP.debug = debug
|
31
|
+
|
32
|
+
copy
|
28
33
|
end
|
29
34
|
|
30
35
|
def self.sanitize_stderr
|
31
|
-
sanitizer = Sanitizer.new($stdout)
|
36
|
+
sanitizer = Text::Sanitizer.new($stdout)
|
32
37
|
previous_stderr = $stderr
|
33
38
|
$stderr = sanitizer
|
34
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,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:
|
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:
|
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
|
-
|
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
|
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
|
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
|
166
|
-
relative = File.dirname(
|
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
|
data/lib/imap/backup/version.rb
CHANGED
@@ -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.
|
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-
|
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/
|
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
|