Class: Virginity::Vcard21::Writer::Vcard21Line

Inherits:
Object
  • Object
show all
Defined in:
lib/virginity/vcard21/writer.rb

Defined Under Namespace

Classes: LineTooWide

Constant Summary collapse

LINE_TOO_LONG =
/[^\n\r]{76,}/

Instance Method Summary collapse

Constructor Details

#initialize(group, name, params, value) ⇒ Vcard21Line

this is probably the correct way to see if we have non-ascii in ruby1.9 we duplicate every part of a content-line so that we safely can change values



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/virginity/vcard21/writer.rb', line 14

def initialize(group, name, params, value)
  @group = group.nil? ? nil : group.dup
  @name = name.dup
  @params = Param::deep_copy(params)
  if @params.any? {|p| p.key =~ ENCODING and p.value =~ /^b$/i }
    @params.delete_if {|p| p.key =~ ENCODING and p.value =~ /^b$/i }
    @params << Param.new("ENCODING","BASE64")
  end
  if qp?
    @value = EncodingDecoding::decode_quoted_printable(@value)
    @params.delete_if {|p| p.key =~ ENCODING and p.value =~ QUOTED_PRINTABLE }
  else
    @value = value.dup
  end
  @value = "2.1" if @name == "VERSION"
end

Instance Method Details

#base64?Boolean

Returns:

  • (Boolean)


44
45
46
# File 'lib/virginity/vcard21/writer.rb', line 44

def base64?
  @params.any? { |p| Vcard21::base64_param?(p) }
end

#inspectObject



31
32
33
# File 'lib/virginity/vcard21/writer.rb', line 31

def inspect
  {:group => @group, :name => @name, :params => @params.join(', '), :value => @value}.inspect
end

#line_too_wide_for21?(line) ⇒ Boolean

Returns:

  • (Boolean)


36
37
38
# File 'lib/virginity/vcard21/writer.rb', line 36

def line_too_wide_for21?(line)
  !(line =~ LINE_TOO_LONG).nil?
end

#non_ascii?Boolean

FIXME there must be a better way to find non-ascii chars

Returns:

  • (Boolean)


49
50
51
52
53
54
# File 'lib/virginity/vcard21/writer.rb', line 49

def non_ascii?
  @value.each_byte do |b|
    return true if b > 127
  end
  false
end

#params_to_s(options = {}) ⇒ Object

param = param-name “=” param-value *(“,” param-value)



66
67
68
69
70
71
72
73
74
75
76
# File 'lib/virginity/vcard21/writer.rb', line 66

def params_to_s(options = {})
  return "" if @params.empty?
  if options[:vcard21_omit_type_if_knowntype]
    pv = @params.uniq.sort.map do |p|
      (p.key == "TYPE" and KNOWNTYPES.include? p.value) ? p.value : p.to_s
    end
    ";" + pv.join(";")
  else
    ";" + @params.uniq.sort.join(";")
  end
end

#pre_process_value!(options = {}) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/virginity/vcard21/writer.rb', line 80

def pre_process_value!(options = {})
  encoding = @params.select {|p| p.key =~ ENCODING }
  raise "vCard author is confused, #{encoding.inspect}" if encoding.size > 1
  if encoding.empty?
    if non_ascii?
      @params << Param.new("CHARSET","UTF-8")
      @params << Param.new("ENCODING","QUOTED-PRINTABLE")
    elsif @value =~ /\r|\n/
      @params << Param.new("ENCODING","QUOTED-PRINTABLE")
    elsif line_too_wide_for21?(@value) # if the value part alone already is too wide
      @params << Param.new("ENCODING","QUOTED-PRINTABLE")
    end
  else
    case encoding.first.value
    when QUOTED_PRINTABLE, EIGHT_BIT, SEVEN_BIT, BASE64
      nil
    else
      raise "unexpected encoding #{encoding.first.inspect}"
    end
  end
end

#qp?Boolean

Returns:

  • (Boolean)


40
41
42
# File 'lib/virginity/vcard21/writer.rb', line 40

def qp?
  @params.any? { |p| Vcard21::qp_param?(p) }
end

#to_s(options = {}) ⇒ Object



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/virginity/vcard21/writer.rb', line 102

def to_s(options = {})
  pre_process_value!(options)
  @params.uniq!
  line = [@group, @name].compact.join(".")
  line << params_to_s(options.merge({:vcard21_omit_type_if_knowntype => true}))
  line << ":"
  if qp?
    line << EncodingDecoding::encode_quoted_printable(@value, :initial_position => line.size) if qp?
  elsif base64?
    #Fixes::photo_folding_like_apple(@value, options.merge({:width => 70})) + "\r\n"
    # "\\0" is the matched string
    line << "\r\n" << @value.gsub(/.{70}/u, "\\0\r\n") << "\r\n"
  else
    line << @value
  end
  raise LineTooWide, "line_too_wide #{line.inspect}" if line_too_wide_for21?(line)
  line
rescue LineTooWide => e
  return line if qp? # we did all we can, let's hope the phone can read this vcard
  @params << Param.new("ENCODING","QUOTED-PRINTABLE")
  retry
end