Quoting timcharper at gmail.com, on Tue, Jul 31, 2007 at 11:10:23PM -0600:> Sam, > > Here''s a patch of the fixes I applied to get it to read the outlook card, > plus a copy of the card. Hope these may be of some use there!Thanks Tim, but I think your patch will break valid vcards. Also, the card you sent me is not a valid vcard. I suspect that somehow in the process of extracting it from email, something is being damaged. The problem is here: ---- LABEL;WORK;ENCODING=QUOTED-PRINTABLE:734 Business Street=0D=0AProvo, UT 84601 ---- It appears Provo was intended to be part of the previous field, doesn''t it? But for that to be true the line would have to start with a single whitespace character, such as: ---- LABEL;WORK;ENCODING=QUOTED-PRINTABLE:734 Business Street=0D=0A Provo, UT 84601 ---- Thats how fields are folded in vcard. If you modify your .vcf file in the several lines where this error occurs, you will see it parses OK. Also, note that your patch does a blanket conversion on the entire vcard! If I had a company named: ORG:sam=11monkeys your patch would treat the =11 as quoted printable. The only thing that is supposed to be quoted-printable is the value of the LABEL field! But! We still aren''t out of the woods. If you take: ---- LABEL;WORK;ENCODING=QUOTED-PRINTABLE:734 Business Street=0D=0A Provo, UT 84601 ---- Apply vcard unfolding, you will get: ---- LABEL;WORK;ENCODING=QUOTED-PRINTABLE:734 Business Street=0D=0A=Provo, UT 84601 ---- Unfotunately, there is a problem here. That lone = at the end of the line: irb(main):001:0> "734 Business Street=0D=0A=Provo, UT 84601".unpack(''M*'') => ["734 Business Street\r\n"] I really don''t know what to make of this file. An = at the end of the line is a "soft-line-break" It means, unfold the following line. But that doesn''t make any sense here... It looks to me like the original vcard looked like: ---- LABEL;WORK;ENCODING=QUOTED-PRINTABLE:734 Business Street=0D=0AProvo, UT 84601 ---- (note there isn''t an extra "=") Some mail transport software then did some kind of wrapping on it, and marked it as wrapped: ---- LABEL;WORK;ENCODING=QUOTED-PRINTABLE:734 Business Street=0D=0AProvo, UT 84601 ---- And then somehow you got that data as if it was a valid vcard. Anyhow, the long and the short of it is that if you can''t arrange to get undamaged vcards, you''ll have to patch them up outside of vpim. I''d like to support broken vcards if possible, but not at the price of misinterpreting valid vcards. My suggestion is to do something like card.gsub(/=\n/, "\n ") Will patch up your vcard so vpim accepts it. Cheers, Sam Btw, I don''t understand something in your patch:> Index: lib/vpim/rfc2425.rb > ==================================================================> --- lib/vpim/rfc2425.rb (revision 747) > +++ lib/vpim/rfc2425.rb (revision 748) > @@ -1,3 +1,4 @@ > + > =begin > Copyright (C) 2006 Sam Roberts > > @@ -228,7 +229,7 @@ > end > > def Vpim.encode_text(v) #:nodoc: > - v.to_str.gsub(/([.\n])/) do > + v.to_s.gsub(/([.\n])/) dov is supposed to be a string, or something duck-typed to be a string. Any object that believes itself to be a string implements #to_str, a convention used in ruby itself: irb(main):006:0> class S; def to_str; "hi" end end => nil irb(main):007:0> "hi" + Object.new TypeError: can''t convert Object into String from (irb):7:in `+'' from (irb):7 irb(main):008:0> "hi" + S.new => "hihi" #to_s is a cast operator, it will coerce something into some kind of string form, but probably not one you want! irb(main):002:0> Object.new.to_s => "#<Object:0x572920>" irb(main):003:0> Object.new.to_str NoMethodError: undefined method `to_str'' for #<Object:0x56e4ec> from (irb):3 irb(main):005:0> File.open("_", "w").to_s => "#<File:0x563560>" With this change pretty much any ruby object would just silently show up as weirdo text.> case $1 > when "\n" > "\\n" > @@ -242,10 +243,10 @@ > > # v is an Array of String, or just a single String > def Vpim.encode_text_list(v, sep = ",") #:nodoc: > - begin > - v.to_ary.map{ |t| Vpim.encode_text(t) }.join(sep) > - rescue > - Vpim.encode_text(v)Ditto for my use of #to_ary, anything that is "array-like" implements #to_ary, your change below checks against an explicit type, anti-duck-typing.> + if Array===v > + v.map{ |t| Vpim.encode_text(t) }.join(sep) > + else > + Vpim.encode_text(v.to_s) > end > end > > Index: lib/vpim/dirinfo.rb > ==================================================================> --- lib/vpim/dirinfo.rb (revision 747) > +++ lib/vpim/dirinfo.rb (revision 748) > @@ -71,7 +71,9 @@ > else > raise ArgumentError, "DirectoryInfo cannot be created from a #{card.type}" > end > - > + # patch to fix outlook vcf cards from failing to load > + string.gsub!("=0D=0A=\n", "=0D=0A") > + string.gsub!("=0D=0A", "=0A") # change \r\n to \n > fields = Vpim.decode(string) > > new(fields) > Index: lib/vpim/vcard.rb > ==================================================================> --- lib/vpim/vcard.rb (revision 747) > +++ lib/vpim/vcard.rb (revision 748) > @@ -386,7 +386,7 @@ > # Override the attr reader to make it dynamic > remove_method :formatted > def formatted #:nodoc: > - f = [ @prefix, @given, @additional, @family ].map{|i| i == '''' ? nil : i.strip}.compact.join('' '') > + f = [ @prefix, @given, @additional, @family ].map{|i| (i||"").strip }.select{|x| !x.blank? }.join('' '') > if @suffix != '''' > f << '', '' << @suffix > end > @@ -410,7 +410,7 @@ > > def encode #:nodoc: > Vpim::DirectoryInfo::Field.create(''N'', > - Vpim.encode_text_list([ @family, @given, @additional, @prefix, @suffix ].map{|n| n.strip}, '';'') > + Vpim.encode_text_list([ @family, @given, @additional, @prefix, @suffix ].map{|n| (n||"").strip}, '';'') > ) > end > def encode_fn #:nodoc: > @@ -1090,7 +1090,7 @@ > end > @card << Vpim::DirectoryInfo::Field.create( ''FN'', fullname ); > end > - > + > # Set the name fields, N and FN. > # > # Attributes of +name+ are: > @@ -1175,6 +1175,21 @@ > > @card << Vpim::DirectoryInfo::Field.create( ''NICKNAME'', nickname ); > end > + > + > + { > + :job_title => "TITLE", > + :company_name => "ORG", > + :revision => "REV" > + }.each_pair{|method_name, vcard_index| > + class_eval <<-EOF, __FILE__, __LINE__ > + def #{method_name}=(value) > + delete_if { |l| l.name == ''#{vcard_index}'' } > + > + @card << Vpim::DirectoryInfo::Field.create( ''#{vcard_index}'', value); > + end > + EOF > + } > > # Add a birthday field, BDAY. > #
Tijn Schuurmans - Soocial.com
2007-Oct-01 11:46 UTC
[Vpim-talk] VPIM - outlook contact failed to parse
Dear list, Please find attached a patch to rfc2425.rb to handle line breaks in quoted printable fields; like Outlook stores vcards. Note that I did not have to change the unfolding code for this. I believe this patch does not interfere with the parsing of valid vcards. It should only enable vpim to load an invalid vcard that is slightly diverging from the standard in a well defined way. I hope you''ll find it useful, I''m looking forward to reading your remarks. -- Best regards, Tijn Schuurmans - Soocial.com PS. My previous message from a week ago never arrived at the mailinglist. What could have happened? -------------- next part -------------- A non-text attachment was scrubbed... Name: handle_borked_quoted_printables.patch Type: text/x-diff Size: 1788 bytes Desc: not available Url : http://rubyforge.org/pipermail/vpim-talk/attachments/20071001/dd01c7b3/attachment.bin