为什么我在 Rails 2 中使用 vpim 时遇到编码错误?

发布于 2024-11-14 14:08:41 字数 2204 浏览 3 评论 0原文

我收到以下错误:

Vpim::InvalidEncodingError ([email protected]):
2011-06-07T01:37:06+00:00 app[web.1]:   .bundle/gems/ruby/1.8/gems/vpim-0.695/lib/vpim/field.rb:110:in `decode0'

它对于其他 vcard 工作正常。数据看起来是正确的——它应该是一封电子邮件:

这是一个示例电子名片,当有电子邮件时它就会爆炸……我所做的修复方法是手动删除第二封电子邮件,但这很痛苦:

BEGIN:VCARD
VERSION:2.1
N:Roberts;Paul;;;
FN:Paul Roberts
ORG:Sonoma Technology Inc
TITLE:EVP Business Dev/Chief Scientific Officer
TEL;WORK;VOICE:707-665-9900
TEL;WORK;FAX:707-665-9800
ADR;WORK;ENCODING=QUOTED-PRINTABLE:;;1455 N McDowell Blvd Suite D;Petaluma;CA;94954;USA
LABEL;WORK;ENCODING=QUOTED-PRINTABLE:1455 N McDowell Blvd Suite D=0D=0APetaluma, CA 94954=0D=0AUSA
URL:http://www.sonomatech.com
URL:http://www.sonomatech.com
EMAIL;PREF;INTERNET:[email protected]
[email protected]
NOTE;ENCODING=QUOTED-PRINTABLE:=0D=0A Data provided by Lead411,  http://www.lead411.com/=0D=0A =0D=0A
END:VCARD

这是我的使用回形针和 vpim 的控制器:

 68      unless @contact.vcard.path.blank?
 69 
 70        paperclip_vcard = File.new(@contact.vcard.path)
 71 
 72       # try to scrub the vcard
 73        scrub_vcf(paperclip_vcard)
 74 
 75        @vcard = Vpim::Vcard.decode(paperclip_vcard).first
 76        @contact.title = @vcard.title
 77        @contact.email = @vcard.email
 78        @contact.first_name = @vcard.name.given
 79        @contact.last_name = @vcard.name.family
 80        @contact.phone = @vcard.telephones[0]
 81        @contact.fax = @vcard.telephones[1]
 82 
 83        @contact.address.street1 = @vcard.address.street
 84        @contact.address.city = @vcard.address.locality
 85        @contact.address.state = @vcard.address.region
 86        @contact.address.zip = @vcard.address.postalcode
 87        @contact.company_name = @vcard.org.fetch(0)
 88 
 89     end

I get the following error:

Vpim::InvalidEncodingError ([email protected]):
2011-06-07T01:37:06+00:00 app[web.1]:   .bundle/gems/ruby/1.8/gems/vpim-0.695/lib/vpim/field.rb:110:in `decode0'

It has worked fine for other vcards. And the data looks right -- it should be an email:

Here is a sample vcard that blows up when there's an email...what I"ve done to fix it is manually remove the second email, but that's a pain:

BEGIN:VCARD
VERSION:2.1
N:Roberts;Paul;;;
FN:Paul Roberts
ORG:Sonoma Technology Inc
TITLE:EVP Business Dev/Chief Scientific Officer
TEL;WORK;VOICE:707-665-9900
TEL;WORK;FAX:707-665-9800
ADR;WORK;ENCODING=QUOTED-PRINTABLE:;;1455 N McDowell Blvd Suite D;Petaluma;CA;94954;USA
LABEL;WORK;ENCODING=QUOTED-PRINTABLE:1455 N McDowell Blvd Suite D=0D=0APetaluma, CA 94954=0D=0AUSA
URL:http://www.sonomatech.com
URL:http://www.sonomatech.com
EMAIL;PREF;INTERNET:[email protected]
[email protected]
NOTE;ENCODING=QUOTED-PRINTABLE:=0D=0A Data provided by Lead411,  http://www.lead411.com/=0D=0A =0D=0A
END:VCARD

Here's my controller using paperclip and vpim:

 68      unless @contact.vcard.path.blank?
 69 
 70        paperclip_vcard = File.new(@contact.vcard.path)
 71 
 72       # try to scrub the vcard
 73        scrub_vcf(paperclip_vcard)
 74 
 75        @vcard = Vpim::Vcard.decode(paperclip_vcard).first
 76        @contact.title = @vcard.title
 77        @contact.email = @vcard.email
 78        @contact.first_name = @vcard.name.given
 79        @contact.last_name = @vcard.name.family
 80        @contact.phone = @vcard.telephones[0]
 81        @contact.fax = @vcard.telephones[1]
 82 
 83        @contact.address.street1 = @vcard.address.street
 84        @contact.address.city = @vcard.address.locality
 85        @contact.address.state = @vcard.address.region
 86        @contact.address.zip = @vcard.address.postalcode
 87        @contact.company_name = @vcard.org.fetch(0)
 88 
 89     end

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

