dcb180161a25b15f70222741646ff81f1af1abcb
[claws.git] / tools / vcard2xml.py
1 #!/usr/bin/python2.2
2 # -*- coding: latin-1 -*-
3 """
4
5 Copyright © 2003 Bogdan Sumanariu <zarrok@yahoo.com>
6
7   This file is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 3 of the License, or
10   (at your option) any later version.
11    
12   This program is distributed in the hope that it will be useful, but
13   WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15   General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program; if not, write to the Free Software
19   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
21   script name : evolutionvcard2claws.py
22
23  script purpose : convert an evolution addressbook VCARD file 
24  into a Claws Mail addressbook
25
26  tested with evolution 1.2.x, and 1.4.x
27
28 """
29
30 import string
31 import sys
32 import time
33 import os
34
35 keywds = ('x-evolution-file-as','fn', 'n','email;internet','nickname', 'url', 'org')
36
37
38 ################################################################################
39 ##  reads a vcard and stores as hash pairs key/value where value is a list    ##
40 ################################################################################
41
42 def readVCARD (file) :
43
44         """
45
46         skips fom <file> until a 'begin' tag from VCARD is encountered.
47         from this point starts constructing a map (key, [values] ) 
48         VCARD entry format -> tag:value 
49         
50                 key <- tag
51                 [values] <- list with the values of <tag> if there are more tags with the same name
52
53         """
54         r=' '
55         bgn,end = -1, -1;
56         d = dict()
57         while r and bgn < 0 :
58                 r = file.readline()
59                 if len (r)  == 0 : return dict()
60                 if string.find('begin',string.lower(string.strip(r))) :
61                         bgn = 1
62         while r and end < 0 :
63                 r = file.readline()
64                 s = string.split(string.lower(string.strip(r)),':')
65                 if s[0] <> '' :
66                         if d.has_key(s[0]) :
67                                 d[s[0]].append(s[1])
68                         elif len(s) > 1:
69                                 d[s[0]] = [s[1]]        
70                         else :
71                                 d[s[0]] = ['']
72                         if s[0] == 'end' : end = 1      
73         return d
74
75 ##################################################################################
76                                  
77
78 ###############################################################################################
79 ## writes on a given file an xml representation for claws-mail addressbook received as a hash  ##
80 ###############################################################################################
81
82 def writeXMLREPR (vcard,file,uid) :
83
84         """
85         based on <vcard> and <uid> writes only recognized tags (the ones defined in <keywds> list)
86         NOTE: <url> and <org> tag will be written as attributes (there are such tags in claws-mail's
87               XML schema)
88         """
89         if len (vcard.keys()) == 0 : return
90         name = string.split(vcard.get(keywds[2])[0],';')
91
92         fn, ln, nick, cn, a = '', '', '', '', ''
93
94         if len(name) == 2 :
95                 fn = name[0]
96                 ln = name[1]
97         elif len(name) ==1 :
98                 fn = name[0]
99         
100         if vcard.has_key(keywds[4]) :
101                 nick = vcard.get(keywds[4])[0]
102         if len(vcard.get(keywds[1])[0]) :
103                 cn = vcard.get(keywds[1])[0]
104         else :
105                 cn = vcard.get(keywds[0])[0];
106
107         a += str('\n<person uid=\"' + str(uid[0]) + '\" first-name=\"' + fn + '\" last-name=\"' + ln
108                 + '\" nick-name=\"' + nick + '\" cn=\"' + cn + '\" >\n')
109         a += '\t<address-list>\n'
110         if vcard.get(keywds[3]) :
111                 for c in vcard.get(keywds[3]) :
112                         uid[0] = uid[0] + 1
113                         a += '\t\t<address uid=\"' + str(uid[0]) + '\" alias=\"' + nick  + '\" email=\"' + c + '\" remarks=\"\" />\n'
114         else :
115                 uid[0] = uid[0]+1
116                 a += '\t\t<address uid=\"' + str(uid[0]) + '\" alias=\"' +  nick + '\" email=\"\" remarks=\"\" />\n'
117         a += '\t</address-list>\n'
118         a += '\t<attribute-list>\n'
119         for key in keywds[5:] :
120                 if vcard.get(key) :
121                         for c in vcard.get(key) :
122                                 uid[0] = uid[0] + 1
123                                 a += '\t\t<attribute uid=\"' + str(uid[0]) + '\" name=\"' + key +'\">'+c+'</attribute>\n'
124         a += '\t</attribute-list>\n'
125         a += '</person>\n'
126         file.write(a)
127         file.flush()
128                 
129 ###################################################################################################
130
131 def convert (in_f, o_f, name='INBOX') :
132         d = {'d':1}
133         uid = [int(time.time())]
134         try : 
135                 print 'proccessing...\n'
136                 o_f.write('<?xml version="1.0" encoding="ISO-8859-1" ?>\n<address-book name="'+name+'" >\n');
137
138                 while len(d.keys()) > 0 :
139                         d = readVCARD(in_f)
140                         writeXMLREPR (d, o_f, uid)
141                         uid[0] = uid [0]+1
142
143                 o_f.write('\n</address-book>')
144                 print 'finished processing...\n'
145         except IOError, err :
146                 print 'Caught an IOError : ',err,'\t ABORTING!!!'
147                 raise err
148
149 #################################################################################################
150
151 def execute () :
152         if len(sys.argv) <> 3 and len(sys.argv) <> 2 :
153                 print str("\nUsage: vcard2xml.py  source_file [destination_file]\n\n" +
154                 '\tWhen only <source_file> is specified will overwrite the existing addressbook.\n'+
155                 '\tWhen both arguments are suplied will create a new additional addressbook named \n\tas the destination file.'+'\n\tNOTE: in both cases the Claws Mail must be closed and ran at least once.\n\n')
156                 sys.exit(1)
157
158         in_file = None
159         out_file = None
160         path_to_out = os.environ['HOME']+'/.claws-mail/'
161         adr_idx = 'addrbook--index.xml'
162         adr_idx_file = None
163         tmp_adr_idx_file= None
164         got_ex = 0
165
166         try :
167                 in_file = open(sys.argv[1])
168         except IOError, e:
169                 print 'Could not open input file <',sys.argv[1],'>  ABORTING'
170                 sys.exit(1)
171
172         if len(sys.argv) == 2 :
173                 try :
174                         dlist = os.listdir(path_to_out);
175                         flist=[]
176                         for l in dlist :
177                                 if l.find('addrbook') == 0 and l.find("addrbook--index.xml") < 0 and l.find('bak') < 0 :
178                                         flist.append(l)
179                         flist.sort()
180                         out_file = flist.pop()
181                         os.rename(path_to_out+out_file, path_to_out+out_file+'.tmp')
182                         out_file = open(path_to_out+out_file,'w')
183                         convert(in_file, out_file)
184                 except Exception, e:
185                         got_ex = 1
186                         print 'got exception: ', e
187         else :
188                 try :
189                         os.rename(path_to_out+adr_idx, path_to_out+adr_idx+'.tmp')
190                         tmp_adr_idx_file = open(path_to_out+adr_idx+'.tmp')
191                         adr_idx_file = open(path_to_out+adr_idx,'w')
192                 except Exception, e :
193                         print 'Could not open <', path_to_out+adr_idx,'> file. Make sure you started Claws Mail at least once.'
194                         sys.exit(1)
195                 try :
196                         out_file = open(path_to_out+sys.argv[2],'w')
197                         convert(in_file, out_file, sys.argv[2].split('.xml')[0])
198                         l = tmp_adr_idx_file.readline()
199                         while l :
200                                 if l.strip() == '</book_list>' :
201                                         adr_idx_file.write('\t<book name="'+sys.argv[2].split('.xml')[0] +'" file="'+sys.argv[2]+'" />\n')
202                                         adr_idx_file.write(l)
203                                 else :
204                                         adr_idx_file.write(l)
205                                 l = tmp_adr_idx_file.readline()
206                 except Exception, e:
207                         got_ex = 1
208                         print 'got exception: ', e
209         
210
211         if got_ex :
212                 #clean up the mess
213                 print 'got exception, cleaning up the mess... changed files will be restored...\n'
214                 if adr_idx_file :
215                         adr_idx_file.close()
216                 if out_file :
217                         out_file.close()
218                 if len(sys.argv) == 2 :
219                         os.rename(out_file.name+'.tmp', out_file.name)
220                 else :
221                         os.remove(out_file.name)
222                         os.rename(path_to_out+adr_idx+'.tmp', path_to_out+adr_idx)
223                 if tmp_adr_idx_file :
224                         tmp_adr_idx_file.close()
225                                 
226         else :
227                 #closing all and moving temporary data into place
228                 print 'closing open files...\n'
229                 in_file.close()
230                 out_file.close()        
231                 if len(sys.argv) == 3 :
232                         os.rename(path_to_out+adr_idx+'.tmp',path_to_out+adr_idx+'.bak' )
233                 if len(sys.argv) == 2 :
234                         os.rename(out_file.name+'.tmp', out_file.name+'.bak')
235                 if adr_idx_file :
236                         adr_idx_file.close()
237                 if tmp_adr_idx_file :
238                         tmp_adr_idx_file.close()
239                 print 'done!'
240                 
241
242 if __name__ == '__main__':
243     execute ()
244
245