Package native :: Package egroupware :: Module egroupware
[hide private]
[frames] | no frames]

Source Code for Module native.egroupware.egroupware

  1  ### BITPIM 
  2  ### 
  3  ### Copyright (C) 2004 Roger Binns <rogerb@rogerbinns.com> 
  4  ### 
  5  ### This program is free software; you can redistribute it and/or modify 
  6  ### it under the terms of the BitPim license as detailed in the LICENSE file. 
  7  ### 
  8  ### $Id: egroupware.py 1770 2004-11-22 06:53:49Z rogerb $ 
  9   
 10  """Be at one with eGroupware 
 11   
 12  We talk to eGroupware using its xmlrpc interface.  Unfortunately the interface 
 13  has several quality issues, so we try to work around them in this code. 
 14  """ 
 15   
 16  import xmlrpclib 
 17  import urlparse 
 18  import time 
 19  import datetime 
 20   
21 -def getsession(url, user, password, domain="default"):
22 23 # fixup whatever the user max have given us 24 scheme, location, path, query, fragment = urlparse.urlsplit(url) 25 26 if scheme is None and location is None and query is None: 27 url="http://"+url 28 29 if url[-1]!="/": url+="/" 30 url+="xmlrpc.php" 31 32 sp=xmlrpclib.ServerProxy(url) 33 34 res=sp.system.login({"username": user, "password": password, "domain": domain}) 35 36 if "sessionid" not in res or "kp3" not in res: 37 raise Exception("Invalid username or password") 38 39 scheme, location, path, query, fragment = urlparse.urlsplit(url) 40 41 if location.find("@")>=0: 42 location=location[location.find("@")+1:] 43 44 newurl=urlparse.urlunsplit( (scheme, "%s:%s@%s" % (res["sessionid"], res["kp3"], location), path, query, fragment) ) 45 return Session(xmlrpclib.ServerProxy(newurl), res)
46
47 -class Session:
48
49 - def __init__(self, sp, ifo):
50 self.sp=sp 51 self.__ifo=ifo
52
53 - def __del__(self):
54 self.sp.system.logout(self.__ifo) 55 self.sp=None 56 self.__ifo=None
57
58 - def getyearcalendar(self, year):
59 return getcalendar((year,), (year,))
60
61 - def getcalendar(self, start=(), end=()):
62 if len(start)!=6 or len(end)!=6: 63 t=time.localtime() 64 startdefs=(t[0], 1, 1, 0,0,0) 65 enddefs=(t[0],12,31,23,59,60) 66 start=start+startdefs[len(start):] 67 end=end+enddefs[len(end):] 68 start="%04d-%02d-%02dT%02d:%02d:%02d" % start 69 end="%04d-%02d-%02dT%02d:%02d:%02d" % end 70 for item in self.sp.calendar.bocalendar.search({"start": start, "end": end}): 71 for k in item.keys(): 72 if isinstance(item[k], xmlrpclib.DateTime): 73 v=str(item[k]) 74 v=[int(x) for x in v[0:4], v[5:7], v[8:10], v[11:13], v[14:16], v[17:19]] 75 if v==[0,0,0,0,0,0]: 76 del item[k] 77 else: 78 item[k]=datetime.datetime(*v) 79 yield item
80
81 - def doescontactexist(self, id):
82 try: 83 return self.sp.addressbook.boaddressbook.read({'id': id}) 84 except xmlrpclib.Fault, f: 85 # in theory only fault 10 - Entry does not (longer) exist! 86 # should be looked for. Unfortunately egroupware has a 87 # bug and returns fault 9 - Access denied if the id 88 # doesn't exist. So we consider any failure to mean 89 # that the id doesn't exist. Reported as SF bug #1057984 90 print "eg contact doesn't exist, fault", f 91 return False
92
93 - def getcontacts(self):
94 "returns all contacts" 95 # internally we read them a group at a time 96 offset=0 97 limit=5 98 99 # NB an offset of zero causes egroupware to return ALL contacts ignoring limit! 100 # This has been filed as bug 1040738 at SourceForge against eGroupware. It 101 # won't hurt unless you have huge number of contacts as egroupware will try 102 # to return all of them at once. Alternatively make the simple fix as in 103 # the bug report 104 105 while True: 106 contacts=self.sp.addressbook.boaddressbook.search({'start': offset, 'limit': limit}) 107 if len(contacts)==0: 108 raise StopIteration() 109 for i in contacts: 110 yield i 111 if len(contacts)<limit: 112 raise StopIteration() 113 offset+=len(contacts)
114
115 - def writecontact(self, contact):
116 "Returns the id of the contact" 117 # egroupware returns True if the contact was written successfully using the 118 # existing id, otherwise it returns the new id 119 res=self.sp.addressbook.boaddressbook.write(contact) 120 if res is True: 121 return contact['id'] 122 return res
123
124 - def getcontactspbformat(self):
125 "returns contacts in a format suitable for the BitPim phonebook importer" 126 # eGroupware gives a nice shine in the UI, but the underlying data is 127 # somewhat messy 128 for c in self.getcontacts(): 129 res={} 130 # egroupware format is very similar to vCard 131 res['Name']=c['fn'] 132 res['First Name']=c['n_given'] 133 res['Middle Name']=c['n_middle'] 134 res['Last Name']=c['n_family'] 135 res['UniqueSerial-id']=c['id'] 136 res['UniqueSerial-sourcetype']='egroupware' 137 # addresses 138 for t,prefix in ("business", "adr_one"), ("home", "adr_two"): 139 a={} 140 # egroupware has street 2 and 3 in the ui, but doesn't expose them 141 # via xmlrpc - reported as SF bug # 1043862 142 for p2,k in ("_street", "street"), ("_locality", "city"), ("_region", "state"), \ 143 ("_postalcode", "postalcode"), ("_countryname", "country"): 144 if len(c.get(prefix+p2,"")): a[k]=c[prefix+p2] 145 if t=="business" and len(c.get("org_name", "")): a['company']=c["org_name"] 146 if len(a): 147 a['type']=t 148 aa="Address" 149 if aa in res: 150 aa+="2" 151 assert aa not in res 152 res[aa]=a 153 # categories 154 cats=[] 155 ccats=c.get("cat_id", "") 156 if len(ccats): # could be empty string or a dict 157 for cat in ccats: 158 cats.append(ccats[cat]) 159 if len(cats): 160 res["Categories"]=cats 161 # email - we ignore the silly egroupware email type field 162 suf="" 163 if len(c.get("email","")): 164 res["Email Address"]={'email': c['email'], 'type': 'business'} 165 suf="2" 166 if len(c.get("email_home", "")): 167 res["Email Address"+suf]={'email': c['email_home'], 'type': 'home'} 168 # phone numbers 169 res["Home Phone"]=c['tel_home'] 170 res["Mobile Phone"]=c['tel_cell'] # nb: in eGroupware this is business cell 171 res["Business Fax"]=c['tel_fax'] 172 res["Pager"]=c['tel_pager'] # nb: in eGroupware this is business pager 173 res["Business Phone"]=c['tel_work'] 174 # various other fields 175 res['Notes']=c['note'] 176 res['Business Web Page']=c['url'] 177 178 # filter out empty fields 179 res=dict([(k,v) for k,v in res.items() if len(v)]) 180 yield res
181
182 - def getcategories(self):
183 "Get the list of categories" 184 # egroupware returns a dict with each key being an asciized integer 185 # id. The same field is present in the dict value, so we just return 186 # the values 187 return [v for k,v in self.sp.addressbook.boaddressbook.categories(True).items()]
188 189 190 if __name__=='__main__': 191 import sys 192 import common 193 s=getsession(*sys.argv[1:]) 194 for v in s.getcategories(): 195 print common.prettyprintdict(v) 196 #for n,i in enumerate(s.getcontacts()): 197 # print n,common.prettyprintdict(i) 198 199 #print n,i.get('id',""),i.get('n_given', ""),i.get('n_family', "") 200