svn_record 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.
- checksums.yaml +7 -0
- data/README.md +72 -0
- data/Rakefile +7 -0
- data/app/assets/images/svn_record/file_icon/bullet_add.png +0 -0
- data/app/assets/images/svn_record/file_icon/bullet_black.png +0 -0
- data/app/assets/images/svn_record/file_icon/bullet_blue.png +0 -0
- data/app/assets/images/svn_record/file_icon/bullet_delete.png +0 -0
- data/app/assets/images/svn_record/file_icon/bullet_diamond.png +0 -0
- data/app/assets/images/svn_record/file_icon/bullet_end.png +0 -0
- data/app/assets/images/svn_record/file_icon/bullet_go.png +0 -0
- data/app/assets/images/svn_record/file_icon/bullet_orange.png +0 -0
- data/app/assets/images/svn_record/file_icon/bullet_purple.png +0 -0
- data/app/assets/images/svn_record/file_icon/bullet_toggle_minus.png +0 -0
- data/app/assets/images/svn_record/file_icon/bullet_toggle_plus.png +0 -0
- data/app/assets/images/svn_record/file_icon/dir.png +0 -0
- data/app/assets/images/svn_record/file_icon/file.png +0 -0
- data/app/assets/images/svn_record/file_icon/folder.png +0 -0
- data/app/assets/images/svn_record/file_icon/folder_open.png +0 -0
- data/app/assets/images/svn_record/file_icon/folder_open_add.png +0 -0
- data/app/assets/images/svn_record/file_icon/folder_open_orange.png +0 -0
- data/app/assets/javascripts/svn_record/application.js +16 -0
- data/app/assets/javascripts/svn_record/change.js.coffee +4 -0
- data/app/assets/stylesheets/svn_record/application.css +14 -0
- data/app/assets/stylesheets/svn_record/site.css +396 -0
- data/app/controllers/svn_record/application_controller.rb +3 -0
- data/app/controllers/svn_record/repository/application_controller.rb +3 -0
- data/app/controllers/svn_record/repository/changes_controller.rb +38 -0
- data/app/models/svn_record/repository/change.rb +39 -0
- data/app/models/svn_record/repository/file.rb +20 -0
- data/app/models/svn_record/repository/user.rb +14 -0
- data/app/views/layouts/svn_record/subversion.html.slim +22 -0
- data/app/views/svn_record/repository/changes/_changesets_list.slim +29 -0
- data/app/views/svn_record/repository/changes/diff.html.slim +30 -0
- data/app/views/svn_record/repository/changes/entry.html.slim +18 -0
- data/app/views/svn_record/repository/changes/index.html.slim +34 -0
- data/app/views/svn_record/repository/changes/list.html.slim +2 -0
- data/app/views/svn_record/repository/changes/revisions.html.slim +18 -0
- data/config/configuration.yml +5 -0
- data/config/routes.rb +17 -0
- data/lib/Svn/helper.rb +108 -0
- data/lib/Svn/mime_type.rb +492 -0
- data/lib/Svn/scm/adapters/subversion.rb +303 -0
- data/lib/generators/svn_record/install_generator.rb +16 -0
- data/lib/generators/svn_record/templates/create_repository_changes.rb +17 -0
- data/lib/generators/svn_record/templates/create_repository_files.rb +21 -0
- data/lib/generators/svn_record/templates/create_repository_user.rb +8 -0
- data/lib/svn_record/engine.rb +11 -0
- data/lib/svn_record/version.rb +3 -0
- data/lib/svn_record.rb +4 -0
- metadata +161 -0
@@ -0,0 +1,492 @@
|
|
1
|
+
module Svn
|
2
|
+
module MimeType
|
3
|
+
|
4
|
+
MIME_TYPES = {
|
5
|
+
'text/css' => 'css',
|
6
|
+
'text/html' => 'html,htm,xhtml',
|
7
|
+
'text/x-html-template' => 'rhtml',
|
8
|
+
'text/x-ruby' => 'rb,rbw,ruby,rake,erb',
|
9
|
+
'text/x-sh' => 'sh',
|
10
|
+
'text/csv' => 'csv',
|
11
|
+
'image/gif' => 'gif',
|
12
|
+
'image/jpeg' => 'jpg,jpeg,jpe',
|
13
|
+
'image/png' => 'png',
|
14
|
+
'image/tiff' => 'tiff,tif',
|
15
|
+
'image/x-ms-bmp' => 'bmp',
|
16
|
+
'image/x-xpixmap' => 'xpm',
|
17
|
+
'image/svg+xml'=> 'svg',
|
18
|
+
'application/javascript' => 'js',
|
19
|
+
'application/vnd.ms-powerpoint' => 'ppt,pps',
|
20
|
+
'application/x-tar' => 'tar',
|
21
|
+
'application/zip' => 'zip',
|
22
|
+
'application/x-gzip' => 'gz',
|
23
|
+
}.freeze
|
24
|
+
|
25
|
+
EXTENSIONS = MIME_TYPES.inject({}) do |map, (type, exts)|
|
26
|
+
exts.split(',').each {|ext| map[ext.strip] = type}
|
27
|
+
map
|
28
|
+
end
|
29
|
+
|
30
|
+
# returns mime type for name or nil if unknown
|
31
|
+
def self.of(name)
|
32
|
+
return nil unless name
|
33
|
+
m = name.to_s.match(/(^|\.)([^\.]+)$/)
|
34
|
+
EXTENSIONS[m[2].downcase] if m
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns the css class associated to
|
38
|
+
# the mime type of name
|
39
|
+
def self.css_class_of(name)
|
40
|
+
mime = of(name)
|
41
|
+
mime && mime.gsub('/', '-')
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.main_mimetype_of(name)
|
45
|
+
mimetype = of(name)
|
46
|
+
mimetype.split('/').first if mimetype
|
47
|
+
end
|
48
|
+
|
49
|
+
# return true if mime-type for name is type/*
|
50
|
+
# otherwise false
|
51
|
+
def self.is_type?(type, name)
|
52
|
+
main_mimetype = main_mimetype_of(name)
|
53
|
+
type.to_s == main_mimetype
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
module SyntaxHighlighting
|
58
|
+
|
59
|
+
class << self
|
60
|
+
attr_reader :highlighter
|
61
|
+
delegate :highlight_by_filename, :highlight_by_language, :to => :highlighter
|
62
|
+
|
63
|
+
def highlighter=(name)
|
64
|
+
if name.is_a?(Module)
|
65
|
+
@highlighter = name
|
66
|
+
else
|
67
|
+
@highlighter = const_get(name)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
module CodeRay
|
72
|
+
require 'coderay'
|
73
|
+
require 'coderay/helpers/file_type'
|
74
|
+
class << self
|
75
|
+
# Highlights +text+ as the content of +filename+
|
76
|
+
# Should not return line numbers nor outer pre tag
|
77
|
+
def highlight_by_filename(text, filename)
|
78
|
+
language = ::CodeRay::FileType[filename]
|
79
|
+
language ? ::CodeRay.scan(text, language).html(:break_lines => true) : ERB::Util.h(text)
|
80
|
+
end
|
81
|
+
# Highlights +text+ using +language+ syntax
|
82
|
+
# Should not return outer pre tag
|
83
|
+
def highlight_by_language(text, language)
|
84
|
+
::CodeRay.scan(text, language).html(:wrap => :span)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
SyntaxHighlighting.highlighter = 'CodeRay'
|
90
|
+
|
91
|
+
class UnifiedDiff < Array
|
92
|
+
attr_reader :diff_type, :diff_style
|
93
|
+
|
94
|
+
def initialize(diff, options={})
|
95
|
+
options.assert_valid_keys(:type, :style, :max_lines)
|
96
|
+
diff = diff.split("\n") if diff.is_a?(String)
|
97
|
+
@diff_type = options[:type] || 'inline'
|
98
|
+
@diff_style = options[:style]
|
99
|
+
lines = 0
|
100
|
+
@truncated = false
|
101
|
+
diff_table = DiffTable.new(diff_type, diff_style)
|
102
|
+
diff.each do |line_raw|
|
103
|
+
line = Svn::CodesetUtil.to_utf8_by_setting(line_raw)
|
104
|
+
unless diff_table.add_line(line)
|
105
|
+
self << diff_table if diff_table.length > 0
|
106
|
+
diff_table = DiffTable.new(diff_type, diff_style)
|
107
|
+
end
|
108
|
+
lines += 1
|
109
|
+
if options[:max_lines] && lines > options[:max_lines]
|
110
|
+
@truncated = true
|
111
|
+
break
|
112
|
+
end
|
113
|
+
end
|
114
|
+
self << diff_table unless diff_table.empty?
|
115
|
+
self
|
116
|
+
end
|
117
|
+
def truncated?; @truncated; end
|
118
|
+
end
|
119
|
+
|
120
|
+
# Class that represents a file diff
|
121
|
+
class DiffTable < Array
|
122
|
+
attr_reader :file_name
|
123
|
+
def initialize(type="inline", style=nil)
|
124
|
+
@parsing = false
|
125
|
+
@added = 0
|
126
|
+
@removed = 0
|
127
|
+
@type = type
|
128
|
+
@style = style
|
129
|
+
@file_name = nil
|
130
|
+
@git_diff = false
|
131
|
+
end
|
132
|
+
|
133
|
+
def add_line(line)
|
134
|
+
unless @parsing
|
135
|
+
if line =~ /^(---|\+\+\+) (.*)$/
|
136
|
+
self.file_name = $2
|
137
|
+
elsif line =~ /^@@ (\+|\-)(\d+)(,\d+)? (\+|\-)(\d+)(,\d+)? @@/
|
138
|
+
@line_num_l = $2.to_i
|
139
|
+
@line_num_r = $5.to_i
|
140
|
+
@parsing = true
|
141
|
+
end
|
142
|
+
else
|
143
|
+
if line =~ %r{^[^\+\-\s@\\]}
|
144
|
+
@parsing = false
|
145
|
+
return false
|
146
|
+
elsif line =~ /^@@ (\+|\-)(\d+)(,\d+)? (\+|\-)(\d+)(,\d+)? @@/
|
147
|
+
@line_num_l = $2.to_i
|
148
|
+
@line_num_r = $5.to_i
|
149
|
+
else
|
150
|
+
parse_line(line, @type)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
return true
|
154
|
+
end
|
155
|
+
def each_line
|
156
|
+
prev_line_left, prev_line_right = nil, nil
|
157
|
+
each do |line|
|
158
|
+
spacing = prev_line_left && prev_line_right && (line.nb_line_left != prev_line_left+1) && (line.nb_line_right != prev_line_right+1)
|
159
|
+
yield spacing, line
|
160
|
+
prev_line_left = line.nb_line_left.to_i if line.nb_line_left.to_i > 0
|
161
|
+
prev_line_right = line.nb_line_right.to_i if line.nb_line_right.to_i > 0
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def inspect
|
166
|
+
puts '### DIFF TABLE ###'
|
167
|
+
puts "file : #{file_name}"
|
168
|
+
self.each do |d|
|
169
|
+
d.inspect
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
private
|
174
|
+
|
175
|
+
def file_name=(arg)
|
176
|
+
both_git_diff = false
|
177
|
+
if file_name.nil?
|
178
|
+
@git_diff = true if arg =~ %r{^(a/|/dev/null)}
|
179
|
+
else
|
180
|
+
both_git_diff = (@git_diff && arg =~ %r{^(b/|/dev/null)})
|
181
|
+
end
|
182
|
+
if both_git_diff
|
183
|
+
if file_name && arg == "/dev/null"
|
184
|
+
# keep the original file name
|
185
|
+
@file_name = file_name.sub(%r{^a/}, '')
|
186
|
+
else
|
187
|
+
# remove leading b/
|
188
|
+
@file_name = arg.sub(%r{^b/}, '')
|
189
|
+
end
|
190
|
+
elsif @style == "Subversion"
|
191
|
+
# removing trailing "(revision nn)"
|
192
|
+
@file_name = arg.sub(%r{\t+\(.*\)$}, '')
|
193
|
+
else
|
194
|
+
@file_name = arg
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def diff_for_added_line
|
199
|
+
if @type == 'sbs' && @removed > 0 && @added < @removed
|
200
|
+
self[-(@removed - @added)]
|
201
|
+
else
|
202
|
+
diff = Diff.new
|
203
|
+
self << diff
|
204
|
+
diff
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def parse_line(line, type="inline")
|
209
|
+
if line[0, 1] == "+"
|
210
|
+
diff = diff_for_added_line
|
211
|
+
diff.line_right = line[1..-1]
|
212
|
+
diff.nb_line_right = @line_num_r
|
213
|
+
diff.type_diff_right = 'diff_in'
|
214
|
+
@line_num_r += 1
|
215
|
+
@added += 1
|
216
|
+
true
|
217
|
+
elsif line[0, 1] == "-"
|
218
|
+
diff = Diff.new
|
219
|
+
diff.line_left = line[1..-1]
|
220
|
+
diff.nb_line_left = @line_num_l
|
221
|
+
diff.type_diff_left = 'diff_out'
|
222
|
+
self << diff
|
223
|
+
@line_num_l += 1
|
224
|
+
@removed += 1
|
225
|
+
true
|
226
|
+
else
|
227
|
+
write_offsets
|
228
|
+
if line[0, 1] =~ /\s/
|
229
|
+
diff = Diff.new
|
230
|
+
diff.line_right = line[1..-1]
|
231
|
+
diff.nb_line_right = @line_num_r
|
232
|
+
diff.line_left = line[1..-1]
|
233
|
+
diff.nb_line_left = @line_num_l
|
234
|
+
self << diff
|
235
|
+
@line_num_l += 1
|
236
|
+
@line_num_r += 1
|
237
|
+
true
|
238
|
+
elsif line[0, 1] = "\\"
|
239
|
+
true
|
240
|
+
else
|
241
|
+
false
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
def write_offsets
|
247
|
+
if @added > 0 && @added == @removed
|
248
|
+
@added.times do |i|
|
249
|
+
line = self[-(1 + i)]
|
250
|
+
removed = (@type == 'sbs') ? line : self[-(1 + @added + i)]
|
251
|
+
offsets = offsets(removed.line_left, line.line_right)
|
252
|
+
removed.offsets = line.offsets = offsets
|
253
|
+
end
|
254
|
+
end
|
255
|
+
@added = 0
|
256
|
+
@removed = 0
|
257
|
+
end
|
258
|
+
|
259
|
+
def offsets(line_left, line_right)
|
260
|
+
if line_left.present? && line_right.present? && line_left != line_right
|
261
|
+
max = [line_left.size, line_right.size].min
|
262
|
+
starting = 0
|
263
|
+
while starting < max && line_left[starting] == line_right[starting]
|
264
|
+
starting += 1
|
265
|
+
end
|
266
|
+
while line_left[starting].ord.between?(128, 191) && starting > 0
|
267
|
+
starting -= 1
|
268
|
+
end
|
269
|
+
ending = -1
|
270
|
+
while ending >= -(max - starting) && line_left[ending] == line_right[ending]
|
271
|
+
ending -= 1
|
272
|
+
end
|
273
|
+
while line_left[ending].ord.between?(128, 191) && ending > -1
|
274
|
+
ending -= 1
|
275
|
+
end
|
276
|
+
unless starting == 0 && ending == -1
|
277
|
+
[starting, ending]
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
# A line of diff
|
284
|
+
class Diff
|
285
|
+
attr_accessor :nb_line_left
|
286
|
+
attr_accessor :line_left
|
287
|
+
attr_accessor :nb_line_right
|
288
|
+
attr_accessor :line_right
|
289
|
+
attr_accessor :type_diff_right
|
290
|
+
attr_accessor :type_diff_left
|
291
|
+
attr_accessor :offsets
|
292
|
+
|
293
|
+
def initialize()
|
294
|
+
self.nb_line_left = ''
|
295
|
+
self.nb_line_right = ''
|
296
|
+
self.line_left = ''
|
297
|
+
self.line_right = ''
|
298
|
+
self.type_diff_right = ''
|
299
|
+
self.type_diff_left = ''
|
300
|
+
end
|
301
|
+
|
302
|
+
def type_diff
|
303
|
+
type_diff_right == 'diff_in' ? type_diff_right : type_diff_left
|
304
|
+
end
|
305
|
+
|
306
|
+
def line
|
307
|
+
type_diff_right == 'diff_in' ? line_right : line_left
|
308
|
+
end
|
309
|
+
|
310
|
+
def html_line_left
|
311
|
+
line_to_html(line_left, offsets)
|
312
|
+
end
|
313
|
+
|
314
|
+
def html_line_right
|
315
|
+
line_to_html(line_right, offsets)
|
316
|
+
end
|
317
|
+
|
318
|
+
def html_line
|
319
|
+
line_to_html(line, offsets)
|
320
|
+
end
|
321
|
+
|
322
|
+
def inspect
|
323
|
+
puts '### Start Line Diff ###'
|
324
|
+
puts self.nb_line_left
|
325
|
+
puts self.line_left
|
326
|
+
puts self.nb_line_right
|
327
|
+
puts self.line_right
|
328
|
+
end
|
329
|
+
|
330
|
+
private
|
331
|
+
|
332
|
+
def line_to_html(line, offsets)
|
333
|
+
html = line_to_html_raw(line, offsets)
|
334
|
+
html.force_encoding('UTF-8') if html.respond_to?(:force_encoding)
|
335
|
+
html
|
336
|
+
end
|
337
|
+
|
338
|
+
def line_to_html_raw(line, offsets)
|
339
|
+
if offsets
|
340
|
+
s = ''
|
341
|
+
unless offsets.first == 0
|
342
|
+
s << CGI.escapeHTML(line[0..offsets.first-1])
|
343
|
+
end
|
344
|
+
s << '<span>' + CGI.escapeHTML(line[offsets.first..offsets.last]) + '</span>'
|
345
|
+
unless offsets.last == -1
|
346
|
+
s << CGI.escapeHTML(line[offsets.last+1..-1])
|
347
|
+
end
|
348
|
+
s
|
349
|
+
else
|
350
|
+
CGI.escapeHTML(line)
|
351
|
+
end
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
module CodesetUtil
|
356
|
+
|
357
|
+
def self.replace_invalid_utf8(str)
|
358
|
+
return str if str.nil?
|
359
|
+
if str.respond_to?(:force_encoding)
|
360
|
+
str.force_encoding('UTF-8')
|
361
|
+
if ! str.valid_encoding?
|
362
|
+
str = str.encode("US-ASCII", :invalid => :replace,
|
363
|
+
:undef => :replace, :replace => '?').encode("UTF-8")
|
364
|
+
end
|
365
|
+
elsif RUBY_PLATFORM == 'java'
|
366
|
+
begin
|
367
|
+
ic = Iconv.new('UTF-8', 'UTF-8')
|
368
|
+
str = ic.iconv(str)
|
369
|
+
rescue
|
370
|
+
str = str.gsub(%r{[^\r\n\t\x20-\x7e]}, '?')
|
371
|
+
end
|
372
|
+
else
|
373
|
+
ic = Iconv.new('UTF-8', 'UTF-8')
|
374
|
+
txtar = ""
|
375
|
+
begin
|
376
|
+
txtar += ic.iconv(str)
|
377
|
+
rescue Iconv::IllegalSequence
|
378
|
+
txtar += $!.success
|
379
|
+
str = '?' + $!.failed[1,$!.failed.length]
|
380
|
+
retry
|
381
|
+
rescue
|
382
|
+
txtar += $!.success
|
383
|
+
end
|
384
|
+
str = txtar
|
385
|
+
end
|
386
|
+
str
|
387
|
+
end
|
388
|
+
|
389
|
+
def self.to_utf8(str, encoding)
|
390
|
+
return str if str.nil?
|
391
|
+
str.force_encoding("ASCII-8BIT") if str.respond_to?(:force_encoding)
|
392
|
+
if str.empty?
|
393
|
+
str.force_encoding("UTF-8") if str.respond_to?(:force_encoding)
|
394
|
+
return str
|
395
|
+
end
|
396
|
+
enc = encoding.blank? ? "UTF-8" : encoding
|
397
|
+
if str.respond_to?(:force_encoding)
|
398
|
+
if enc.upcase != "UTF-8"
|
399
|
+
str.force_encoding(enc)
|
400
|
+
str = str.encode("UTF-8", :invalid => :replace,
|
401
|
+
:undef => :replace, :replace => '?')
|
402
|
+
else
|
403
|
+
str.force_encoding("UTF-8")
|
404
|
+
if ! str.valid_encoding?
|
405
|
+
str = str.encode("US-ASCII", :invalid => :replace,
|
406
|
+
:undef => :replace, :replace => '?').encode("UTF-8")
|
407
|
+
end
|
408
|
+
end
|
409
|
+
elsif RUBY_PLATFORM == 'java'
|
410
|
+
begin
|
411
|
+
ic = Iconv.new('UTF-8', enc)
|
412
|
+
str = ic.iconv(str)
|
413
|
+
rescue
|
414
|
+
str = str.gsub(%r{[^\r\n\t\x20-\x7e]}, '?')
|
415
|
+
end
|
416
|
+
else
|
417
|
+
ic = Iconv.new('UTF-8', enc)
|
418
|
+
txtar = ""
|
419
|
+
begin
|
420
|
+
txtar += ic.iconv(str)
|
421
|
+
rescue Iconv::IllegalSequence
|
422
|
+
txtar += $!.success
|
423
|
+
str = '?' + $!.failed[1,$!.failed.length]
|
424
|
+
retry
|
425
|
+
rescue
|
426
|
+
txtar += $!.success
|
427
|
+
end
|
428
|
+
str = txtar
|
429
|
+
end
|
430
|
+
str
|
431
|
+
end
|
432
|
+
|
433
|
+
def self.to_utf8_by_setting(str)
|
434
|
+
return str if str.nil?
|
435
|
+
str = self.to_utf8_by_setting_internal(str)
|
436
|
+
if str.respond_to?(:force_encoding)
|
437
|
+
str.force_encoding('UTF-8')
|
438
|
+
end
|
439
|
+
str
|
440
|
+
end
|
441
|
+
|
442
|
+
def self.to_utf8_by_setting_internal(str)
|
443
|
+
return str if str.nil?
|
444
|
+
if str.respond_to?(:force_encoding)
|
445
|
+
str.force_encoding('ASCII-8BIT')
|
446
|
+
end
|
447
|
+
return str if str.empty?
|
448
|
+
return str if /\A[\r\n\t\x20-\x7e]*\Z/n.match(str) # for us-ascii
|
449
|
+
if str.respond_to?(:force_encoding)
|
450
|
+
str.force_encoding('UTF-8')
|
451
|
+
end
|
452
|
+
str = self.replace_invalid_utf8(str)
|
453
|
+
if str.respond_to?(:force_encoding)
|
454
|
+
str.force_encoding('UTF-8')
|
455
|
+
end
|
456
|
+
str
|
457
|
+
end
|
458
|
+
|
459
|
+
def self.from_utf8(str, encoding)
|
460
|
+
str ||= ''
|
461
|
+
if str.respond_to?(:force_encoding)
|
462
|
+
str.force_encoding('UTF-8')
|
463
|
+
if encoding.upcase != 'UTF-8'
|
464
|
+
str = str.encode(encoding, :invalid => :replace,
|
465
|
+
:undef => :replace, :replace => '?')
|
466
|
+
else
|
467
|
+
str = self.replace_invalid_utf8(str)
|
468
|
+
end
|
469
|
+
elsif RUBY_PLATFORM == 'java'
|
470
|
+
begin
|
471
|
+
ic = Iconv.new(encoding, 'UTF-8')
|
472
|
+
str = ic.iconv(str)
|
473
|
+
rescue
|
474
|
+
str = str.gsub(%r{[^\r\n\t\x20-\x7e]}, '?')
|
475
|
+
end
|
476
|
+
else
|
477
|
+
ic = Iconv.new(encoding, 'UTF-8')
|
478
|
+
txtar = ""
|
479
|
+
begin
|
480
|
+
txtar += ic.iconv(str)
|
481
|
+
rescue Iconv::IllegalSequence
|
482
|
+
txtar += $!.success
|
483
|
+
str = '?' + $!.failed[1, $!.failed.length]
|
484
|
+
retry
|
485
|
+
rescue
|
486
|
+
txtar += $!.success
|
487
|
+
end
|
488
|
+
str = txtar
|
489
|
+
end
|
490
|
+
end
|
491
|
+
end
|
492
|
+
end
|