合约呢 2024-11-21 14:08:41

您需要查看您的电子名片是如何创建的;第 14 行的第二封电子邮件不是有效的属性定义,这就是导致解析器出错的原因(这就是为什么如果您手动删除它,它会成功解析)。

您可以在Vcard 2.1 规范( RTF 版本的可读性要高得多,可以在此处获取。

从您提供的信息来看,这看起来不像解码端的 Vpim 的问题,而是如何您的 Vcard 已创建。如果您自己创建 Vcard,我会看看您的编码逻辑。如果您从外部来源接收它们,那么您可能需要编写一些自定义清理逻辑来删除不正确的属性定义,这样您就不必自己手动删除它们。

您应该能够通过对每一行进行快速正则表达式检查来非常轻松地完成此操作:

def scrub_vcf(vcard)
  line_arr = File.readlines(vcard)
  line_arr.delete_if { |line| line.match(/^.+\:.+$/).nil? }
  File.open(vcard, "w") do |f| 
    line_arr.each{|line| f.puts(line)}
  end
end
# use the scrubbed vcf with vpim

当然,将其保留在数组中可能比将其写回到文件中更快,仅供参考。

希望有帮助。


更新:如果您不想保留文件,可以返回一个字符串,Vpim 可以解码 而不是文件:

def scrub_vcf(vcard)
  line_arr = File.readlines(vcard)
  line_arr.delete_if { |line| line.match(/^.+\:.+$/).nil? }
  return line_arr.join
end
# use the scrubbed vcf with vpim #=> Vpim::Vcard.decode(scrub_vcf(vcard))

请注意,在运行 ruby​​ 时,我在使用带有 Vpim::Vcard.decode 的字符串时遇到了问题1.9.x 中,由于 String 类不再具有 each 方法。不过,Ruby 1.8.7 运行良好。 Vpim 看起来自 2008/2009 年以来就没有升级过,所以它可能没有升级到与 ruby​​ 1.9.x 一起使用。


再次更新:这是更新后的 Vpim 版本,可与 ruby​​ 1.9.x 一起使用(准确修复了我之前遇到的问题):https://github.com/sam-github/vpim

You need to look at how your Vcards are being created; the second email on line 14 isn't a valid property definition, which is what's causing the parser to screw up (and which is why it parses successfully if you manually delete it).

You can read about the property definition in Section 2 in the Vcard 2.1 specification (the RTF version–which is far more readable–is available here).

From the information you provided, this doesn't look like a problem with Vpim on the decoding side, but rather how your Vcards are created. If you're creating the Vcards yourself, I'd take a look at your encoding logic. If you're receiving them from outside sources, then you might want to write some custom scrubbing logic to get rid of improper property definitions, so you don't have to manually remove them yourself.

You should be able to do this quite easily with a quick regex check on each line:

def scrub_vcf(vcard)
  line_arr = File.readlines(vcard)
  line_arr.delete_if { |line| line.match(/^.+\:.+$/).nil? }
  File.open(vcard, "w") do |f| 
    line_arr.each{|line| f.puts(line)}
  end
end
# use the scrubbed vcf with vpim

Of course, it would probably be quicker to keep this in an array rather than writing it back out to a file, FYI.

Hope that helps.


UPDATE: If you don't want to keep the file, you can return a string, which Vpim can decode instead of a file:

def scrub_vcf(vcard)
  line_arr = File.readlines(vcard)
  line_arr.delete_if { |line| line.match(/^.+\:.+$/).nil? }
  return line_arr.join
end
# use the scrubbed vcf with vpim #=> Vpim::Vcard.decode(scrub_vcf(vcard))

Note that I ran into problems with using a String with Vpim::Vcard.decode when running ruby 1.9.x, due to the fact that the String class no longer has an each method. Ruby 1.8.7 works fine, though. Vpim looks like it hasn't been upgraded since 2008/2009, so it's probably not been upgraded for use with ruby 1.9.x.


UPDATE AGAIN: Here's a version of Vpim updated for use with ruby 1.9.x (fixes precisely the issue I ran into earlier): https://github.com/sam-github/vpim

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文