vcard2n3.rb

# quick'n'dirty vCard to N3 (Turtle) converter
#
# wydaje się, że działa OK na pliku VCF
# wyeksportowanym z telefonu Sony Ericsson
#
# ver.1.0
# (c) MiMaS 01.2006


we = ARGV.first ? File.open(ARGV.shift) : $stdin
wy = ARGV.first ? File.open(ARGV.shift, 'w') : $stdout

require 'iconv'
$ic = Iconv.new('utf-8', 'utf-7')
# kodowanie znaków w mojej książce adr. i tak zawsze jest UTF-7
# chociaż teoretycznie w liniach zawierających teksty kodowane
# przed ':' może być coś innego niż ';CHARSET=UTF-7'
def cleartext(t)
  $ic.iconv(t.strip)
end 

contacts = Hash.new
id = 0
we.readlines.each do |line|
  case line 
  when /^BEGIN:VCARD/
    contacts[id] = Hash.new
    contacts[id]["TEL"] = Array.new 
  when /^N([^:]*):(.*);(.+)/
    contacts[id]["Given"] = cleartext($2)
    contacts[id]["Family"] = cleartext($3)
  when /^TEL([;])?(.{0,4})?:([+\d#]+)/
    contacts[id]["TEL"].push( {
      "type" => $2.strip,
      "value" => $3} )
  when /^URL(.*):(.+)/
    u = $2.strip
    if u
      if u.index(/^http:/) 
        contacts[id]["URL"] = u
      else
        contacts[id]["URL"] = "http://" + u
      end
    end
  when /^ADR(.*):;;(.*);(.*);(.*);(.*);(.*)/
    contacts[id]["ADR"] = {
      "street-address" => cleartext($2), 
      "locality" => cleartext($3), 
      "region" => cleartext($4), 
      "postal-code" => $5, 
      "country-name" => cleartext($6) }
  when /^(EMAIL|TITLE|ORG|NOTE)([^:]*):(.+)/
    contacts[id][$1] = cleartext($3)
  when /^END:VCARD/
    id += 1
  end
end

$ic.close


wy << "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n"
wy << "@prefix v: <http://nwalsh.com/rdf/vCard#> .\n"
wy << "\n"

contacts.each do |id, c|
  about = Iconv.iconv('utf-7', 'utf-8', (c["Family"]+c["Given"]).tr(" #+-=()[]<>.,_",""))

  wy << "<http://mimas.ceti.pl/pim##{about}> rdf:type v:VCard; "
  wy << "v:fn \"#{c["Family"]} #{c["Given"]}\"; "
  wy << "v:n [a v:Name; v:family-name \"#{c["Family"]}\"; v:given-name \"#{c["Given"]}\" ]"

  t = {"HOME"=>"homeTel",
       "WORK"=>"workTel",
       "CELL"=>"mobileTel",
       "FAX"=>"fax",
       ""=>"unlabeledTel"}
  c["TEL"].each do |tel|
    wy << "; v:#{t[tel["type"]]} <tel:#{tel["value"]}>"
  end
  if c["EMAIL"]
    wy << "; v:email <mailto:#{c["EMAIL"]}>"
  end
  if c["URL"]
    wy << "; v:url <#{c["URL"]}>"
  end
  if c["ADR"]
    wy << "; v:adr [a v:Address"
    c["ADR"].each_key do |k|
      if c["ADR"][k] && !c["ADR"][k].empty?
        wy << "; v:#{k} \"#{c["ADR"][k]}\""
      end
    end
    wy << "]"
  end
  if c["TITLE"]
    wy << "; v:title \"#{c["TITLE"]}\""
  end
  if c["ORG"]
    wy << "; v:org [a v:Organization; v:organization-name \"#{c["ORG"]}\"]"
  end
  if c["NOTE"]
    wy << "; v:note \"#{c["NOTE"]}\""
  end
  wy << " .\n"
end

if we.instance_of? File
  we.close
end
if wy.instance_of? File
  wy.close
end