4
* Copyright (C) 2009 to 2011 Tim Marston <tim@ed.am>
4
* Copyright (C) 2009 to 2011 Tim Marston <edam@waxworlds.org>
6
6
* This file is part of the Import Contacts program (hereafter referred
7
7
* to as "this program"). For more information, see
8
* http://ed.am/dev/android/import-contacts
8
* http://www.waxworlds.org/edam/software/android/import-contacts
10
10
* This program is free software: you can redistribute it and/or modify
11
11
* it under the terms of the GNU General Public License as published by
38
38
import java.util.HashSet;
39
39
import java.util.Iterator;
40
40
import java.util.List;
41
import java.util.Locale;
42
41
import java.util.NoSuchElementException;
43
42
import java.util.Set;
44
43
import java.util.Vector;
45
44
import java.util.regex.Matcher;
46
45
import java.util.regex.Pattern;
48
import android.annotation.SuppressLint;
49
47
import android.content.SharedPreferences;
48
import android.provider.Contacts;
49
import android.provider.Contacts.PhonesColumns;
51
51
public class VcardImporter extends Importer
84
83
class VCardFilter implements FilenameFilter {
85
84
public boolean accept( File dir, String name ) {
86
return name.toLowerCase( Locale.US ).endsWith( ".vcf" );
85
return name.toLowerCase().endsWith( ".vcf" );
89
88
files = file.listFiles( new VCardFilter() );
570
569
// determine whether we care about this entry
571
570
final HashSet< String > interesting_fields =
572
new HashSet< String >( Arrays.asList( new String[] { "N",
573
"FN", "ORG", "TITLE", "TEL", "EMAIL", "ADR", "LABEL" }
571
new HashSet< String >( Arrays.asList( new String[]
572
{ "N", "FN", "ORG", "TITLE", "TEL", "EMAIL", "ADR" }
575
574
boolean is_interesting_field =
576
575
interesting_fields.contains( name_param_parts[ 0 ] );
578
577
// parse encoding parameter
579
578
String encoding = checkParam( name_param_parts, "ENCODING" );
580
if( encoding != null )
581
encoding = encoding.toUpperCase( Locale.US );
579
if( encoding != null ) encoding = encoding.toUpperCase();
582
580
if( is_interesting_field && encoding != null &&
583
581
!encoding.equals( "8BIT" ) &&
584
582
!encoding.equals( "QUOTED-PRINTABLE" ) )
590
588
// parse charset parameter
591
589
String charset = checkParam( name_param_parts, "CHARSET" );
592
if( charset != null )
593
charset = charset.toUpperCase( Locale.US );
590
if( charset != null ) charset = charset.toUpperCase();
594
591
if( charset != null &&
595
592
!charset.equals( "US-ASCII" ) &&
596
593
!charset.equals( "ASCII" ) &&
679
676
parseEMAIL( name_param_parts, complete_value );
680
677
else if( name_param_parts[ 0 ].equals( "ADR" ) )
681
678
parseADR( name_param_parts, complete_value );
682
else if( name_param_parts[ 0 ].equals( "LABEL" ) )
683
parseLABEL( name_param_parts, complete_value );
883
878
if( types.contains( "FAX" ) )
884
879
if( types.contains( "HOME" ) )
885
type = TYPE_FAX_HOME;
880
type = PhonesColumns.TYPE_FAX_HOME;
887
type = TYPE_FAX_WORK;
882
type = PhonesColumns.TYPE_FAX_WORK;
888
883
else if( types.contains( "CELL" ) || types.contains( "VIDEO" ) )
884
type = PhonesColumns.TYPE_MOBILE;
890
885
else if( types.contains( "PAGER" ) )
886
type = PhonesColumns.TYPE_PAGER;
892
887
else if( types.contains( "WORK" ) )
888
type = PhonesColumns.TYPE_WORK;
890
type = PhonesColumns.TYPE_HOME;
897
892
// add phone number
898
893
addNumber( value, type, is_preferred );
909
904
boolean is_preferred = types.contains( "PREF" );
911
906
if( types.contains( "WORK" ) )
907
type = Contacts.ContactMethods.TYPE_WORK;
909
type = Contacts.ContactMethods.TYPE_HOME;
916
911
addEmail( unescapeValue( value ), type, is_preferred );
940
935
Set< String > types = extractTypes( params, Arrays.asList(
941
"PREF", "WORK", "HOME" ) );
945
if( types.contains( "WORK" ) )
950
addAddress( unescapeValue( value ), type );
953
private void parseLABEL( String[] params, String value )
955
Set< String > types = extractTypes( params, Arrays.asList(
956
"PREF", "WORK", "HOME" ) );
960
if( types.contains( "WORK" ) )
936
"PREF", "WORK", "HOME", "INTERNET" ) );
940
if( types.contains( "WORK" ) )
941
type = Contacts.ContactMethods.TYPE_WORK;
943
type = Contacts.ContactMethods.TYPE_HOME;
965
945
addAddress( unescapeValue( value ), type );
980
* Amongst the params, find the value of the first, only, of any with
984
* @return a value, or null
986
959
private String checkParam( String[] params, String name )
988
String[] res = checkParams( params, name );
989
return res.length > 0? res[ 0 ] : null;
993
* Amongst the params, find the values of any with the specified name
996
* @return an array of values, or null
998
private String[] checkParams( String[] params, String name )
1000
HashSet< String > ret = new HashSet< String >();
1002
961
Pattern p = Pattern.compile(
1003
962
"^" + name + "[ \\t]*=[ \\t]*(\"?)(.*)\\1$" );
1004
963
for( int i = 0; i < params.length; i++ ) {
1005
964
Matcher m = p.matcher( params[ i ] );
1006
965
if( m.matches() )
1007
ret.add( m.group( 2 ) );
1010
return (String[]) ret.toArray( new String[ ret.size() ] );
1014
* Amongst the params, return any type values present. For v2.1 vCards,
1015
* those types are just parameters. For v3.0, they are prefixed with
1016
* "TYPE=". There may also be multiple type parameters.
1018
* @param a list of type values to look for
1019
* @return a set of present type values
1021
971
private Set< String > extractTypes( String[] params,
1022
972
List< String > valid_types )
1024
974
HashSet< String > types = new HashSet< String >();
1026
976
// get 3.0-style TYPE= param
1027
String type_params[] = checkParams( params, "TYPE" );
1028
for( int a = 0; a < type_params.length; a++ )
1030
// check for a comma-separated list of types (why? this isn't in
1032
String[] parts = type_params[ a ].split( "," );
978
if( ( type_param = checkParam( params, "TYPE" ) ) != null ) {
979
String[] parts = type_param.split( "," );
1033
980
for( int i = 0; i < parts.length; i++ )
1034
981
if( valid_types.contains( parts[ i ] ) )
1035
982
types.add( parts[ i ] );