vcard2xml.py 7.5 KB

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