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