adr2csv.pl 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #!perl
  2. #
  3. # ADR 2 CSV
  4. # Opera Mail 'adr' to Thunderbird 'csv' contacts file converter.
  5. # Version 1
  6. # by Dwayne J Pivac @ OMI Ltd.
  7. #
  8. # This program is free software: you can redistribute it and/or modify
  9. # it under the terms of the GNU General Public License as published by
  10. # the Free Software Foundation, either version 3 of the License, or
  11. # (at your option) any later version.
  12. #
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  16. # See the GNU General Public License for more details.
  17. #
  18. #
  19. use strict;
  20. use warnings;
  21. use File::Spec;
  22. my $in = ($ARGV[0]);
  23. if ( ((!$in)) || ((!-e $in)) ) {
  24. die "Usage: perl adr2csv.pl /path/to/file.adr\nError: Input file not found.\n";
  25. }
  26. # Initial output path
  27. (my $out_path = $in) =~ s/\.[^.]+$/\.csv/;
  28. # Versioning logic
  29. if ( (-e $out_path) ) {
  30. my $found = (0);
  31. my ($base, $ext) = ($out_path =~ /^(.*)\.(csv)$/);
  32. for (my $i = (1); ($i <= 99); $i++) {
  33. my $suffix = sprintf("_%02d", $i);
  34. my $test_path = ($base . $suffix . "." . $ext);
  35. if ( (!-e $test_path) ) {
  36. $out_path = ($test_path);
  37. $found = (1);
  38. last;
  39. }
  40. }
  41. if ( (!$found) ) {
  42. die "Error: Reached limit of 99 versioned files.\nPlease clean up the directory.\n";
  43. }
  44. }
  45. my %headers_map = (
  46. # Thnderbird header => Opera Mail header
  47. "01_Display Name" => "NAME",
  48. "02_Primary Email" => "MAIL",
  49. "03_Home Phone" => "PHONE",
  50. "04_Fax Number" => "FAX",
  51. "05_Web Page 1" => "URL",
  52. "06_Notes" => "DESCRIPTION",
  53. "07_Nickname" => "SHORT NAME",
  54. "08_Home Address" => "POSTALADDRESS",
  55. "09_Custom 1" => "PICTUREURL",
  56. "10_Secondary Email" => "MAIL"
  57. );
  58. # Slurp data and close input file immediately
  59. open(my $fh_in, '<', $in) or die "Could not open $in: $!";
  60. my @contact_data = (<$fh_in>);
  61. close($fh_in);
  62. open(my $fh_out, '>', $out_path) or die "Could not open $out_path: $!";
  63. my @sorted_headers = (sort(keys(%headers_map)));
  64. my @clean_headers = (map { (my $h = $_) =~ s/^\d+_(.*)/$1/; $h } @sorted_headers);
  65. print $fh_out join(",", map { qq("$_") } @clean_headers) . "\n";
  66. my %contact;
  67. my $is_contact = (0);
  68. for my $line (@contact_data) {
  69. chomp($line);
  70. $line =~ s/^\s+//;
  71. if ( ($line =~ /^#(\w+)/) ) {
  72. my $section = ($1);
  73. if ( (($is_contact)) && ((%contact)) ) {
  74. &write_row($fh_out, \%contact, \%headers_map, \@sorted_headers);
  75. }
  76. %contact = ();
  77. $is_contact = ( ($section eq 'CONTACT') ? (1) : (0) );
  78. next;
  79. }
  80. if ( (($is_contact)) && (($line =~ /^([^=]+)=(.*)/)) ) {
  81. $contact{$1} = ($2);
  82. }
  83. }
  84. # Final record check
  85. if ( (($is_contact)) && ((%contact)) ) {
  86. &write_row($fh_out, \%contact, \%headers_map, \@sorted_headers);
  87. }
  88. close($fh_out);
  89. print "Converted $in to $out_path\n";
  90. sub write_row {
  91. my ($fh, $dat, $m, $h) = (@_);
  92. my @row;
  93. for my $header (@$h) {
  94. my $adr_key = ($m->{$header});
  95. my $val = ($dat->{$adr_key} // '');
  96. $val =~ s/\x02+/\n/g;
  97. if ( ($adr_key eq 'MAIL') ) {
  98. my @emails = (split(/\n+/, $val));
  99. if ( ($header =~ /Primary/) ) {
  100. $val = ($emails[0] // '');
  101. }
  102. elsif ( ($header =~ /Secondary/) ) {
  103. $val = ($emails[1] // '');
  104. }
  105. }
  106. $val =~ s/\r\n/\n/g;
  107. $val =~ s/\r/\n/g;
  108. $val =~ s/"/""/g;
  109. push(@row, qq("$val"));
  110. }
  111. print $fh join(",", @row) . "\n";
  112. }