mozldif2n3.rb

# quick'n'dirty (MozillaThunderbird)LDIF to N3 (Turtle) converter
#
# wydaje się, że działa OK na pliku LDIF 
# wyeksportowanym z książki adresowej Thunderbirda
#
# ver.1.0
# (c) MiMaS 01.2006


require 'iconv'

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

contacts = Hash.new
id = 0
we.readlines.each do |line|
  if line =~ /^dn:(.*)/
    id += 1
    contacts[id] = Hash.new
  elsif line =~ /^(\w+):(.*)/
    pp = $1
    vv = $2
    if !(pp == "objectclass" || pp =~ /^mozillaCustom/)
      if vv[0] == ?:
        # name:: --> base64 value
        vv = vv.gsub(/^: /,"").unpack("m*")[0]
      end
      contacts[id][pp] = vv.strip
    end
  end
end


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

contacts.each do |id, c|
  about = ""
  if c["cn"]
    about << c["cn"]
  else
    about << c["sn"].to_s << c["givenName"].to_s
  end
  if about.empty? && c["mail"] =~ /([.\w]+)@(.*)/
    about << $1
  end
  about = Iconv.iconv('utf-7', 'utf-8', about.tr(" #+-=()[]<>.,_",""))

  name = ""
  if c["cn"]
    name << c["cn"]
  else
    name << c["sn"].to_s << " " << c["givenName"].to_s
  end
  name.strip!
  if name.empty? && c["mail"]
    name << c["mail"]
  end

  wy << "<http://mimas.ceti.pl/pim##{about}> rdf:type v:VCard; v:fn \"#{name}\" "

  if c["sn"] || c["givenName"]
    wy << "; v:n [a v:Name; v:family-name \"#{c["sn"]}\"; v:given-name \"#{c["givenName"]}\" ]"
  end

  if c["mozillaNickname"]
    wy << "; foaf:nick \"#{c["mozillaNickname"]}\""
  elsif c["nsAIMid"]
    wy << "; foaf:aimChatID \"#{c["nsAIMid"]}\""
  end

  if c["mail"]
    wy << "; v:email <mailto:#{c["mail"]}>"
  end
  if c["mozillaSecondEmail"]
    wy << "; v:email <mailto:#{c["mozillaSecondEmail"]}>"
  end

  { "telephoneNumber"=>"workTel",
    "homePhone"=>"homeTel",
    "mobile"=>"mobileTel",
    "fax"=>"fax"
  }.each do |p,v|
    if c[p]
      wy << "; v:#{v} <tel:#{c[p]}>"
    end
  end

  if c["mozillaHomeStreet2"]
    c["homeStreet"] = c["homeStreet"].to_s << " " << c["mozillaHomeStreet2"].to_s
  end
  if c["homeStreet"] || c["mozillaHomeLocalityName"] || c["mozillaHomeState"] || c["mozillaHomePostalCode"] || c["mozillaHomeCountryName"]
    wy << "; v:homeAdr [a v:Address"
    { "homeStreet"=>"street-address",
      "mozillaHomeLocalityName"=>"locality",
      "mozillaHomeState"=>"region",
      "mozillaHomePostalCode"=>"postal-code",
      "mozillaHomeCountryName"=>"country-name"
    }.each do |p,v|
      if c[p]
        wy << "; v:#{v} \"#{c[p]}\""
      end
    end
    wy << "]"
  end

  if c["mozillaWorkStreet2"]
    c["street"] = c["street"].to_s << " " << c["mozillaWorkStreet2"].to_s
  end
  if c["street"] || c["l"] || c["st"] || c["postalCode"] || c["c"] 
    wy << "; v:workAdr [a v:Address"
    { "street"=>"street-address",
      "l"=>"locality",
      "st"=>"region",
      "postalCode"=>"postal-code",
      "c"=>"country-name"
    }.each do |p,v|
      if c[p]
        wy << "; v:#{v} \"#{c[p]}\""
      end
    end
    wy << "]"
  end

  if c["title"]
    wy << "; v:title \"#{c["TITLE"]}\""
  end
  if c["department"] || c["company"]
    wy << "; v:org [a v:Organization; "
    if c["department"]
      wy << "v:organization-unit \"#{c["department"]}\";"
    end
    if c["company"]
      wy << "v:organization-name \"#{c["company"]}\""
    end
    wy << "] "
  end

  if c["mozillaHomeUrl"]
    wy.write("; foaf:homepage <#{c["mozillaHomeUrl"]}> ")
  end
  if c["mozillaWorkUrl"]
    wy.write("; foaf:workplaceHomepage <#{c["mozillaWorkUrl"]}> ")
  end

  if c["description"]
    wy << "; v:note \"#{c["description"].tr("\n"," ")}\""
  end
  wy << " .\n"
end

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