stanza.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. import base64
  2. import datetime as dt
  3. from sleekxmpp.util import bytes
  4. from sleekxmpp.xmlstream import ElementBase, ET, register_stanza_plugin, JID
  5. from sleekxmpp.plugins import xep_0082
  6. class VCardTemp(ElementBase):
  7. name = 'vCard'
  8. namespace = 'vcard-temp'
  9. plugin_attrib = 'vcard_temp'
  10. interfaces = set(['FN', 'VERSION'])
  11. sub_interfaces = set(['FN', 'VERSION'])
  12. class Name(ElementBase):
  13. name = 'N'
  14. namespace = 'vcard-temp'
  15. plugin_attrib = name
  16. interfaces = set(['FAMILY', 'GIVEN', 'MIDDLE', 'PREFIX', 'SUFFIX'])
  17. sub_interfaces = interfaces
  18. def _set_component(self, name, value):
  19. if isinstance(value, list):
  20. value = ','.join(value)
  21. if value is not None:
  22. self._set_sub_text(name, value, keep=True)
  23. else:
  24. self._del_sub(name)
  25. def _get_component(self, name):
  26. value = self._get_sub_text(name, '')
  27. if ',' in value:
  28. value = [v.strip() for v in value.split(',')]
  29. return value
  30. def set_family(self, value):
  31. self._set_component('FAMILY', value)
  32. def get_family(self):
  33. return self._get_component('FAMILY')
  34. def set_given(self, value):
  35. self._set_component('GIVEN', value)
  36. def get_given(self):
  37. return self._get_component('GIVEN')
  38. def set_middle(self, value):
  39. print(value)
  40. self._set_component('MIDDLE', value)
  41. def get_middle(self):
  42. return self._get_component('MIDDLE')
  43. def set_prefix(self, value):
  44. self._set_component('PREFIX', value)
  45. def get_prefix(self):
  46. return self._get_component('PREFIX')
  47. def set_suffix(self, value):
  48. self._set_component('SUFFIX', value)
  49. def get_suffix(self):
  50. return self._get_component('SUFFIX')
  51. class Nickname(ElementBase):
  52. name = 'NICKNAME'
  53. namespace = 'vcard-temp'
  54. plugin_attrib = name
  55. plugin_multi_attrib = 'nicknames'
  56. interfaces = set([name])
  57. is_extension = True
  58. def set_nickname(self, value):
  59. if not value:
  60. self.xml.text = ''
  61. return
  62. if not isinstance(value, list):
  63. value = [value]
  64. self.xml.text = ','.join(value)
  65. def get_nickname(self):
  66. if self.xml.text:
  67. return self.xml.text.split(',')
  68. class Email(ElementBase):
  69. name = 'EMAIL'
  70. namespace = 'vcard-temp'
  71. plugin_attrib = name
  72. plugin_multi_attrib = 'emails'
  73. interfaces = set(['HOME', 'WORK', 'INTERNET', 'PREF', 'X400', 'USERID'])
  74. sub_interfaces = set(['USERID'])
  75. bool_interfaces = set(['HOME', 'WORK', 'INTERNET', 'PREF', 'X400'])
  76. class Address(ElementBase):
  77. name = 'ADR'
  78. namespace = 'vcard-temp'
  79. plugin_attrib = name
  80. plugin_multi_attrib = 'addresses'
  81. interfaces = set(['HOME', 'WORK', 'POSTAL', 'PARCEL', 'DOM', 'INTL',
  82. 'PREF', 'POBOX', 'EXTADD', 'STREET', 'LOCALITY',
  83. 'REGION', 'PCODE', 'CTRY'])
  84. sub_interfaces = set(['POBOX', 'EXTADD', 'STREET', 'LOCALITY',
  85. 'REGION', 'PCODE', 'CTRY'])
  86. bool_interfaces = set(['HOME', 'WORK', 'DOM', 'INTL', 'PREF'])
  87. class Telephone(ElementBase):
  88. name = 'TEL'
  89. namespace = 'vcard-temp'
  90. plugin_attrib = name
  91. plugin_multi_attrib = 'telephone_numbers'
  92. interfaces = set(['HOME', 'WORK', 'VOICE', 'FAX', 'PAGER', 'MSG',
  93. 'CELL', 'VIDEO', 'BBS', 'MODEM', 'ISDN', 'PCS',
  94. 'PREF', 'NUMBER'])
  95. sub_interfaces = set(['NUMBER'])
  96. bool_interfaces = set(['HOME', 'WORK', 'VOICE', 'FAX', 'PAGER',
  97. 'MSG', 'CELL', 'VIDEO', 'BBS', 'MODEM',
  98. 'ISDN', 'PCS', 'PREF'])
  99. def setup(self, xml=None):
  100. super(Telephone, self).setup(xml=xml)
  101. ## this blanks out numbers received from server
  102. ##self._set_sub_text('NUMBER', '', keep=True)
  103. def set_number(self, value):
  104. self._set_sub_text('NUMBER', value, keep=True)
  105. def del_number(self):
  106. self._set_sub_text('NUMBER', '', keep=True)
  107. class Label(ElementBase):
  108. name = 'LABEL'
  109. namespace = 'vcard-temp'
  110. plugin_attrib = name
  111. plugin_multi_attrib = 'labels'
  112. interfaces = set(['HOME', 'WORK', 'POSTAL', 'PARCEL', 'DOM', 'INT',
  113. 'PREF', 'lines'])
  114. bool_interfaces = set(['HOME', 'WORK', 'POSTAL', 'PARCEL', 'DOM',
  115. 'INT', 'PREF'])
  116. def add_line(self, value):
  117. line = ET.Element('{%s}LINE' % self.namespace)
  118. line.text = value
  119. self.xml.append(line)
  120. def get_lines(self):
  121. lines = self.xml.find('{%s}LINE' % self.namespace)
  122. if lines is None:
  123. return []
  124. return [line.text for line in lines]
  125. def set_lines(self, values):
  126. self.del_lines()
  127. for line in values:
  128. self.add_line(line)
  129. def del_lines(self):
  130. lines = self.xml.find('{%s}LINE' % self.namespace)
  131. if lines is None:
  132. return
  133. for line in lines:
  134. self.xml.remove(line)
  135. class Geo(ElementBase):
  136. name = 'GEO'
  137. namespace = 'vcard-temp'
  138. plugin_attrib = name
  139. plugin_multi_attrib = 'geolocations'
  140. interfaces = set(['LAT', 'LON'])
  141. sub_interfaces = interfaces
  142. class Org(ElementBase):
  143. name = 'ORG'
  144. namespace = 'vcard-temp'
  145. plugin_attrib = name
  146. plugin_multi_attrib = 'organizations'
  147. interfaces = set(['ORGNAME', 'ORGUNIT', 'orgunits'])
  148. sub_interfaces = set(['ORGNAME', 'ORGUNIT'])
  149. def add_orgunit(self, value):
  150. orgunit = ET.Element('{%s}ORGUNIT' % self.namespace)
  151. orgunit.text = value
  152. self.xml.append(orgunit)
  153. def get_orgunits(self):
  154. orgunits = self.xml.find('{%s}ORGUNIT' % self.namespace)
  155. if orgunits is None:
  156. return []
  157. return [orgunit.text for orgunit in orgunits]
  158. def set_orgunits(self, values):
  159. self.del_orgunits()
  160. for orgunit in values:
  161. self.add_orgunit(orgunit)
  162. def del_orgunits(self):
  163. orgunits = self.xml.find('{%s}ORGUNIT' % self.namespace)
  164. if orgunits is None:
  165. return
  166. for orgunit in orgunits:
  167. self.xml.remove(orgunit)
  168. class Photo(ElementBase):
  169. name = 'PHOTO'
  170. namespace = 'vcard-temp'
  171. plugin_attrib = name
  172. plugin_multi_attrib = 'photos'
  173. interfaces = set(['TYPE', 'EXTVAL'])
  174. sub_interfaces = interfaces
  175. class Logo(ElementBase):
  176. name = 'LOGO'
  177. namespace = 'vcard-temp'
  178. plugin_attrib = name
  179. plugin_multi_attrib = 'logos'
  180. interfaces = set(['TYPE', 'EXTVAL'])
  181. sub_interfaces = interfaces
  182. class Sound(ElementBase):
  183. name = 'SOUND'
  184. namespace = 'vcard-temp'
  185. plugin_attrib = name
  186. plugin_multi_attrib = 'sounds'
  187. interfaces = set(['PHONETC', 'EXTVAL'])
  188. sub_interfaces = interfaces
  189. class BinVal(ElementBase):
  190. name = 'BINVAL'
  191. namespace = 'vcard-temp'
  192. plugin_attrib = name
  193. interfaces = set(['BINVAL'])
  194. is_extension = True
  195. def setup(self, xml=None):
  196. self.xml = ET.Element('')
  197. return True
  198. def set_binval(self, value):
  199. self.del_binval()
  200. parent = self.parent()
  201. if value:
  202. xml = ET.Element('{%s}BINVAL' % self.namespace)
  203. xml.text = bytes(base64.b64encode(value)).decode('utf-8')
  204. parent.append(xml)
  205. def get_binval(self):
  206. parent = self.parent()
  207. xml = parent.find('{%s}BINVAL' % self.namespace)
  208. if xml is not None:
  209. return base64.b64decode(bytes(xml.text))
  210. return b''
  211. def del_binval(self):
  212. self.parent()._del_sub('{%s}BINVAL' % self.namespace)
  213. class Classification(ElementBase):
  214. name = 'CLASS'
  215. namespace = 'vcard-temp'
  216. plugin_attrib = name
  217. plugin_multi_attrib = 'classifications'
  218. interfaces = set(['PUBLIC', 'PRIVATE', 'CONFIDENTIAL'])
  219. bool_interfaces = interfaces
  220. class Categories(ElementBase):
  221. name = 'CATEGORIES'
  222. namespace = 'vcard-temp'
  223. plugin_attrib = name
  224. plugin_multi_attrib = 'categories'
  225. interfaces = set([name])
  226. is_extension = True
  227. def set_categories(self, values):
  228. self.del_categories()
  229. for keyword in values:
  230. item = ET.Element('{%s}KEYWORD' % self.namespace)
  231. item.text = keyword
  232. self.xml.append(item)
  233. def get_categories(self):
  234. items = self.xml.findall('{%s}KEYWORD' % self.namespace)
  235. if items is None:
  236. return []
  237. keywords = []
  238. for item in items:
  239. keywords.append(item.text)
  240. return keywords
  241. def del_categories(self):
  242. items = self.xml.findall('{%s}KEYWORD' % self.namespace)
  243. for item in items:
  244. self.xml.remove(item)
  245. class Birthday(ElementBase):
  246. name = 'BDAY'
  247. namespace = 'vcard-temp'
  248. plugin_attrib = name
  249. plugin_multi_attrib = 'birthdays'
  250. interfaces = set([name])
  251. is_extension = True
  252. def set_bday(self, value):
  253. if isinstance(value, dt.datetime):
  254. value = xep_0082.format_datetime(value)
  255. self.xml.text = value
  256. def get_bday(self):
  257. if not self.xml.text:
  258. return None
  259. return xep_0082.parse(self.xml.text)
  260. class Rev(ElementBase):
  261. name = 'REV'
  262. namespace = 'vcard-temp'
  263. plugin_attrib = name
  264. plugin_multi_attrib = 'revision_dates'
  265. interfaces = set([name])
  266. is_extension = True
  267. def set_rev(self, value):
  268. if isinstance(value, dt.datetime):
  269. value = xep_0082.format_datetime(value)
  270. self.xml.text = value
  271. def get_rev(self):
  272. if not self.xml.text:
  273. return None
  274. return xep_0082.parse(self.xml.text)
  275. class Title(ElementBase):
  276. name = 'TITLE'
  277. namespace = 'vcard-temp'
  278. plugin_attrib = name
  279. plugin_multi_attrib = 'titles'
  280. interfaces = set([name])
  281. is_extension = True
  282. def set_title(self, value):
  283. self.xml.text = value
  284. def get_title(self):
  285. return self.xml.text
  286. class Role(ElementBase):
  287. name = 'ROLE'
  288. namespace = 'vcard-temp'
  289. plugin_attrib = name
  290. plugin_multi_attrib = 'roles'
  291. interfaces = set([name])
  292. is_extension = True
  293. def set_role(self, value):
  294. self.xml.text = value
  295. def get_role(self):
  296. return self.xml.text
  297. class Note(ElementBase):
  298. name = 'NOTE'
  299. namespace = 'vcard-temp'
  300. plugin_attrib = name
  301. plugin_multi_attrib = 'notes'
  302. interfaces = set([name])
  303. is_extension = True
  304. def set_note(self, value):
  305. self.xml.text = value
  306. def get_note(self):
  307. return self.xml.text
  308. class Desc(ElementBase):
  309. name = 'DESC'
  310. namespace = 'vcard-temp'
  311. plugin_attrib = name
  312. plugin_multi_attrib = 'descriptions'
  313. interfaces = set([name])
  314. is_extension = True
  315. def set_desc(self, value):
  316. self.xml.text = value
  317. def get_desc(self):
  318. return self.xml.text
  319. class URL(ElementBase):
  320. name = 'URL'
  321. namespace = 'vcard-temp'
  322. plugin_attrib = name
  323. plugin_multi_attrib = 'urls'
  324. interfaces = set([name])
  325. is_extension = True
  326. def set_url(self, value):
  327. self.xml.text = value
  328. def get_url(self):
  329. return self.xml.text
  330. class UID(ElementBase):
  331. name = 'UID'
  332. namespace = 'vcard-temp'
  333. plugin_attrib = name
  334. plugin_multi_attrib = 'uids'
  335. interfaces = set([name])
  336. is_extension = True
  337. def set_uid(self, value):
  338. self.xml.text = value
  339. def get_uid(self):
  340. return self.xml.text
  341. class ProdID(ElementBase):
  342. name = 'PRODID'
  343. namespace = 'vcard-temp'
  344. plugin_attrib = name
  345. plugin_multi_attrib = 'product_ids'
  346. interfaces = set([name])
  347. is_extension = True
  348. def set_prodid(self, value):
  349. self.xml.text = value
  350. def get_prodid(self):
  351. return self.xml.text
  352. class Mailer(ElementBase):
  353. name = 'MAILER'
  354. namespace = 'vcard-temp'
  355. plugin_attrib = name
  356. plugin_multi_attrib = 'mailers'
  357. interfaces = set([name])
  358. is_extension = True
  359. def set_mailer(self, value):
  360. self.xml.text = value
  361. def get_mailer(self):
  362. return self.xml.text
  363. class SortString(ElementBase):
  364. name = 'SORT-STRING'
  365. namespace = 'vcard-temp'
  366. plugin_attrib = 'SORT_STRING'
  367. plugin_multi_attrib = 'sort_strings'
  368. interfaces = set([name])
  369. is_extension = True
  370. def set_sort_string(self, value):
  371. self.xml.text = value
  372. def get_sort_string(self):
  373. return self.xml.text
  374. class Agent(ElementBase):
  375. name = 'AGENT'
  376. namespace = 'vcard-temp'
  377. plugin_attrib = name
  378. plugin_multi_attrib = 'agents'
  379. interfaces = set(['EXTVAL'])
  380. sub_interfaces = interfaces
  381. class JabberID(ElementBase):
  382. name = 'JABBERID'
  383. namespace = 'vcard-temp'
  384. plugin_attrib = name
  385. plugin_multi_attrib = 'jids'
  386. interfaces = set([name])
  387. is_extension = True
  388. def set_jabberid(self, value):
  389. self.xml.text = JID(value).bare
  390. def get_jabberid(self):
  391. return JID(self.xml.text)
  392. class TimeZone(ElementBase):
  393. name = 'TZ'
  394. namespace = 'vcard-temp'
  395. plugin_attrib = name
  396. plugin_multi_attrib = 'timezones'
  397. interfaces = set([name])
  398. is_extension = True
  399. def set_tz(self, value):
  400. time = xep_0082.time(offset=value)
  401. if time[-1] == 'Z':
  402. self.xml.text = 'Z'
  403. else:
  404. self.xml.text = time[-6:]
  405. def get_tz(self):
  406. if not self.xml.text:
  407. return xep_0082.tzutc()
  408. time = xep_0082.parse('00:00:00%s' % self.xml.text)
  409. return time.tzinfo
  410. register_stanza_plugin(VCardTemp, Name)
  411. register_stanza_plugin(VCardTemp, Address, iterable=True)
  412. register_stanza_plugin(VCardTemp, Agent, iterable=True)
  413. register_stanza_plugin(VCardTemp, Birthday, iterable=True)
  414. register_stanza_plugin(VCardTemp, Categories, iterable=True)
  415. register_stanza_plugin(VCardTemp, Desc, iterable=True)
  416. register_stanza_plugin(VCardTemp, Email, iterable=True)
  417. register_stanza_plugin(VCardTemp, Geo, iterable=True)
  418. register_stanza_plugin(VCardTemp, JabberID, iterable=True)
  419. register_stanza_plugin(VCardTemp, Label, iterable=True)
  420. register_stanza_plugin(VCardTemp, Logo, iterable=True)
  421. register_stanza_plugin(VCardTemp, Mailer, iterable=True)
  422. register_stanza_plugin(VCardTemp, Note, iterable=True)
  423. register_stanza_plugin(VCardTemp, Nickname, iterable=True)
  424. register_stanza_plugin(VCardTemp, Org, iterable=True)
  425. register_stanza_plugin(VCardTemp, Photo, iterable=True)
  426. register_stanza_plugin(VCardTemp, ProdID, iterable=True)
  427. register_stanza_plugin(VCardTemp, Rev, iterable=True)
  428. register_stanza_plugin(VCardTemp, Role, iterable=True)
  429. register_stanza_plugin(VCardTemp, SortString, iterable=True)
  430. register_stanza_plugin(VCardTemp, Sound, iterable=True)
  431. register_stanza_plugin(VCardTemp, Telephone, iterable=True)
  432. register_stanza_plugin(VCardTemp, Title, iterable=True)
  433. register_stanza_plugin(VCardTemp, TimeZone, iterable=True)
  434. register_stanza_plugin(VCardTemp, UID, iterable=True)
  435. register_stanza_plugin(VCardTemp, URL, iterable=True)
  436. register_stanza_plugin(Photo, BinVal)
  437. register_stanza_plugin(Logo, BinVal)
  438. register_stanza_plugin(Sound, BinVal)
  439. register_stanza_plugin(Agent, VCardTemp)