[CalendarServer-changes] [11592] CalendarServer/trunk/txdav/carddav/datastore

source_changes at macosforge.org source_changes at macosforge.org
Fri Aug 9 19:35:04 PDT 2013


Revision: 11592
          http://trac.calendarserver.org//changeset/11592
Author:   gaya at apple.com
Date:     2013-08-09 19:35:04 -0700 (Fri, 09 Aug 2013)
Log Message:
-----------
don't remove self-referent group members; allow groups and members to be added to sharee partially-shared addressbooks in bulk operations; add CalDAVTester tests.

Modified Paths:
--------------
    CalDAVTester/trunk/Resource/CardDAV/sharing/access/setup/6.vcf
    CalDAVTester/trunk/scripts/tests/CardDAV/sharing-access.xml
    CalDAVTester/trunk/scripts/tests/CardDAV/sharing-unshare.xml
    CalendarServer/trunk/twistedcaldav/storebridge.py
    CalendarServer/trunk/txdav/carddav/datastore/sql.py

Added Paths:
-----------
    CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/
    CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/1.vcf
    CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/10.xml
    CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/11.xml
    CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/12.xml
    CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/13.xml
    CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/2.vcf
    CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/3.vcf
    CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/4.vcf
    CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/5.vcf
    CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/6.vcf
    CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/7.vcf
    CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/8.vcf
    CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/9.xml
    CalDAVTester/trunk/scripts/tests/CardDAV/sharing-bulk.xml

Modified: CalDAVTester/trunk/Resource/CardDAV/sharing/access/setup/6.vcf
===================================================================
--- CalDAVTester/trunk/Resource/CardDAV/sharing/access/setup/6.vcf	2013-08-07 22:36:54 UTC (rev 11591)
+++ CalDAVTester/trunk/Resource/CardDAV/sharing/access/setup/6.vcf	2013-08-10 02:35:04 UTC (rev 11592)
@@ -7,987 +7,5 @@
 TEL;type=CELL:8888888888
 item1.ADR;type=WORK;type=pref:;;1234 Golly Street;Sunnyside;CA;99999;USA
 item1.X-ABADR:us
-PHOTO;BASE64:
-  /9j/4AAQSkZJRgABAQAAAQABAAD/7QA8UGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAB8cAVoAAx
-  sl RxwCAAACAAIcAhkAC1Bob3RvIEJvb3RoAP/iG6hJQ0NfUFJPRklMRQABAQAAG5hhcHBsAgA
-  AAG1u dHJSR0IgWFlaIAfaAAEAEwAJADEABGFjc3BBUFBMAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-  AAAAAAD2 1gABAAAAANMtYXBwbFYcEOZVYuhIRg5LwLIi62wAAAAAAAAAAAAAAAAAAAAAAAAAA
-  AAAAAAAAAAA AAAAEXJYWVoAAAFQAAAAFGdYWVoAAAFkAAAAFGJYWVoAAAF4AAAAFHd0cHQAAA
-  GMAAAAFGNoYWQA AAGgAAAALHJUUkMAAAHMAAAIDGdUUkMAAAnYAAAIDGJUUkMAABHkAAAIDGF
-  hcmcAABnwAAAAIGFh Z2cAABoQAAAAIGFhYmcAABowAAAAIHZjZ3QAABpQAAAAMG5kaW4AABqA
-  AAAAOGRlc2MAABq4AAAA ZGRzY20AABscAAAALm1tb2QAABtMAAAAKGNwcnQAABt0AAAAJFhZW
-  iAAAAAAAAB7vQAAQXsAAAJL WFlaIAAAAAAAAFYqAACp0AAAFF9YWVogAAAAAAAAJO8AABS1AA
-  C8glhZWiAAAAAAAADz2AABAAAA ARYIc2YzMgAAAAAAAQu3AAAFlv//81cAAAcpAAD91///+7f
-  ///2mAAAD2gAAwPZjdXJ2AAAAAAAA BAAAAAAFAAoADwAUABkAHgAjACgALQAyADcAOwBAAEUA
-  SgBPAFQAWQBeAGMAaABtAHIAdwB8AIEA hgCLAJAAlQCaAJ8ApACpAK4AsgC3ALwAwQDGAMsA0
-  ADVANoA4ADlAOoA8AD1APsBAQEHAQwBEgEY AR4BJQErATEBOAE+AUUBSwFSAVkBYAFmAW0BdQ
-  F8AYMBigGSAZkBoQGoAbABuAHAAcgB0AHYAeAB 6QHxAfoCAgILAhQCHAIlAi4CNwJAAkoCUwJ
-  cAmYCcAJ5AoMCjQKXAqECqwK1Ar8CygLUAt8C6gL0 Av8DCgMVAyADKwM3A0IDTQNZA2UDcAN8
-  A4gDlAOgA6wDuQPFA9ID3gPrA/gEBAQRBB4ELAQ5BEYE VARhBG8EfASKBJgEpgS0BMIE0QTfB
-  O4E/AULBRoFKAU3BUcFVgVlBXQFhAWTBaMFswXDBdMF4wXz BgMGFAYkBjUGRQZWBmcGeAaJBp
-  oGqwa9Bs4G4AbyBwMHFQcnBzkHTAdeB3AHgweWB6gHuwfOB+EH 9AgICBsILwhCCFYIagh+CJI
-  Ipgi6CM4I4wj3CQwJIQk2CUsJYAl1CYoJoAm1CcsJ4An2CgwKIgo5 Ck8KZQp8CpIKqQrACtcK
-  7gsFCx0LNAtLC2MLewuTC6sLwwvbC/MMDAwkDD0MVgxuDIcMoQy6DNMM 7Q0GDSANOg1UDW4Ni
-  A2iDbwN1w3xDgwOJw5CDl0OeA6TDq8Oyg7mDwIPHg86D1YPcg+OD6sPyA/k EAEQHhA7EFgQdh
-  CTELEQzhDsEQoRKBFGEWQRgxGhEcAR3xH+Eh0SPBJbEnoSmhK5EtkS+RMZEzkT WRN6E5oTuxP
-  bE/wUHRQ+FF8UgRSiFMQU5RUHFSkVSxVtFZAVshXVFfcWGhY9FmAWgxanFsoW7hcS FzUXWRd9
-  F6IXxhfqGA8YNBhZGH0YoxjIGO0ZExk4GV4ZhBmqGdAZ9hodGkMaahqQGrca3hsGGy0b VBt8G
-  6MbyxvzHBscQxxsHJQcvRzmHQ4dNx1gHYodsx3dHgYeMB5aHoQerh7YHwMfLR9YH4Mfrh/Z IA
-  QgMCBbIIcgsyDeIQohNyFjIY8hvCHpIhUiQiJwIp0iyiL4IyUjUyOBI68j3SQMJDokaSSXJMYk
-  9SUkJVQlgyWzJeImEiZCJnImoybTJwMnNCdlJ5Ynxyf4KCooWyiNKL4o8CkiKVUphym5KewqHy
-  pS KoUquCrrKx4rUiuGK7or7iwiLFYsiiy/LPQtKS1eLZMtyC39LjMuaS6eLtQvCy9BL3cvri/
-  kMBsw UjCJMMEw+DEwMWcxnzHXMg8ySDKAMrgy8TMqM2MznDPVNA80SDSCNLw09jUwNWo1pTXf
-  Nho2VTaQ Nss3BjdCN343uTf1ODE4bTiqOOY5IzlgOZ052joXOlQ6kjrPOw07SzuJO8c8BjxEP
-  IM8wj0BPUA9 fz2/Pf4+Pj5+Pr4+/j8/P38/wEAAQEFAgkDEQQVBR0GIQcpCDEJOQpFC00MWQ1
-  hDm0PeRCFEZUSo ROxFMEV0RbhF/EZARoVGykcOR1NHmUfeSCNIaUivSPVJO0mBScdKDkpVSpt
-  K4ksqS3FLuEwATEhM kEzYTSBNaE2xTfpOQk6MTtVPHk9nT7FP+1BFUI9Q2VEkUW5RuVIEUk9S
-  mlLlUzFTfFPIVBRUYFSt VPlVRlWSVd9WLFZ6VsdXFFdiV7BX/lhMWJpY6Vk4WYZZ1VokWnRaw
-  1sTW2NbslwDXFNco1z0XURd lV3mXjdeiV7aXyxffl/QYCJgdGDHYRlhbGG/YhJiZWK5YwxjYG
-  O0ZAhkXGSxZQVlWmWvZgRmWWav ZwRnWmewaAZoXGiyaQlpX2m2ag1qZGq8axNra2vDbBtsc2z
-  LbSNtfG3Vbi5uh27gbzpvk2/tcEdw oXD7cVZxsHILcmZywXMcc3hz03QvdIt053VDdaB1/HZZ
-  drZ3E3dwd854K3iJeOd5RXmjegJ6YHq/ ex57fXvcfDx8m3z7fVt9u34bfnx+3H89f55//4Bgg
-  MKBI4GFgeeCSYKrgw6DcIPThDaEmYT8hWCF w4YnhouG74dUh7iIHYiBiOaJTImxihaKfIrii0
-  iLrowUjHuM4o1Ija+OF45+juWPTY+1kB2QhZDu kVaRv5IokpGS+pNkk82UN5ShlQuVdZXglkq
-  WtZcgl4uX95himM6ZOpmmmhKafprrm1ebxJwxnJ+d DJ15neeeVZ7DnzGfoKAPoH2g7KFbocui
-  OqKqoxqjiqP6pGqk26VMpbymLqafpxCngqf0qGWo2KlK qbyqL6qiqxWriKv7rG+s461WrcuuP
-  66zryivnbARsIew/LFxseeyXbLTs0mzv7Q2tK21JLWbthK2 ibcBt3m38bhpuOG5WrnSuku6xL
-  s+u7e8MLyqvSS9nr4ZvpO/Dr+JwATAf8D6wXbB8cJtwunDZsPi xF/E3MVZxdbGU8bRx07HzMh
-  KyMnJR8nGykXKxMtDy8LMQszBzUHNwc5CzsLPQ8/D0ETQxtFH0cjS StLM007T0NRT1NbVWNXb
-  1l7W4tdl1+nYbdjx2XXZ+tp/2wPbiNwO3JPdGd2e3iTeqt8x37fgPuDF 4Uzh0+Ja4uLjauPy5
-  HrlAuWL5hPmnOcl56/oOOjC6Uzp1upg6urrdev/7IrtFu2h7izuuO9E79Dw XPDp8XXyAvKP8x
-  zzqvQ39MX1U/Xh9m/2/veM+Bv4qvk5+cn6Wfro+3j8CPyZ/Sn9uv5L/tz/bmN1 cnYAAAAAAAA
-  EAAAAAAUACgAPABQAGQAeACMAKAAtADIANwA7AEAARQBKAE8AVABZAF4AYwBoAG0A cgB3AHwA
-  gQCGAIsAkACVAJoAnwCkAKkArgCyALcAvADBAMYAywDQANUA2gDgAOUA6gDwAPUA+wEB AQcBD
-  AESARgBHgElASsBMQE4AT4BRQFLAVIBWQFgAWYBbQF1AXwBgwGKAZIBmQGhAagBsAG4AcAB yA
-  HQAdgB4AHpAfEB+gICAgsCFAIcAiUCLgI3AkACSgJTAlwCZgJwAnkCgwKNApcCoQKrArUCvwLK
-  AtQC3wLqAvQC/wMKAxUDIAMrAzcDQgNNA1kDZQNwA3wDiAOUA6ADrAO5A8UD0gPeA+sD+AQEBB
-  EE HgQsBDkERgRUBGEEbwR8BIoEmASmBLQEwgTRBN8E7gT8BQsFGgUoBTcFRwVWBWUFdAWEBZM
-  FowWz BcMF0wXjBfMGAwYUBiQGNQZFBlYGZwZ4BokGmgarBr0GzgbgBvIHAwcVBycHOQdMB14H
-  cAeDB5YH qAe7B84H4Qf0CAgIGwgvCEIIVghqCH4IkgimCLoIzgjjCPcJDAkhCTYJSwlgCXUJi
-  gmgCbUJywng CfYKDAoiCjkKTwplCnwKkgqpCsAK1wruCwULHQs0C0sLYwt7C5MLqwvDC9sL8w
-  wMDCQMPQxWDG4M hwyhDLoM0wztDQYNIA06DVQNbg2IDaINvA3XDfEODA4nDkIOXQ54DpMOrw7
-  KDuYPAg8eDzoPVg9y D44Pqw/ID+QQARAeEDsQWBB2EJMQsRDOEOwRChEoEUYRZBGDEaERwBHf
-  Ef4SHRI8ElsSehKaErkS 2RL5ExkTORNZE3oTmhO7E9sT/BQdFD4UXxSBFKIUxBTlFQcVKRVLF
-  W0VkBWyFdUV9xYaFj0WYBaD FqcWyhbuFxIXNRdZF30XohfGF+oYDxg0GFkYfRijGMgY7RkTGT
-  gZXhmEGaoZ0Bn2Gh0aQxpqGpAa txreGwYbLRtUG3wboxvLG/McGxxDHGwclBy9HOYdDh03HWA
-  dih2zHd0eBh4wHloehB6uHtgfAx8t H1gfgx+uH9kgBCAwIFsghyCzIN4hCiE3IWMhjyG8Ieki
-  FSJCInAinSLKIvgjJSNTI4EjryPdJAwk OiRpJJckxiT1JSQlVCWDJbMl4iYSJkImciajJtMnA
-  yc0J2UnlifHJ/goKihbKI0ovijwKSIpVSmH Kbkp7CofKlIqhSq4KusrHitSK4YruivuLCIsVi
-  yKLL8s9C0pLV4tky3ILf0uMy5pLp4u1C8LL0Ev dy+uL+QwGzBSMIkwwTD4MTAxZzGfMdcyDzJ
-  IMoAyuDLxMyozYzOcM9U0DzRINII0vDT2NTA1ajWl Nd82GjZVNpA2yzcGN0I3fje5N/U4MTht
-  OKo45jkjOWA5nTnaOhc6VDqSOs87DTtLO4k7xzwGPEQ8 gzzCPQE9QD1/Pb89/j4+Pn4+vj7+P
-  z8/fz/AQABAQUCCQMRBBUFHQYhBykIMQk5CkULTQxZDWEOb Q95EIURlRKhE7EUwRXRFuEX8Rk
-  BGhUbKRw5HU0eZR95II0hpSK9I9Uk7SYFJx0oOSlVKm0riSypL cUu4TABMSEyQTNhNIE1oTbF
-  N+k5CToxO1U8eT2dPsU/7UEVQj1DZUSRRblG5UgRST1KaUuVTMVN8 U8hUFFRgVK1U+VVGVZJV
-  31YsVnpWx1cUV2JXsFf+WExYmljpWThZhlnVWiRadFrDWxNbY1uyXANc U1yjXPRdRF2VXeZeN
-  16JXtpfLF9+X9BgImB0YMdhGWFsYb9iEmJlYrljDGNgY7RkCGRcZLFlBWVa Za9mBGZZZq9nBG
-  daZ7BoBmhcaLJpCWlfabZqDWpkarxrE2tra8NsG2xzbMttI218bdVuLm6HbuBv Om+Tb+1wR3C
-  hcPtxVnGwcgtyZnLBcxxzeHPTdC90i3TndUN1oHX8dll2tncTd3B3zngreIl453lF eaN6Anpg
-  er97Hnt9e9x8PHybfPt9W327fht+fH7cfz1/nn//gGCAwoEjgYWB54JJgquDDoNwg9OE NoSZh
-  PyFYIXDhieGi4bvh1SHuIgdiIGI5olMibGKFop8iuKLSIuujBSMe4zijUiNr44Xjn6O5Y9N j7
-  WQHZCFkO6RVpG/kiiSkZL6k2STzZQ3lKGVC5V1leCWSpa1lyCXi5f3mGKYzpk6maaaEpp+muub
-  V5vEnDGcn50MnXmd555VnsOfMZ+goA+gfaDsoVuhy6I6oqqjGqOKo/qkaqTbpUylvKYupp+nEK
-  eC p/SoZajYqUqpvKovqqKrFauIq/usb6zjrVaty64/rrOvKK+dsBGwh7D8sXGx57JdstOzSbO
-  /tDa0 rbUktZu2EraJtwG3ebfxuGm44blaudK6S7rEuz67t7wwvKq9JL2evhm+k78Ov4nABMB/
-  wPrBdsHx wm3C6cNmw+LEX8TcxVnF1sZTxtHHTsfMyErIyclHycbKRcrEy0PLwsxCzMHNQc3Bz
-  kLOws9Dz8PQ RNDG0UfRyNJK0szTTtPQ1FPU1tVY1dvWXtbi12XX6dht2PHZddn62n/bA9uI3A
-  7ck90Z3Z7eJN6q 3zHft+A+4MXhTOHT4lri4uNq4/LkeuUC5YvmE+ac5yXnr+g46MLpTOnW6mD
-  q6ut16//siu0W7aHu LO6470Tv0PBc8OnxdfIC8o/zHPOq9Df0xfVT9eH2b/b+94z4G/iq+Tn5
-  yfpZ+uj7ePwI/Jn9Kf26 /kv+3P9uY3VydgAAAAAAAAQAAAAABQAKAA8AFAAZAB4AIwAoAC0AM
-  gA3ADsAQABFAEoATwBUAFkA XgBjAGgAbQByAHcAfACBAIYAiwCQAJUAmgCfAKQAqQCuALIAtw
-  C8AMEAxgDLANAA1QDaAOAA5QDq APAA9QD7AQEBBwEMARIBGAEeASUBKwExATgBPgFFAUsBUgF
-  ZAWABZgFtAXUBfAGDAYoBkgGZAaEB qAGwAbgBwAHIAdAB2AHgAekB8QH6AgICCwIUAhwCJQIu
-  AjcCQAJKAlMCXAJmAnACeQKDAo0ClwKh AqsCtQK/AsoC1ALfAuoC9AL/AwoDFQMgAysDNwNCA
-  00DWQNlA3ADfAOIA5QDoAOsA7kDxQPSA94D 6wP4BAQEEQQeBCwEOQRGBFQEYQRvBHwEigSYBK
-  YEtATCBNEE3wTuBPwFCwUaBSgFNwVHBVYFZQV0 BYQFkwWjBbMFwwXTBeMF8wYDBhQGJAY1BkU
-  GVgZnBngGiQaaBqsGvQbOBuAG8gcDBxUHJwc5B0wH XgdwB4MHlgeoB7sHzgfhB/QICAgbCC8I
-  QghWCGoIfgiSCKYIugjOCOMI9wkMCSEJNglLCWAJdQmK CaAJtQnLCeAJ9goMCiIKOQpPCmUKf
-  AqSCqkKwArXCu4LBQsdCzQLSwtjC3sLkwurC8ML2wvzDAwM JAw9DFYMbgyHDKEMugzTDO0NBg
-  0gDToNVA1uDYgNog28DdcN8Q4MDicOQg5dDngOkw6vDsoO5g8C Dx4POg9WD3IPjg+rD8gP5BA
-  BEB4QOxBYEHYQkxCxEM4Q7BEKESgRRhFkEYMRoRHAEd8R/hIdEjwS WxJ6EpoSuRLZEvkTGRM5
-  E1kTehOaE7sT2xP8FB0UPhRfFIEUohTEFOUVBxUpFUsVbRWQFbIV1RX3 FhoWPRZgFoMWpxbKF
-  u4XEhc1F1kXfReiF8YX6hgPGDQYWRh9GKMYyBjtGRMZOBleGYQZqhnQGfYa HRpDGmoakBq3Gt
-  4bBhstG1QbfBujG8sb8xwbHEMcbByUHL0c5h0OHTcdYB2KHbMd3R4GHjAeWh6E Hq4e2B8DHy0
-  fWB+DH64f2SAEIDAgWyCHILMg3iEKITchYyGPIbwh6SIVIkIicCKdIsoi+CMlI1Mj gSOvI90k
-  DCQ6JGkklyTGJPUlJCVUJYMlsyXiJhImQiZyJqMm0ycDJzQnZSeWJ8cn+CgqKFsojSi+ KPApI
-  ilVKYcpuSnsKh8qUiqFKrgq6yseK1Irhiu6K+4sIixWLIosvyz0LSktXi2TLcgt/S4zLmku ni
-  7ULwsvQS93L64v5DAbMFIwiTDBMPgxMDFnMZ8x1zIPMkgygDK4MvEzKjNjM5wz1TQPNEg0gjS8
-  NPY1MDVqNaU13zYaNlU2kDbLNwY3Qjd+N7k39TgxOG04qjjmOSM5YDmdOdo6FzpUOpI6zzsNO0
-  s7 iTvHPAY8RDyDPMI9AT1APX89vz3+Pj4+fj6+Pv4/Pz9/P8BAAEBBQIJAxEEFQUdBiEHKQgx
-  CTkKR QtNDFkNYQ5tD3kQhRGVEqETsRTBFdEW4RfxGQEaFRspHDkdTR5lH3kgjSGlIr0j1STtJ
-  gUnHSg5K VUqbSuJLKktxS7hMAExITJBM2E0gTWhNsU36TkJOjE7VTx5PZ0+xT/tQRVCPUNlRJ
-  FFuUblSBFJP UppS5VMxU3xTyFQUVGBUrVT5VUZVklXfVixWelbHVxRXYlewV/5YTFiaWOlZOF
-  mGWdVaJFp0WsNb E1tjW7JcA1xTXKNc9F1EXZVd5l43Xole2l8sX35f0GAiYHRgx2EZYWxhv2I
-  SYmViuWMMY2BjtGQI ZFxksWUFZVplr2YEZllmr2cEZ1pnsGgGaFxosmkJaV9ptmoNamRqvGsT
-  a2trw2wbbHNsy20jbXxt 1W4ubodu4G86b5Nv7XBHcKFw+3FWcbByC3JmcsFzHHN4c9N0L3SLd
-  Od1Q3Wgdfx2WXa2dxN3cHfO eCt4iXjneUV5o3oCemB6v3see3173Hw8fJt8+31bfbt+G358ft
-  x/PX+ef/+AYIDCgSOBhYHngkmC q4MOg3CD04Q2hJmE/IVghcOGJ4aLhu+HVIe4iB2IgYjmiUy
-  JsYoWinyK4otIi66MFIx7jOKNSI2v jheOfo7lj02PtZAdkIWQ7pFWkb+SKJKRkvqTZJPNlDeU
-  oZULlXWV4JZKlrWXIJeLl/eYYpjOmTqZ ppoSmn6a65tXm8ScMZyfnQydeZ3nnlWew58xn6CgD
-  6B9oOyhW6HLojqiqqMao4qj+qRqpNulTKW8 pi6mn6cQp4Kn9KhlqNipSqm8qi+qoqsVq4ir+6
-  xvrOOtVq3Lrj+us68or52wEbCHsPyxcbHnsl2y 07NJs7+0NrSttSS1m7YStom3Abd5t/G4abj
-  huVq50rpLusS7Pru3vDC8qr0kvZ6+Gb6Tvw6/icAE wH/A+sF2wfHCbcLpw2bD4sRfxNzFWcXW
-  xlPG0cdOx8zISsjJyUfJxspFysTLQ8vCzELMwc1BzcHO Qs7Cz0PPw9BE0MbRR9HI0krSzNNO0
-  9DUU9TW1VjV29Ze1uLXZdfp2G3Y8dl12fraf9sD24jcDtyT 3Rndnt4k3qrfMd+34D7gxeFM4d
-  PiWuLi42rj8uR65QLli+YT5pznJeev6DjowulM6dbqYOrq63Xr /+yK7Rbtoe4s7rjvRO/Q8Fz
-  w6fF18gLyj/Mc86r0N/TF9VP14fZv9v73jPgb+Kr5OfnJ+ln66Pt4 /Aj8mf0p/br+S/7c/25w
-  YXJhAAAAAAADAAAAAmZmAADypwAADVkAABPQAAALA3BhcmEAAAAAAAMA AAACZmYAAPKnAAANW
-  QAAE9AAAAsDcGFyYQAAAAAAAwAAAAJmZgAA8qcAAA1ZAAAT0AAACwN2Y2d0 AAAAAAAAAAEAAQ
-  AAAAAAAAABAAAAAQAAAAAAAAABAAAAAQAAAAAAAAABAABuZGluAAAAAAAAADAA AKPAAABXwAA
-  ASsAAAJ5AAAAlQAAAEwAAAFBAAABUQAACMzMAAjMzAAIzM2Rlc2MAAAAAAAAACkNp bmVtYSBI
-  RAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAA
-  AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABtbHVjAAAAAAAAAAEAAAAMZW5VUwAAABIAAAAc AE
-  MAaQBuAGUAbQBhACAASABEAABtbW9kAAAAAAAABhAAAJIjAgAqqcBCT4AAAAAAAAAAAAAAAAAA
-  AAAAdGV4dAAAAABDb3B5cmlnaHQgQXBwbGUsIEluYy4sIDIwMTAA/+EAQEV4aWYAAE1NACoAAA
-  AI AAGHaQAEAAAAAQAAABoAAAAAAAKgAgAEAAAAAQAAAoCgAwAEAAAAAQAAAeAAAAAA/9sAQwA
-  CAgIC AgECAgICAgICAwMGBAMDAwMHBQUEBggHCAgIBwgICQoNCwkJDAoICAsPCwwNDg4ODgkL
-  EBEPDhEN Dg4O/9sAQwECAgIDAwMGBAQGDgkICQ4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4OD
-  g4ODg4ODg4O Dg4ODg4ODg4ODg4ODg4O/8AAEQgB4AKAAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQ
-  EBAAAAAAAAAAAB AgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhN
-  RYQcicRQygZGhCCNC scEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RV
-  VldYWVpjZGVmZ2hpanN0 dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4u
-  brCw8TFxsfIycrS09TV1tfY 2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQ
-  EAAAAAAAABAgMEBQYHCAkKC//E ALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXE
-  TIjKBCBRCkaGxwQkjM1LwFWJy0QoW JDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZX
-  WFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWG h4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5u
-  sLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp 6vLz9PX29/j5+v/aAAwDAQACEQMRAD8A+To438
-  n5HVipGCR1q/Em6JiwOc9PrUEKbY8KCd3SrsUZ UfNk7sZA9ayje2jCbjHboWoh5gIJCsp71PH
-  ErQltrDcfXrTQvz4I4zwAeasLE8bcA4HTNNU07u+o oKLd0yaJFEWQCGwCD6CtJBFsOCSx6nNV
-  wuxE+Q5HC59KsxxuACNufUjpWjp33ZLm0TwpsdgnO3HG fWrSjEnG7nr+VQRIWYqQ3J4q7GMNn
-  OCTilaNxzaT1Y+NWSJQw6Lipo13RM3pgfjUa5RzuO5asxKi kEkYA6VqtI+pLaWhZZRJFGDlyM
-  kY71MgUIecgjn61HbguCjoyg9+lSxoVbDHbnkkjpWaj0fQldri g52+4yaFj2y8AqvbmlCls4O
-  DnAJ9Ksqylxxz0Fa81mrIt3jHTqKkW/DZ5PJxUgQhmByXBz+lAAUA k9D2qcbAFZTuPcntUOUm
-  7Iq17SYigNGoYbiF7UhGJfQAZz2zUiliduRwdtTkYQhSFXd1NDk927lR Scit85kG3gnHFLhwA
-  FHOc/Wp4wNuVHHc1IACxB7D16VE2+a6QX3uiEJlD8pyTkj0p2394QQSQMYF SnOSMhe3Sm7Cjq
-  mecck1fNeOpMoprRgFOCOetOcMSrHg9elPAxIN2MHkcdqcRltuDg85rG0m9EFu zI/LRWwAScZ
-  Jz1qdYQ6EkYZe1KiFnG0qPXNPwSQpJI7Y705yfRltSe5XdHLbu2enpT1HzorHOBjH tUmxhkkP
-  j+VTJGwYFgNp6k9qXncIzTViAxgAjsPU0Kn4euas+WcOx4GaBHk7sL1GM96q65Xd3KjF W0ZFj
-  aSQQ425NSrGSARwTkA9s0qRqCSenQVZCrsO0MOelRKSTSSM3q9Csy5Us3LnH51IYyYs5zg8 U4
-  JyTtJwanCsEwMHDZxjkD3q4JNle8rscgySOM/xe9O2sMdTjJx9KmSJt7FgASevtT1j3MCucg9/
-  SpcnfVGcVGz1K5A3K5545+tChshh1PUmrYjUxlQCy57elBSQPwowDjmm9VuNP3WV+EYEhsZwD7
-  1J 5J8hPmBPU+9WFBEhLAcgHkd6MFQvTI45PQVV9dUOzbuiqy7QY14wc59qV41LYHJz61Oqqck
-  5Ck55 70BAH3N+B9aXMloWm4+RD5fBU8Z70/CGIIRkgCpH+UZYZUd6REClRz64PUVUWum5Ls3e
-  40KOWPJJ ySO1O2ARk7SecjHrUx4G7aCuc1IIt5G3PqwpXfVA1FSRXXPkruO3PApArlxhgFAw1
-  WOA4UgLzyT/ ACppUuu3B2selWvd3RDTTd1Yr/OZM54PU+1QqDu5OwDocdauldockfTNQAttBl
-  AKdiB1pdW2i3Hm V0tCA9HwDgNjFVHAM24Da2CRn0q80eWPGFIz9DVdo+u75h0yKiN4PRgrRV7
-  3KgDbl24B5xnvUbB9 x2jAH86uBBgsM5XvnpUBDEE7lJ7itLoEkiIKwO5Dgn1HWlbywxDk5HQ+
-  9TE7odqDaucjPUVGw+Ut wxPYCsVBbBy8xG65jcHJycDHeq4j3LuHAA+6fX1q9jeMgDJ6HFQbS
-  YsZ6frXRBNJ3JbtuisBiTK8 8jj3pXZyjsOCCOoqfaDKCo+975pxVhHtwAMYJNZ631FzK+xS2h
-  gxYcqvr1qIYDbiCMj86uGPDBWH TuO9Q+UCgC/fz1NaXhs2a+0SVkQBR5me5/Wo2CkMGyvHU/W
-  rRTM23DZzyewprKwKbgSMdMVlzLWx GiaZWZjgncMdAKh2MZPu4wME5qw6cL8v3RSNteQqnUD5
-  qSduhUndaFJ0zDg9R1xUBjDJtwdpXIIq 4yb3L7H9wTTHXbBtTHzdCaq/K77icVoomeYiybHO0
-  d6rSJt6EEdiexrTKtxsXLY5Paq7RMJgSAV9 AO9aRloxwhzbsoup2LzkHjFV5EJCg4Cgg5J71o
-  vHvZQT8oyenJqJok3spy2RkUmna19yNFKyZmkF Qp77TkfWmYAUKwK854rQ8tGiBLLnuPU01kX
-  G/cCc8nHFRey1KbVrWM4oPvAhWB4J7etV2RfkUckN lauunm4JAHJOMVXlj2gEHoM5qKcYq/mV
-  Dkdmys20naecZGRVcqQAduATyPStJAB8q7Xz6dxULsm0 gRk49T1pTcl0M5rXRGaYwqAschhgj
-  pz2pohVSH5DAYPPerk4Aj2k8KPkJqMqhVsjA+8aykoyV1qy KrbdmcPbIxtyuVDk8fnU6rIGwd
-  ofkdO3rTIInVztB4HrV6AMW3Pznnnr9K0Ti/e6lxS2JI0Cpuxu I6Cre1WXBIyM8jtUaBWcFM4
-  PcnirO35gvOSMgY61cZrZjcHGWwi7iuCcj+Ee1X9hXaW4GOcnvUSq DtAIYDgEVbRCBubJwcVS
-  kk77EX5unyFQnapVjwfWrigjkHDcHJ5qFVIjD4G0jgkd6srGGm5IU4ye a05+idg93axKCN6kr
-  vBPIFWU2iR8grn7opIIwTtDAgc4qYRESj5DhelJVOgRkh6K5X5uFHT3NWM5 D56ds0kSkCMEdu
-  hqVEEm4ZAb+lNpLV7DhK716CAgAZIXb6ipCSUYfx54I9KcEGdzfMO3vUwUsQdp 9zUOSvciDs7
-  iRhfJAI3AEDOeasEqVZQhB3YzTFXksFOMAjPQ1KuWl5GOetOUrlNSXoBQHaOjcfnU ka5U8YHb
-  PenlOeDnjipowcruCliMAAVkqivoTKWtyNFwrZHy+3rTRlnYpww9RVlk25yehAxTdv8A dGQD0
-  qlO+xoprls9xrMCB8wyf0pCuWHfHenCPMuzGOeuKmSM7kBIZTyfX6VF9GPVOxCvLZPOD27V KE
-  bIJypB4PtTyquWCgkcdOtSohG35WbB4FKLk7hLyIwrGU7umck461OqnIBABxxgUoV15QBhyRxU
-  6eYeoyMfLxRe1rpBza3bsQZQjcfu9TUygsrkKewB7U7CBcbcZOOaeyB9wG4ZYdDilLlRLV43aI
-  TG uPmJ6cD0p21sBODjgcdqnxmPIU8cD6UuTtw2D6cYzQ46FySk1cjCfu8MMgHjFAQlNoGVz1q
-  4qghS VyT2oC4QYVjk5JHalC9rijOMVpoVkUhyQC4x0FWQB5bYG3d1Y/yp+z+JAct/KpnX5Azj
-  bz0NNTaY k4vcr7ZNoyQwHT61NtO44OM/p7U5doVdx5IPSpgCEAGCTxWmluxUdFqyMAhcHO3GK
-  cSfJORkAjp6 U9cFgMH/AGs96fszGV2n1xUzXSwKdyIE7GUjjqPWmMMjoTk8+9TjG7ZyzY5FLt
-  3KNwwR29KXw9Ac bNELITCVOGbsQKaAxkI6AdzVkgliFU7R3pdqm4YlSoOMZp82gcyk7EGNyjc
-  QwxggU0A+aXCYY+tW lTO3b3PXFKEKJwCcVSfvWsVztIgbe23cPy70/Y2CBnPXr0qVfmBVl4Jy
-  MU9IwAR0HbJ6Ucz6IzTa 1kyLYMDncWHTHU0NkAKFxjjOOlP2Ethn4HpSAbnz144BPNNy1CMdd
-  dSsWy43jdj26UhH948jsBUp QtIwxtIPT0pWX94GUHO386huI3Ho0UXjV3ZS5Uk5AzTRGFkJOc
-  dvarGBvxgk7eD6VHs3RKTuDZwc 96J3ve5bTatcpMSrPgD73PFJJHnHG47cjjvVh4w82GO3NN2
-  lmbkbRwvrRGpZak8qbK4RdoPc56U1 Yssc8Lj8an2FWA2kDrmjaSJF7Acgd6qE2nZAoroVzkRh
-  MHryR601lLK/RecdKsbVQhs5BOMZppUD LDoWyM/zpuUn5lUuVN6FFDhsgcKecUOQVODhifu1b
-  KjcSBt9TUJQqRlcE8Z60m1fUUpq2xAQxG4Y yM5yKiY8jcV6YOBirexgvIyvUkVXKhotuNp7E+
-  9J27ExlddyJkzGqA8g4+opgQ+YTuyoOfc1MQm/ axIIXtSIqHDchgp4zS5ujJcXazKnl43NnIL
-  fjTCWBJ+UZzxire0OMgYXnPNRMpZQNpx9KtSuh3Kp QH0BA4Gar/NuJVlK5wAfSr5HAJwQOw6i
-  oiBsJI2nODx1pqL6FOS27lRlj3ZUnntmogqtuyCBwTV4 qBDwPusB7moggxgMApOSKz5o3sDir
-  XKJiGAD/A3B9cVG4zCCAADkZx61oFi2F2NtyeSKg6wfKowD 0I6+9a03fWRn71ym0YEW3AyOp9
-  aq7Au4ckdh6f8A160Xj/dDdnPbNQeSCDuJIz69TVWuro0VmUHC 7AuGG3pVfyQ1xt3YBB4NaDQ
-  7Mt1LHHNRybWK7mULjhhwBUPmbuiZtRdkzLwF2quA5GR9KrvG29lY ckdfStJkJj3BVYLxkVCV
-  dUBxuycnik5a3BN82hQ2c/N8317VAY2JZuMY45q+6b0Jyc+npVRl2Abu F6hu2ayjPmlpv6BNy
-  scWkR3jy2LAnB9quLjesZZX+nGDTY1jLkYZT6E9asDHnMccqeKelryZTjL1 FjYKFB7cYq2u1S
-  u70xn29KYqLlTtPIz06VONznDHCYHUd61cby00RKcXezJgQASANuMgDrU6FimE yVwBmmIMbVy
-  B2JI4qwmVOM454GOoqXZIlOUVoTJhjtY8A4/GrCqC+FPze/NV0CEMNxGfSrKAL8oy W65PaiKT
-  WzE27WluWgxVtnG4kc46+1Wgrn7o4zwT2qqh+QO3UNjOPWrhP7kBWUELzSu001oRy20S J0VVG
-  7JYHoKkjAAdz8pNNjKsFVVZiF69qVmDBAM5x2rSMeZe87lXT0JFXmMs4GB/KnLkRhgxyR2/ Wl
-  2guoxyeeakj27UGQp64PaovJO6Qk3HbUWP7/Xv8ue9TkOzPtA4PpQEBnDg8Dr6GpSPkLA8Yxij
-  nTZq7qwJnYA+SSOwxzUwVlkG44OM/SowMptTjB6mpwoZSTnI7Z7VTb6iWj2H5wDlctjIPpTRyw
-  zn 3xT1RSRklcdc1IFCsGzjI9O9ZxUNbAnbWxXCKThSR3GT0zU5XaVXOWPp3pwX93uCk/NyalR
-  RyWyp BOM9jROS66E8zvoNU4I+Vl55JqULnc/IYniiMeZHuHQHk9jT1x5mARzzjHIp8umxq3ro
-  PXBVQMgj v2qQLu3jBUfWpPLOVw67SvI9akXaRxlm74PWnLTUjpdkIiHnsDkgHIqdFYxFmVcjv
-  ilCsMSLxz1N SspDc4xjJFQotyuLV69CGMkPyOnftineWwkIC5FPKDY69SDSKjFzjKgf3jRbRt
-  sbgl5Cbdy4YEYA BqTaCjIOdvB9alVG8xsLlcYA9akCYIAOecDNPmu97FJx7kYwD042kcdqVc7
-  djfMAOB3p3zbgOPfj rUobLDK9tpx2pRi7aohNX1GgKAoIB9Tj9Kbty6gZHGf/AK1WNoQhscA0
-  9VHILA5746VVkXGViEr8 4VO1WAFADt0xg+1TBQCCRnjOaDGrx/KOSOM9KhN3DmVyodyvlRkg5
-  6cmnsN8gYqykjBx61N5W5lH LEccdTStGQQAhD9GJqrpyDroQfO0ez15/AUpOTt2HINSiLPAzu
-  we9PIIBADZI4/xofI1sNMhKYkB /g6/So1VPMU/MCw/vVcyWhIBDY4IqIgAqMHjP+RUwV2xvfc
-  RP9Y3QkYwaXG+ZW3Acf8A6qGUlAFw CD940Z287d+ey0cvYjldrpjH+/k/dJzSIcHd/CR8pqZQ
-  Cxdl3Hdzjpmoir8jrk4A9PWtFcE00MIA BLN8xP6VEdwZW4wPxqc4Uj5fl7Z7VEyjcSu7BPU9A
-  aUtgcrtXehCQxcE460wuRKqEdRgVOR84Bx0 /P3prYAUYDY6kVCk7lOGlyFolCbm5btUBBVs42
-  qvT6mpMNwwbryBUwAywyCSfyrR3jZkxauVAoK4 bOM8HNC4yybfmPUipNuUAYZOfzoCsZAOAev
-  /ANamo33L+FXW5WZFEhHX0BpxXzHcgDdx19BUzEbi WXBJPHeo0UtJvCsgHBU+lTL4dTOfe5Xd
-  B5pZuMHIUd6iYZbvgkVbkG1TznHf0qFkzI46D+92qeZ7 iSRWcZn2nIbODzTCpGSMHB61YZf3b
-  ZGAO+eTVd4yA2MnPvQk927DVlKxG6jBJwcnk+lQmMFTjJA7 9KlkBWLnO3pinEfIQpHT8qpNtI
-  NU79Cru2odvA6NSMjcBTkY61JtJhDNjlhkAdKeU+UgOFbPJP8A KrejuOL10RVK7IyGI64B9Kj
-  2Ah9wPTKk1O0bFgjnbu6d6btAdhtLc4P+NLRa9yb62bKm3EQDA4xk ketMaM43Y/i6Y5FW2UHG
-  Bmo34PAy9KU7i1asirIGKY7kjgVEQSp3HbjjPqKsSKQTj0BNMPzbsYLd 89Kq+qsVfuQk5YFun
-  QAjioyp2KQDyc1aZThkG3JHSo/4FTBOD8xH6UlG6egnLQolN2dvQDnNVGBC 4AUg9citd1YLjK
-  nJxgcVUkiUQMG4YccU4ya06Cg0tWZ3lLu+X7uM4BqrInzttcH6VpHcG/2T271W aMoF55Kk+9S
-  k3rsaK6bszPkiITczAFuQPQVUMSlPmOQvH1rSePMALZLH37VWkiXJ2HaOvNVzWRPN b1OQ4YLt
-  VTjrxU8cQMiylcDrnHenIvzljjcTgAd6nXIjYN0B5XuKxTd9URHR3S3ARE5wAARmpo1Q hiQ2R
-  j5T1BpQF25DfLwQfapFXDuFBwTz64rW11ZsfM7bCoMHOCTjn61OpUv8yjJ6EdqbyoI5JPPW pl
-  GG46EdamMW90Wo6PUkCAN/CBnJOKsKp2fKC7dGqNYgmCT1NXIwPIC9VPP4+lVTcWmupM5K2jJI
-  1O1QBwTnj6VZjj2jcWyccj3qJUwqYJXnvVlVUBSCBk9D2qV7quZubY5RkEDIAHGKlVeMbSpzzU
-  aq AQc4GOBVhAH4JwelP3+UpxaW+g+NldSDw+MEU5QWlBAx2xjrTEVftDY5I61Nyr5IJPt0pcj
-  TLj7z 0JkY45IBI6YqQr8gHUDpxUaIABtB5PP1q7tGPccYNS0oscFyvQYnzH5cZPTFTKORwRxw
-  PWkC5BOM g8DFSrncFPUcim1bUUnfW4g+VMhSc9c1IY8y7ucA9DQY9/GTz3HSplAEOQDknvT3W
-  gruyY1FyhLn AHIx61LtBjDf7XNNCtySMZ6gU5cnae/92okubqNJLYkCbVIGMY605OeSAPl60r
-  DYM9MYxzTwMvgH APX0ojZ7scZN6MlVCyKXGAv4VKFUSsSQBnK+4qJA7Bg2Qo6L6fWrqrGdxUb
-  l449KblyqzYWdvIjV RvwPnDcn8KmweODgccinEYlAwMdqUoTIoLdOabWt2Jt3syHbmTcOucED
-  uaVtoVQ3BPGTUxjIz6hs 5qTblG+Xjd+lU5K1xrTV7FYJljlzgHOe1TbeSVVs49e9O4JcsMKT0
-  FSKQrjB4789awblbRAoys2Q KSrD5Tk8gnpVhUAKkLuGCTShN69yw6Uqn5ioBU9+atJuzsN2+H
-  uC5VyzggehqVETaBtzz69RTkiM krPj5SvQ84qRlOQxI2jsKeknbqNWTsmO2AH3HamfMpXcBnG
-  Tx0qTkwED0zn0pu3OCRnjinFa6kNN qzDsc8DI5pwB35Jy3b3p3BTIBA6nNAQl+CM96hrW76By
-  WtYjA+YKpw3XB600LIsvIOO4P6VM0Yxu AO49TT8HA7GqUU3ce22hCMkDPDdzSYUjef8AgIqXy
-  y2Rnae9DR7EHoOopJR72BRs1Z7kecJxt56i onGEOB8zDtUyoAvBOKQ7BKvXJAzzTh1sCa2K4f
-  BVf4R0A/nTF5OC+M9qtMIyWO3B6A1CF3bcA8Lx xThNrQJLaxExHmE9RxgetM25cAErg8ZqfGE
-  IYYbFRH5SgK5yOPXNTzeYN3diEjAOBnLcYprIRIVY YGOtT7S67sYYjcaZ5TYJIOc4BpJWepLT
-  tbYYRmIKFI3dKhIw6jnuM9quKH/dgjgc5xUG3Mm/rk/d x0q0+bQtVJR0RFyGVSQcDgUMAXkJU
-  gk5OP5VPtDOcckHtUcyEoSAVJPA9Kq8X6kc3NIr7cyAMDgj jHtRkrICSAT7VMuPkJyG757Gkb
-  PJK5J6YpO70YSd20VHUvHu3AnPboajbCOFOArHBq2w27VAHTp6 UEApjAPf6VU2r2HotEUnU7m
-  Kjfnt6VGwcnbt2kDnjp71aIDMVOdxOQe2Ka6kZ+916VLp3KXLzLuZ +Nr84Y+9H7sx4XhzyRVn
-  y9z/ACglsY3f1qLYBDjGCT1o91oLK+4xwTGGjAbPUCoMZi+YgOOntUxy nVie4x2pzKu7jJDHG
-  aHZLREu97FSSNmdVLDdnAIFMbchCEAsBzVqRS0eSOfT+tRTZMTv6kA4pqVk KMddSmR8wDZwR8
-  xqPgP0zxx71ZCKpyQcBe571AB1yRuHFVKSauXBLUjI5BK4Lc4PVaj2neVcbV6H AqVVLMcfNxy
-  TTSDuBJ68GpgrPUma7kZCMDjIG7hqgWT5dp5OCOP51aZVdODx6VF5ahSxI3H5sY7V cWr+YrNL
-  QiK8DeOT0AqHY2/Zt4znJqwSx9MY4JFRYYHrhRyfrR7NpPQUm7FKdRvHXKjk+tVH+b7o IbsfQ
-  VpMv7sBgOhzkVAy/IW4AwO1EZpoqLcUrGbJBjb1YdiOlVJUGG2Ho2AOta7BQW6nB5qjKWZA Rh
-  cHJOOvvSjNteRK35n+Jx2zLkFgB1x3qwvlvCSDknuPT3pkKctv+ZmH5VbWFfKP8K+1S3Hlu0VT
-  UktBiKcxqMHaMfWpxuMhJGMcYNBVdyYyScZ9qlCjJOfl3Zya0m9UiHT1fMJ/GyhSnOSakRQck5
-  JH 8IPSnCIhiSmSGxmpYgysWABOemKlRvKyKUktiVUVlIySOuM81NHGpmj+96gg96EXeylDjHH
-  Tp9au Ip3cYP0p8zQRu9ESAHY2SBhh19KeFbaVHzKCOlNwjxkMD8w5we9Tqu3Z8hPfg011E2kt
-  h3lg4JyA Dz7VKuQcfLkHPPYUKMyZJ2jqM96kCq4BAZiTyajTVMvVR1YKpbBHIz27VaWMKvJye
-  3vUIiKybRke v+NWgCFBPJxzTlJP4SVGSSdxIwjOWyRnselWE+Y8fNkcUxAxVTtB+g6Va8sYIT
-  txnNRdKSTKbYCJ ieMrgjgVKsZYNjIG7IzzRGDu4BG08GpVXMiu+evABpzk2LXdkUauHOCMHqK
-  mUbZguCR0JPalYEKw PUdcCnxgNEzEYI9TWU00hWd7oQJ8mCc4HBqQIqKpzu29/Q0oBOFwATzU
-  xBCMduOeRUtONrlNydk7 EcQDIykEtnj29qmaPJXAK4680KOFbBJI7elPCbo1wduFJwfSq91dC
-  rPo7Eq/eUBflxxUwABOcgf1 pqACFN5UsecipkAMg3Hg88UoyVr2JVm7Dgm9t3UEZFP2hFBJxu
-  55pFB3gKrFgOlPKMV3N3PB7VTv a7GoJvYRow+5lYDP5mlXIZOp4pdjBFUtlRnGKkERBBIbnt3
-  FO91ua83LFJ7BtT5jwBnFO2jPsB19 KkCkgLtO3GfrSgEvgkAEdMcmkrcy0FGzW+gxQCoKgtzj
-  ilwROARySefapgm04UfNnnFKfvqSvXpU 3voTe70/EWNZd3P44qRwfOAAHPUYpEVmkYDpnjH6i
-  pwrB9nU4x9KmWjJu1Ig8vLAFTg9DninKCV2 gd+CalUk8A/MTmpFIbKt1rbm01RTjK9yAAyOfu
-  qRwB604ghAuMMcGpU6kDGD3I5FIqfMWJwVOMno aj3t0hTjeRCsZXJbGPrSYPmYP3SMZqcbiow
-  uQvf8aUhCVycEH7o61oovqGlyAwhFzye3JpPvNjnb jg1Ic/eLA59+lIMeaG2nG39ahxa3KbaV
-  2RqpPzbhjBycVEUxGoI5PB561YOzgdCOvvTijMSy8qDk AGs3U5CFzXuykw7DnHQe1NHCHjBzz
-  U+MlQwwCOPemMm98DGM9a1TuhtQZAdzEuudpOee1K8ZIjA4 GcZqVdzPtBG0j06CkMTAbVy2Dk
-  k0ot37F1IrS7IGDrnHQjFOKtt4BJH8qs+WPLKnOexzTFVlQKCc k9x0FJz0uZOloVlGZc5xx0P
-  WmlNrLkH1B9qteWeD0JGaULx1DN2HpVRWliZR5VdbFXauQAOvJwaJ NocgDdnpk/pVp4gTkgjn
-  gd6Ro2YLhQB6nnmnyor3U1YoFPn5ZeuAaYYzgAjLDg81om3KgMSOpxgV EFBfKc84PPSn7ttAU
-  le5RcEsdq/IMc1AEZpGypxnj3960XSQEkqcZwABTGDIuSuG7E96b006im2m upRMYDE49vrTcE
-  5bBzjvVzbwCwJpCpCBQMjHQ1jJNNXHvdGeRj5lznOPlqNVUMhUqX27SDVpk53Y YAVDJEzSDkK
-  DVJSW5KtaxTkwBgEE9+KjI4AwTkVZljjyfm+YDGPemmPKKB/31VruXzqBUGCp2ggA bagkTajD
-  kAt69/SrTnAcFW4P51WkHAbady9vWkpMKl3a5G2DHs7tzioZFbzNoAHPYfrUrhjhlO1Q e9MZR
-  5rLuJY9MdqqTWmolFpX6EGMZAYDuD60MCVBf0z9aTB3KpHzECjDAEMQCtJQ1LuyMhsZUcdO el
-  JsUplWAYDGPUVKcHpjgcj1NLjMK7gFbkkdOKpS+8ht21Kzrh/7xxx6YpOAuOhz0xUuR5YGRkcH
-  im7kGSfWhQbQlq7MpFSZNxOBjvUbkBdxGQTzV0puk44P9KqyREbSMYBPXvWnkJK7V9ikwwrDac
-  no KoyRjA7FupNarRsAxIJdT+BqnIoHJwxNYqd37o2r2OSVAH4GTjC+9SiIlP4hgYPPWiNd77O
-  hJzU6 AeYcnkeveiEWndijKXzGoCHGep5H0qdAAEfHBHBqRFH3mU4fJ4pUA2hdp5Hr0q/djqhR
-  ldXGkjyj jOSct7VYgwfmZl4OD6Gh1Uop2MrVaSNBGcDHPU9DRNqMdQ91LUBh5o3UjgnIq0oKH
-  LL8nG0+ntUK Bvk3LtYrk8dCKuqSQC/3OpBpJ6aIbTi7t7iCE+XkcEHOB6VNGgx0ZVbqSc0Ko8
-  xtpLcYODVlVxDw 2OOQR0qm77j1T1ZGisFYZQgcDAqzHt2lMYx/OnIMrx2qxGAJMbcEc896xem
-  w48sVdoYqc8DIIx15 pQgXDEcHg896kMbs8gzhQePpUmzKkcsMnJPrVQlpZDjo9BYlcxsqgZHT
-  PcetWUXy4+oJzSxx4hQn IYggCp0T5cBSXHOaiSbIkuXYYiK7cH5icnBqQja4KA4VtuMVKNq4b
-  GWyMYqRkPmAg9fmxVySSByf qVwuGJbI78+lPXaTtwMZ/KnbSzgYYnOfrTRw6sw+XoR3xWerRV
-  lF3e5MFKjOw4HJz1p+A8oySccq PX60IPlDBWwTzk9KaquFJXnBwPU1Lbej0Jv5jWB8racx5xg
-  +gqeMkZx82FI3evtTQvmJgttbpzTx Gylg2CMYAFOyvqbuCfUkiX92rZGO6+lW1TIwQduetQxD
-  5WVvbOfSreAm0cgYzyaOfo2TNxi9NRMv t447fWpduIvusefu55FQ5YMDj3z1Bq0qsTubPsBVq
-  KWz0Ks762EjjBwwPc5zUvJcAggAZ3HtQPvk 8BfSpQrllHXNS7bszlve43nb6+9TKp2EgBsDOA
-  OaRYz9OM4zV+9vZb65SaZY1YRqg8pNowPp396i bk9LaepajzPRmfg5BKnlue1TMmZcAHJ5APp
-  T+NoCdz370pG1x/Hx2pqLbuK1t9xgRkXeCCCecVN5 b+Q/UH1oQMEVWUk54o2s0yqrMuBg5PU1
-  pZ6CteWoKo3biMBTyaVTmMhyFOPSgxs0PzffHWpApxyM Y4FTy8q3KlFNakQiJYdQQeT/ACqRB
-  hQuQMg4BGakAyoyOB3po5OSmMjr7VTTb1Rnz31vcRQNmRyp 600xqJ+clgORnmpAMoB1Q8ijaD
-  8zHH+16099UNR1uV2QbuhHp/jQFXaC/BwenFWFUFJG5PHY1Hsd WBbgEdetZ7p3ZUrIiCEZC9y
-  MsfaoWOZCMhc9fSrbgEsGVjxke9QDbnLAL8vfvRG27VxKz2IlTOD0 471GUUkHIABq0QGTABPP
-  H+FIsW4LkHimhQ5lqyExlV29s5yKcFcENwDg9qlGPPK5G0E4HrQYyeit nPXNXSWqvsZ2VyFjn
-  eo4bIIzT1jTbvY4PYetTGIh8hRtH51IqEE5TaeM0pRXQ1bKeHIPy5xx0p6R F2Bx1HDdqvqik5
-  cbDg/Q0rRhIDg4GOtQ5JWJk/spbmf5Q3Hb3PGaaqDewPYY/Grvl7lDZAyMA4pp UGfnhh7VUUK
-  a7lVe7MM7fWqzrlchcAHJxWg0YGdoJWhYSVK4ySMnPtWqilqNNJ7FBl+fAzzVdoix GQSoHb1r
-  U8k5Axs5PXtUHlPg8fMvUe9C0d0yYyd7GcIct3z6VE8e5dwyW9PSr5+7u2kjdULJzuCk HJyPW
-  p13Zo7bGcVLSsM/MePpUEifeHBx1NX3Tjbzu/vYqCQARAEEsfQ1knF7MUU07FCRG3AhR24x z7
-  1BJGBvYZX6mtArlivO4HNUpPvsCOR3q1JPboHNLmKkoUx7sbiRyAagkGYgeSw4xVvZhRgZbHT2
-  qsy7mIH8XQ0Jx7g+V9SEgDkc+tRBSCHHHPGe9Tsq5ywO7HrUHP8AF8wWko3ZCiloiJgGdjkfSg
-  nI baARxjingMYCP4euMc0mEIB3gY+8K1lBRHzJ6kIUs2NuHz29aCrdcZI4/OnHGVfJPGBj+dO
-  KEqVA IyecnvTSW9ynOzTSGPGViAwCOnHWoXTbg5Hr9atlGVCHXPriq7cI2MZDDnqKE3bUUOaW
-  xHtJTBHI NV5CMgEgHkirjcy/eBJ64qPYm8qCG5y2am9tQta6KbqcbsZz1xWdKFXLMpJA4wa0Z
-  G/dfM2FJzmq L7TMSGAX0PUirjFv3rCglbU5gI4j4252nGBT448oqgdfzpVJVmABGehNTopfGC
-  MjP41Ki0op7E87 WiSBFILqc8HP41Oqh2OGAOMn61AgKguMlu/vVqMAptcYz07YFU6cbrW4NRX
-  QkWPFxgkMAD+NTeSS BlwOfTpTWXaVyCX3Yx7VaUOzZUcZwKlT00exMVZjfKZ12hup/MVaUMAd
-  zKADjBFLs4I6joAvUmpo 1fG35ST1z0xVJprc0cm9LhkqAFAzj045qZIzu5OSq80KAQC4LKRzg
-  4xU6D98Aepx1pN8q0H7vKHl k7XBwAatJy24gknoaiWMMw56enSrMarGuQ3bvzUWctLi0+YBVz
-  xn73Q9c1LHDlgTnGfyqeJN5DYA 559qkCncBjAPT3odrWW5MXK46OPERJIJAyfzqXy2EkpJxkZ
-  XHepY9oX58cHp6VJtVwMkjBznPWiD aRUpcysiDYcAYIPoamcr5XzIyYbrUwUljkg5GcntTfvb
-  gAGX3qGtSoK2+xERgccseSSOBTNi7Mry QclR71Y45DEc+1Q+VsACFsk561UU+4rx6gpIifeQA
-  TwKQ7vOKFW2Zxu9Klk+cfLjrxxSkseA3XkV KvLYPdWohUxlVGNucZqXbk5GB3570iYYDJyOuK
-  lUZJwQDnafapd47sFG7HwuGcHIIJqYrtUEjLHr UIj+f3x0FWAm2QJnIA7mhRb1iNQSJljUgFs
-  57c1Y2ttByB/eqCIh5VHXvVlQFOfU80Wa3KkmtEOw fLCLHjA9OvNSiP7rbjkjkUcHAwSMcVYV
-  Ay7gu0k8Amna7uhX8hnlqNp5zjBz0zT/AC+eF6DvUywn eRn5QevvTzFzuAI7EUdRwik73KqJw
-  OwBxzUm3EXylQcd6mCOFYcD5snPenhVVtxIJJ5HoablO+hT ty2GBGf72MZyGFBDbUyoGfQVaA
-  O3gAY60hVyCSFDdv8AGjfcmMYy1IgvGADnPfvUvlZbHY5PFAUF l3blyM9elLsbJJyOMGs5pqV
-  0LlTVrkBQNnnDdMZpWGCB9457DrUoQE4OOBTdjbeBuOeNv86pK8bi Sa0uR45XgAE8CkIBf7wH
-  J4x0q0wIAUqOnJxTAozyRhTx70lrrsDepDtG0IWGc9cU0g+bjBbH86nO 3eSRnB4pAp39MN/Oh
-  WauKz2ZAc4XbjJ5INQFQxOEJIHGKuH74yVB9cVGw67APbFXDUFHl1KoG+P7 rEg9qeiHYeMHPe
-  pwhRctyp7U8gKv3TkcDjrmhtDjdvQhaLMZKDcQc5pyIVZOOCMkGpEVs9CFxyB6 1KxJcFQMdia
-  SvYSp3umRffBKr3wMVIsMjElmGSMkY6elShQsauDkk8gdKlCKWGCSV6gd6Iu2liL8 qsVvLDqF
-  79/rR5DNK2WBAGDnpVsR8YwQcdaapYAZIPvjrT1GpaalIoVwB0757U7ZldxXqcVa2jyv xxz3p
-  AoVsO6sMZzVSiujLeq0KjRfMQAVPoaaAWHVSPbg1awAz91PWo9i7cdT1wKztzego766FYqd 2W
-  bPrxUZRSd24sOTnNWNowzFSOw5poT5cDA7E1qlrvYTSKDoVL7cbcA59feqzLuwWyfpxmr5DZIT
-  BUdPpUUiZB2kYbr7VMnfdjaa3RmvtbHynHtVSRFwDtJwOMelakiquFIKkjqaqSg+Ruxls4z2xU
-  cz a0KppddTKnD4QqOW6VVmQguA3zZwR71pN0wc5zwKqug2sfmOTkVV7eQNqKM6XIjBHBIxVdg
-  Rkg5I 4Aq267gcsCR0A71Ds3SMWXaCRn61T1WoorS7Km1uMjGBTTwhJXBPXjrUroVbuU3du9I+
-  Fl6qeMjN Du3ZA4EDDahYnAI6U0xlWOFGcDPvT8HY2c7u2akWMeXnlznrmqlLRGclGG/UrBAXY
-  N6jgdqD8vQE 89TUmAXYchup96UHjdkYA446U1d9DW15e9sNyfNAxkE/pUPAOBjGcgYqdchieK
-  YynfkjOWolG8bh F2TRXIJyAueM8VAAAzNnDn9assA4OzcSc57Ux1VoY/UDqO1EWuVXFdJGfKo
-  LfN2GMVVdQI/ubsdV xzV+VSCwAPzEduaqyZIZsFfqaqN09xt30RzGAJMLjG3gVLGEEMW/qD1F
-  RjcAHI/H1qYHLsevoPT1 p662MG4t2JT8+CFIUHjijZnag5GOfpUwLBlxjaVwvFCEHIzyp61nG
-  pNPRF35rpIlJbJPbjFWowRG Cx6dPU1WBLI2Msc1OoHkDJI9vSnyXVy46R2LCKwk4X5BjBqym4
-  Lk/Xiod6MwyG4461OAw5ByB2NK K0ZEo/zDtuUKg7geRg1ZjU+WeMgcD1piA+YdwGVHHFTRjbt
-  ZeMjBz70NN2Vxuy2JwihcNkEdcd81 OBGG+ZgMdSKjjyVxtYe5HWrJVMJ0PsOtTfQbtzWHqFWJ
-  eCDmrCK0sakcbT0oVB5TKcbhknNWYubf BOCcEKOopw1iDVtLD0QmIsANucY71Kik4yuec0kSF
-  pHboB2p20E919M1K6hyXYIvzcZYHoe30pyx gBU+73P0qZFORtIyD0ppVmlbAANKTb6g1LoyB+
-  5Tpu7imMjYJzyeRgdqtDhcFc4HT0ppHHHzZ6Yq nIlS0sQlSqk8YA/Ko/KbKMCPKUZNWCreWpz
-  kEcj3pVLbSqr94c8dKhKUXdMcFf0GgDfgsPy6VIqj YAx9/rS7dibQCQeckU5fvBQBnPU1HNdm
-  junoPCrvycBck4FTKrFchhgnqeabG2VZTjgYB9aspGdg A9OnaiLktBx3HJGFB44z1xViNCbgF
-  VO0DAz2poBOAAcdqtqTvUMM5AB7Uc0ktyLvcUJ83TcAOcVM qAzEnK46Aninhf3hO3p39akZN8
-  vPyj1p01Lc0i9fUaqkZ6lieBUyBgpyj+1SxodqrjBweT3qVIiQ OowepqrX1sZyiQ4byk2jnHc
-  U5YlLtvGT2IqYxsYiFOSDg0oRliA4PPPrTXky3tqRIMlh2xT3Rtqc YGOM09FDOF6Lg80/6AkA
-  49aOV7ia1uV9u9tv3mI5pAjE/N0I5qwvysTlVOeQe9GwBiOpxnFG2iJc tdNCHywGIJGDxkd6Z
-  tZQWC7WHBH1qyCAjAcjOeabyMbs5I5JrJxaditdSEqdoUDH071GinkjDDIz kdasBVY/KrA4OM
-  96Ty+VxnC9MGr5rKxMo2SZAIyMgDqeSe1OdSBwuQDwKslQfYAdD1pgjxyTwOAK FZopR01Kyod
-  58wbe3P8AOoWAVioBGF5Iq+yhYMN14yfemsmC3HOaIvleocz3K+C2FI4zmnYJjAIz /M1KEIVe
-  Rzxn0p6ALJubOBkCqnZvTUGVwu1WDKQM+vNIFO8hmG32FW3BHJwf6UhwULdeelLmsiYu T6EeB
-  nIDA+hFCBstg/NiplT5iMb365BqTO2MkDDg5YU4zsu4KWpCBzywGCM5qUL83IBUDjFOdV3D 5h
-  83r2qMKu9s8jtg0KSlqx8rlqgKl5QUX5TyM1HtGWPAOec1OMoMZIA6AdqaQoRjz9aLvoK1tyP5
-  JeGwvFQuqqgIP3jx7VPgHAPOB2ppTn5iMKck4qnZE31K7Rgjbn5aidh5RIyGLVaPKjjqQTgVA4
-  GT gYPai19Ane5WkwUO3GSvPvVUjEOHDZP3jVzcykEKHGeRUEjP8oIzlc5os27Ar7dDPlUBDyT
-  gd6qh Q4DE5GOlaLKpBBbnghu2KpOGbG3AwcYx1pabLc1im42RVZQMAfMQccVRdWBPB4/WtHcC
-  zYwMYxkV UcNhgSFPv1NRJyi1clU0tDPkj+QsoxjoRVKUtvywAbPKitBowoIfIBHFQSKu7JUlg
-  vBFVfTVaj52 ml0KZA8rHUkVWdNx4OCSO1XnRwm47QPYVHngYUgjgn6UczW24Nte8iu0P7/ZnO
-  By3bNI5bdtVtuD gD2qVl3KnUk54B5qEI7H5R8o4IPWq1t7zH5takYBUMAQ3PIApuTsG5SOMmp
-  2iCsSScDrTCcp9OmK 0g7aolct9iONgQoZSM8g4psgCjG8D0OamyA2DgAdD601gwTGwnjk1Upa
-  3JUnFpWKyjM2Mjj0HFQs NpUNkGrMqb4s459qrEMgALDnnkVKSfW7E3e8iGQ5Dbhxk45qkcM+5
-  RkYzzVxtxJBxVSRvLj27eB2 xzTUWjVL3fM5bdu5cnGOmasjBb5Qc/xH0qoqhQyuQ4H3CKsJIq
-  hVJwT61PNFrTc5X8PmTqHDFj8w xxjvUy/eUkblzVbcywkEgNnj3qdJGdQw2/THH1ocnbUtO9r
-  lsMoBKgc9DntU0aYLfOOeTxVdFVnC qdwPX2q2VUZ/hI6AnNSk0xNJK1ydAqbSRxyOKmjznAO5
-  umPSqy8sMg7Satp/ruy55zitG0tLjUep MnDHnBJwc1aViCxwuMDjFVwvPykEnnpVmI/MOMA9c
-  9jUTit3qhuS5kmizHubO4AAHGMVJ5W6bI4x 1zTVA8zkkDA6dc1PuYBduGDdRilG0dEaJuOqWp
-  biIZUyMnGAR3FWlCrKMc5HNQxJt5bk9QasY3Ho cHr60Kd2Qvi2FRMLnc3XkZqwi55JyAM9OlM
-  wwwCNzZxVpcKi5BII5NJspxaIwGCAhSvzCkO4NIcY GR19anZQ0eAxGeQKiAwzNznPSmttUSo6
-  7jDhkI54HNR5CDBU4PerI3BMHBweOKMA4LY9MGlJ8ysy tnsVuSS33jjj0pVA8oZBJ6ilB2DC4
-  INOB/eqTzgHJ7VlPRWG4ybsNwwXJztqVI1eQnngc+9NJY8h SwUZwKmjBUHaDu6Gm9tB8slG1h
-  8cYAVlIPHI9KsqpUsRjnqPSkAywBG0Hmp40Y4YDA60r31Y7skT HIPHNWSmTnBOaIugAUk44Pr
-  VgKCRnuOT2FF1zaISs2EasEAYc/xfWrKAZGcHmnImX5yVx2qcLjrg 8gCtZVL6Gb3uMjAMmATk
-  dasAMFORwMjNKoDBmA4AxkCngcKAwx1JxUX1vsauOl0AjcL1JJ9KFG0Y bIXvkVJltz5I+Xoe2
-  KeD8/zY2gdxQrtXHPoQhQWODz2o34l+bgjqcdak48wgKeRUY5yx6elVGCl8 RUrdxMKzNn74pp
-  B5ZSCdv+RUu1g7BsEY5I44p4iw5wGOzGMd6TcY7shuKGbRtweh6cUzZuBxk461 OVBUNyAOcUg
-  VA+TwGHOegqVKz0E3G2pA0Z8xSMgEYBpmwGIBQwYnAFWvLyowR14B707YWkDKBn17 VV0yeezv
-  cg8vJUhcr60YViQcepx2qTBE2F+YL05qdkUpv4B6ips2y29SiYmfaoOR700pubGCSPvE VcyNm
-  Rgtn8hQyhWyMHjPHen72w9ehRUMp4AGBzTtpJZccfSrZ2luAWyM8DrUQD4JOeveq3VxWSaZ Bz
-  zuXk80pUByGyAeKsnHA3AknnjimOiqAyEhQO/NRe+yFomRB9qrtBye9OC7lc8nJAFLwpC53ev1
-  qVscgpgZ7etVDcmWm5HgkHLKoPHIpiqozk5Iz0p2wZY88nIBpM7fw4OKculgcLIUlQvUMM8Uxs
-  bQ B0J6UhHXdxj7tHCt8x68jntUR0eg9JdAfaCSDjB/OmMOuDkdzUoG5GJI44qDJDY4xyTQr7d
-  Qcbaj PmKEH2PSmO373joD1p5kyDzk9uKiOdhGCxYZAHatNiZJW0KsknynYnUHr2qEhfKcsSTg
-  Cp8DhQck dRUDhxk4BBIzipUo27AovRFaR1wV2NtJ49qruy4wePWrxUkglehPJPBqiVLMpdG+b
-  7px6U5W0sSr NWuVSueR8ueSTVaVSJDjGR2PXFWn+8wY8fyqq4ypK5OTyc9qvlu9TXZ3KjKTzz
-  z0qu4ZigVSMAZP rVp0G9gAwBxwarMWG0cHA/GsrXbS/EpQbTdyuyHYp2tg9vaoVAOBwT3qSQM
-  yr1X09qjbakxIBAzx n9avl7mKg2vQYygTIRkgdcetN2/OCGUDrjH60/c+8k4BPI96coACse+d
-  wqm31HV5lYjZSWzncoFQ uA+8N8oB6nip+fLZsgI3AJpjnEm3cuTgn2qU+wlK1m27orMCFUBSx
-  x+VNbMkZDvhQw6cVZbAcAq3 3aikAyApHyjn1NUpN6JWDmTXvIrOjAMVO4KePeo5DuAyMjPQda
-  mLAqSoJBODz+tVmz5WBx6moa7h K60KrszHgcjrVd0weeHHUE9amcMMAAnjPFR7gG3OTuz3rdt
-  pJi5mk9NDjY1Ckclhk4qXc2NyqDt9 qrhpRMWG0fUVKoLBN5Kk4wKiCVtWh6W1ZIrSyFQw9uB6
-  1cVNiYPHTr61WCDBJfkn5cfrVtGVsDna RkUpaPRFqXRLQtRYCAMRz3FTRsr8569/Wq4XbsBwy
-  Afw9asqMOjDHoBRrvuQ5R5diYKckndhTxir kYJfBPbA9qpBf3ipuIx6981eiwG69u9DslqSk7
-  E8ZXcSf4atxIoB5OOvTvVVQQdv97HarUZ+RgCB kd6Tu9i7K9rFkDKqGJyeQfWrUa4b1I6jv9a
-  rK24qehA/KrW3d1ID4AIHem22yox0szSiI81iFBIG M468VYRfnXBHIyQfWqUHAByx46DrV5cG
-  3yMdce9Q6coshLWxajUAZHJx6Ui8rypIJp4+VVLNjIwf rSlHVSgOQeh9Kuj5lJ20FH3nIxnPH
-  HQU+OMAgbx170mweuOak2bHBYnJPWsp2u9SddiCQAyqOCQM getRyBW4UFcdfxq2RkhsDHqKjc
-  BztIyM8047JNGvw6opjG3aMEr0p467SAwJ6etTCNR04zR067Sf aiatr1BSSV+hCissnB6jlT1
-  xVuLcVCYBJ6eppoXBUgdanjC5zv29xU3VtiZrm1QqowYHGOO4zVmM MiNkYAIH1qOMLvwWOSep
-  q2MK23IDDgZp8y2aKtZEkZBwRkgdhU678BAvPeo1Q7hhGUnnHtWiqsij GDgUKTWwJxWlhY0Uq
-  ufl9asKijhQTzknPFRhTjnk+1Tx8NnaQQO1G+7EpNdAC4fKjqeRTzy7FlAz 0FSMoDhiflJ5FI
-  yoZFzk4HUVSSkwbjfmeg4YECqy+5NOIBU4GfWgKwiOG3YNOLED5lJ4OQDUcqWy CPLuiLYdvA2
-  +uaCoD9Rn0xUm7jHQ459qYUYliGUn2PJptoq4m1TgnJLdvSpNrA5UbgBg4pyYwO2R wTQEGeG3
-  AHHB70tGzPnSViHJdQudqmjywAOSeOD2qUtiYkqRxT02lVyeAMe5qrS3aNZaLyGKpEee G7ChE
-  lckMdo7YFTortIG424x0p4HBA7fr7VHMldEvV6WINiqAARuxz7+9KBxlVJI7VYSIPg9Oxpw T5
-  SF7HiiTRL1ZXEZZCSoUHpTNjM53AD+oq0uPKAz17UeUcdOn6ZpN2dmVJJPVFOOPapY7d2etMZN
-  x6g55NWyCpyB8gqJl3AsMD1HcVUVuwk9SuF8sZUA7h82e1MJAZQG3ADk4q75bmMg7QD047VWZd
-  pb ONhPFQnd2QWTYwEmMFgHOeMDt60jH5G2jvnHvTmXLjnGeDjvRsweOctiqtswirDQDu+cgHr
-  UDKPM IU85qUgrGAw7kdaXaSm4FQT7d6ak4vUhy1uRKocc5ODUe07sEEkH5cmpTGynIdeOuPWm
-  kqOW6ZOM VUXqW72uMDsuflBye3Smg5U9h796kC/IvB55qJicjAx6ZqHHrbUl6sj2YZm3A/3eK
-  h+UPnIyM5NT uGB7HsDjrUL8IitsPckU0iZOxXZ/vBRlgM8dSarNllBww4yee9Wn3NI23A4yOK
-  idiJFBHUdaFo9E XIqtln28mPqaqPvxkk+w7c1eGwyDaedvIzUMoIySc5I6DpTcrbg5JOyM9lG
-  7aMbcYyahZG3ZwVxV mYMQfmG44NVnL7MZ4GOPem17oc7lqyo4PlhmPJPTvUG0AvjnuAetWJFb
-  eCQWAOKrudr5b5cjj6UO zVjRp21e5AyDb5jbunK1FIC8KnGORnI6VZO10DFiD2FRE7l2nqR0q
-  rS00MG0upVIyhZM5AOc0pGY 9+04IyamG0M3XpyMd6Yy/uxgNucDPoKTTk7GvM7bkW0AxlsgDj
-  BNI4ILYVSfUjpVoRAHghiOlMyN r7sY5FVdOWphKzd2yg24yE5zkYxUbxnJIzx0NWnQhAcgnHG
-  B1FNO4xkk4XGF9aG23p0HzRVuUqMC FIGM9yRxWczvgkD25H51fdWWQ5yQx6elQOVKkAAkrkjH
-  elGV9C9tTPJJU/KzkH17VCwBRhkjPTNX MAnBBGRyAarSZ2hgQMcEYpxbb1By10RxAR2DHaw2n
-  vU4wEDclx0FRZPnbVHB65NSr/q/mwSPSnaa 3WhnGMpOxIkYcqSSM9BVpOAAgyqnGfWokRTJye
-  /SrUaFM9CSc1LlZ2RUn/Kx6D5k3E46H1q2QTMv zDnt6UyPY0jZHfr6U9UbILevH0rSTbI5dUi
-  wIxuDHd+BqyobrjPNQxbVcjdk+/NTICrBdrgE5JJr K8upspa7k6glsAkHHFXUXDIQM4B/Gq0b
-  KNvRmHJx9atBQNrBjgHOParcrWZLm5aNXLShCFYkg55A q6FGdzHn+9VWMANuySAMgetXI+Y8k
-  YO4Yz6U7q17ii2mWkAVVbgn1FX0j4Udx6iqaj7gHJ3VeiBc 5OSOq4qJau6HfXUsIw2gn5yemO
-  lWUzk4Xgd6gj4QYUdenpVgYJYsTszwB1py2JaSe4w/cGfv/Snq uSpY8gZ5HWpAAyBipCA85PW
-  m8Ky7eR79qhtWdhJdLDFUsxIZcdcYoCnBJUkAcU/bmQtwVHXbQwBD Ku7pwM1Tir6s0TuiLAJw
-  x6DnFRNwTwc9qsBMQvkEnIwaTaRJkjGBSja9nqJct9AHysw4J7HHFSIm HHTBHFNXAycZOOpNW
-  YwrsgByMZIrOTsrlNW+YRhUm5G8Hgn3qxg7iDgcYyajYbQchWXqNvepskjb jt8opxSdmPVsmj
-  JyAWB9eOlaKKTlgRgcEVSjGcHaScfSr6qCPQEZNXNx6E3k1ZE4BXBYZHQU7LC4 BYZBPUUiqRG
-  AgOc5INToEIGckg4UZ6VKskNNpa7j2GSBjjGQaYNocEhvb3pyZUYLAH3puO+B6del LZgiTIEn
-  Q7j2NJ87yMT0xmmgsOh4A5yOTTgrErjOP50k3uUoqIMGRiw+6Rkk01sja5xu64p0mTEQ 3AzTC
-  6tHySCOo9adkyYRfVCnJ6nnPrT14kBBAznioYwc7gc46A1KhJcswBXODijW+5vbSyQ/hijb Xb
-  Pp2qVVTzM+vWmqpUZ3LjPSpgqFxjj+9k03boZbxtIMLtAyQc+tSIAYzn5cdz3pCwLYHJ7Yp4AL
-  bW4XPPNZuPViau0mRgMsxKsGHoKmCEkYU8ZIHpT9pU7sYXPFNAdZyVILMc/hVKTa3LsmtBCpOF
-  AA 9OKWVBv2jPIyTmpI4280biAR2oCKfvE49aUY31bM07S1ICi8ZyQOvNQ7EycffPUE9KsnAfB
-  ySTz7 VGUVXbB3MT070WaepSVr3ZWdWCbGJwOgqJjgJ3HHFWnDOw5xyOMUwqMtjHDdT60NpbkS
-  baRX24wQ jYJORTXIwoIwR0+vensjEAjPShozgFCpwDmnyxHBJdSAoG+YZb0GajcELjcAMdKsY
-  /dsCME4Ix2p N2YBjacdeOarm122G073IQqrGzFWwegJpjBSwYKcE8CrBi/dAksuB0NDLk9cY6
-  ij3G7CUnzXuVDu EgBztHTimEDByxBPSrRGXwrDH8xVXYJGAPU84pytYaW5HJneMsCOPzqFhuY
-  p1OcD6VaaLGOMAdjT HCBgWIBApSfREN32Kflny8HOcYB71DJEzHjqBz9atOPnznGDnk9KgYP5
-  Xy/Mfapemty48zXmUplI A2qzNjGRVd1eNRvUirrABn6g8d6pS7i+SSf5E04663G7oqspI3EHn
-  mqzFVG4DGD3qydwbaPSoJSu SvGT2xVySJnLVXKxJLKvzZ5JNV2A8vjax28DFWJOm3BJPTFV8f
-  vOeBSslcE7FfgpknbjtSAF5c4y CPpxVna2SdoIz3FRHaGyM5zx70k09A50lfYiKBo/pwDTQCG
-  yvOGxx2qQ7NuQrZDcinMP3jHGMnkV TSSVyXKzSRE2M7h1PXHemeWrAF+GI4FSbQhAOPahm4x0
-  JPGe1OVraAo2d7laSNsIy8YHQiq0iHLs WAK4wParxU8gsT61CwBWQMM/Lx70SlqiXOy5Uigy7
-  pGLbj0JPaqjhWkbI2kdavHeocYx04NUyjA8 nODyfU04xS2ZTs7vqUnwp3AgfhVaQFXzjapGST
-  V+URhlGeRnI9OKpH51XJ4C8+1XGTetxKz1OGRH XcDx9asx7gCQBuxk8UkSs7Efe+lWYlZRtI3
-  Ang+tSut3sZ36WEVC0W98KCQRjirKFgQMlhu5zTNp Jz2z8q5596sRxEfJyxJyOcmlLk5WaWtH
-  XYcrMJNvUHjA7VaUoyqSTlSAfc1GigTjIx681ZQASKcZ BGcinFWjYVknZDgpzvZhjdgECrfBA
-  ywztzjHeokUgbsrgcnI71IpJVeV3d+KUWzRt3LUWBGDxuPT /CrKhmlIJGR6DqKgQgkbcZA54q
-  ypDMrEgHGc1lZpkJ66Muop2oCQCO/Y1cQfKpPfpz2qpGcBQCNn bPfNaMIUJn5S49appvcce7L
-  MKhSGHIJAq3GoTGc/n0qpHxKp6gnIFX41LMGOMHnFJvuOTV7lvomF GQCSakKkrljnIzxUXcbT
-  nd2FS4G1T/CB07inTTRCg1G6Q4DCZVlYDOOKcf3sYIHJ75oiXfvDEKM8 U4K2xQqkjtVcqva+o
-  S27jUTG49e4pxUKvuRUyjLnbkAg5yKaDlScZGCOnNZ2uaJ63IGTjklh/CV7 077rDb1I5BpzKT
-  EqnjIwKbtZVGeDuwM85qVDogatuAWNwDnHHSnLgElTtBPODTiCGXJUIO+KcQuM cHb7VUlbR7C
-  +1zE6BSGGak27skZHGefamAEFdoABGcVJEH5LE4PAzUpMaSaumWYlZpc89KuqSpxg A9PpVeKN
-  hGfmJz6VOi5JwNpB6k048vQNd2WflKhs8qe3enqh3lhwe5ojAEahirDHHvQFY4YHK45q k7PQN
-  3qSMVyCoJbvzQ5yFDEKew70oAIBIPB4pCSc5HIPU0nFNXQknsMD4O1OWxRhiAd4JHtSqB5i j2
-  60joAcp1+vWqtdGrS5rCgk5JwfrSkArzgE0iqQ5I5AGKcuHwOgrFtqW4SsnoMUjzAVOTnpUyqG
-  JwCPX61EmFbI5yOanVVZCyMc5zyf0qpRd7kys3cVIyRyGGeetTlcgEYz1I9qSPlQ3HTgCpQPl4
-  wW 6fhQpS26GbkubXoL1YN1xx0p2wALngE8jv8AWm/MHx3qwqq0ZKZLdDROTXU21vZAflwFcNg
-  88dKV hsdWxkbevvSbEaIspJYHOD3FO/e+YMKOnSiLu9EDbuG0GNmw27sD3poG3g5IzkAU8OPL
-  Kty9O2bc EDBxnk1V7XQa21GsmSrE4JPP0qDy/wB4SMjHUntU+zd1O0DjOaTYFLMx9MUrPl3Mp
-  S7MpucDLDq2 aaykJkcgmp9mVbODgcH2qEAhMA9+/an00NY2IAJGyCpOc5x2oZWBOVJ+Xip1yM
-  jIBPrTWLAgsCeM ZqVo7ESqW2RXwfLz91elRONuBjIq0yfNkg8DpTCAxUbWHGDRfUV0lcjHCjq
-  fQGmhOehJY1JJuWba vX0IzTdpI3Ecn+VDWgOOt9rkBB5JGDjBqLBRzgEsB1q2R8nIO4+1NbJb
-  aCuc8gindsV1LS5TzkkS McgVE8fI+Uk9B6GrLIxkZuFxycimFQYyRnccY5q7NLRjjZ7FNlLFt
-  q4GOaruDtUc5A4Aq0V4JAY5 zxUcnyxqXAXAqLaA+XoUXHOTgMB0qjJkSABgcDpjmtGQ5XcF5I
-  wapgNuycZHBJq1dxLc5LqUmH38 kBic1E5LNkgA1cypUsu0MQeTVNwBGScnPIqJxu1czTUpabl
-  BlIkKkcN055qHC72KqST2PNWySGJ6 ZHGRUJQEHBye+PSteW6syp9rkZHyg7wdvHHeowu5VB+X
-  6npUhIJxyF7+xpm3EuQS6Zx71PK72bJj OVmhNuEO5gR600xksfm3dKlUAsVwCucj3oCBo22sR
-  g0c043JipRd0MCoVBAbKnp61CoBlJ6kt0qx 5alzgkY5+tMkTanyDJ3ZOPXFOD08hyV3vqViWD
-  MMADtUAAMbnDcNzV4gBFU/ewMmq7HAYdM0SfMy HorWKTJukZ+QO/1qlInPJBbqeKuurByM4H8
-  6glRfMwW249aXO47Mr2fZmcY/nbcpJbuKptxPg4K4 xj3rSk3IWwQwHT2qhIrlCRg554HSrU0x
-  p6WbOTRcKu0jp2p4R3dQWGcZwBjFNRW81t3HHIFW/LO1 WBz+FVCavqzBSEKuBlyBsOOPepVGE
-  B3HjgGlBA2ZXI6kZ61MFOSI+M8gHtUxkn0L1vqCLgjcCy9R irMbbhnAwTUfV1Gff6VMgJjOSM
-  54IpuF1sXZrccBhsn0xU6hWCtnPHWmqNxIALHpx3qVFAAUgg9R T0tpuVa7J9gRMqu7ng1cjBf
-  kId+MYqBcjb0VcdxVpEODIWAHQYqOawrW1ZcjRvKAPQfdJFXIlKx9 MYPaq0R/dBScqOM/yq6u
-  4qQDjP3ie1SnKXkTF9WW4wjELnHynbmrUKu6Zx04OPWqgTJ3dyOFFWEY jOcnHUDvRGBV7rQux
-  qI5h1IFSnIQHI46+hqDkhSowD1zUysFbOM9unQ1ST1ZKvfclU7HyTtB7GpT kP8AKcHGc9qiLo
-  8Y5B569Kk+UF9z5AXFZ6PdGkeZvTQAoZSQ3OOMVKoHA+YZ96jXbs4buB0p+AFT HT1zV811a5k
-  m0mMdVDKc5YcAf1pz7gABjOeR60qjdIWOGbOOBUgHO0927dai7RbnZLuQqp8ojg5P GR0qRVzk
-  cYByPWgrmRuRweacOH9QAMkUpO6Ls2rdRyZaQEHoOKurlmxjKkn8KrxjlvlYgAbWHcVO AQ27J
-  UEZxUyV3oQ4q+hOmAo6lhxyasCNkbkbh0z6VXADMVGMjn61bRSF+6SDxgdacUoaopavUkVf lD
-  EEAHGKtqPkLbhtHU4qFVygKhgw65OalQ7WOcFcYx6Vo5NqyCK0EB+Qb+mc8Gnkcnn60KMLuJVu
-  OlPADkAg5xSaT6FNkZjxFuORnktTGyd+CBg8Va2g5zzjpzUAYBSpPKjAx3rNNvVgm5q1iMbg+5
-  iM GnjY0nJxx60vCg7uv8vakCZBCg9eM9vam2xqKd7jesgUY+tSqm0gZKkN/OmquJV5+cE1MQS
-  MBWIB 5x3o5ul7FbpxFO8QFRjcDgEDFTAd8980i8QscHr370oYttIwfUY6VUddzLWyViQEuwcL
-  x0x71MIg sg3NhvQVAMEDBBqYN+93MpB6VN0ti32RIVO9FXovBNOZk8rvjOajDHL4VmPfnpQAo
-  CyNknqc0Nu+ hDTtqA2vIxHy9+e9SM7PGGQY9vaoWc7vkA2njHpT2J4weh4IpN6mjSVhCwNtzk
-  c8imhwW5yaeXV0 wfvHgimAgwbOMnnPpSdiXqtRjfMSNw44ppXBIII4AP1p3zFCSm0n1poAdwV
-  JIHv1pxTfUUpRURjf MgGCec5HpTOOOScHpUw+U9Rnp9aiI+bB45qvIhNNJiEjzCOCc81XIJGS
-  cKDxVlgmCCGwTkmmEHYT jgnkGpSHpazI2PAZjls5pnU4XIyM89qlbaoye3603PzBR6Von0BbX
-  IzGVjB3fMcd6a6Ig3KCSelS KzZG5lJ9AKYzPvIUA49qmfNcabvZkRVmPrxVQgnGTsA447fWrW
-  87sdW9B6VC5UA9s9c1pG6bVimn flRXO7zc8kAdKjdQ/BwQRwakKbpAobnvzUZyCNvPH5Vb1ZF
-  7PzKpxxuBHWqMwMaHaR16H0q6yZbh sZHWqskZLbWHzMRg1DXW44pLR9ShKm0jZjOOAPTvUGxV
-  XGc8cZPNaJUeaQB8o79aqsuCx2nJOR/9 al7Rtb6jnJJ2RU2ZTpxVTb5bHGSxIAJq6cknquByP
-  eoTBlGG4jnijp7zMltuVCoZs45BxkHFMZSk m3ORjmrAjw4Qk8rwfemiP5sSAkY4x60pWS3NFN
-  dWRk7uCNvYkDpQFMbcuNwbn3pxXClgSQH55qRg JFXbg85xRaL3FvsiJRuGQcDviggAHoV60rB
-  vNwcbc9vamlDjCnIIyfarml1JnFt3RWLF5gwUehpr Iw+7gZ7kVO+PLHzDcBjAqEqWAUsQuKUo
-  p67B73QpNgxnI46E1TYARu4+bB6E81fZFIAzuJ549qqS EFCF7cHjpVJLboS+YzphnG4jBPQCq
-  sh4I5znn/CtB9rjGMcdfWqZCGFjyR156k0TjJx2L9pFnGxq fMyh3DoWzmr6HcQQQFAwR3Bquh
-  CgkJtbPSrCcHOzAPIFOfvPbQlwdlbQWPltpzkDPPerQ2uQO55x moFyowV+dhj6CrMZBTGVz6i
-  m77obTTv1HoFHyqMnv3qUR9DuBA6rimffjXt1JPSpVQqc57c81DXN G97DSVrtEyMQqEkKu3nj
-  vUyguQeD6moE6fPkZXFW40AT7/A7DvUyShHmsTzpeoLndllZgep9Kuxf fycBTxj1qJcCIY6Ed
-  KtoFKHbhmBHAosmjWUls0WQAYuAQc4q8v8Aqxz04J/CqcI2yNuGVbnirMfz L8wwrGny+RC3Vn
-  oWoyAkec/1FWdzcEDI6Zx0quNm8YVsgY61ZjdmBjYqFz6cmla3vA9XsWBtaPqd 3bmgEp83U1G
-  pAZeQewFKchGJKjFXzW6jhF7E4O0DcAR6YpxfdI+evrUIztyD9OetPjIYnOBjrxWc 5ajhuy4j
-  qVPTcKC/Izg8c4qsjEYHr1yKnj3CbgruPXNTFxTuE421uSGTbGxOcZwR0pQ7bgzfIoGe e9MRC
-  7fMAFJ5Bp7YRxhhwMYNXzK7FzReg7ftckc5OPrTxnhR/EC2KRM8Zwdwz0xUyBAoAB3j37VL 5V
-  uipTfzHxgkK2GxjHWrKLulYMCcjiohyAEBwD1qZQwAOwnI5GeRSbbegJ29SzHtwOhHtU652lhk
-  A8CoUVi+1Qx4GKsxAlCjL3wKm7QNO5KNyE4yccE1MBhF4OGODxzSLtzhfQk89TU6nCrlcccE0+
-  Zl uOl7CkDYAuOOB60zHzgsCMDGalx3GOCOaNoJ6d+lUpaWIWzGlQ2WRgcDr6VAIv3zn7pz909
-  asNhV AAw3tSEjILAsfSqvJBzS2uQgLyGbBznrSgENkfTmnhwWOFGW9qMZbcSOOwqeWW7NNle4
-  nzHqvfqK lBwSCc5NICVQkkFhxSkAkEDnpUu7Rj1JFEag4ySQD1oJONvyqTzigY243DGfTrSg5
-  5OA3ao6XLjo rpEgwgCPtIJzkdqewPOc7ycDPtURIJyMA+lAJ2A9fTmjVoTpteQ9tyq2Dg/zpU
-  IOM8nv6Co2bCqN wIHWmFsSkLycVbV1YqK5r3JgMHJ4BPp1pWkUbcMMDrxUCsW65GKU/KNhIPv
-  ik4rqDi21Zkm8M5bg c0ib/M3ZGMYxTVwEw2cdqeWOMEZHqO1K6UtBuTfxEZb5iSdvfB70hJ3c
-  MOOOO9KQpTK85PNLwW2j gHkE0732I0TuxXOFUNgjPaowuG9QelBY7SFBLHoKZLuZRs3Z6U1Cx
-  UJ3W+4b2LfMDjPHsKc2S3yq eOtKuSfmUjaMGmM4XLhjz0FK6bIabdyPq3HU8nNBC4BwST6dqX
-  n5W9RSbcgNjJIwMHGKvbUf2tQY plQDxVc56qeTxxU7ECPbtwRxn1qAqWIw23mnF9w212GFSkY
-  cDJ796iZg7AYI7kVLkrGCxJOcYNVn G2HGCSD97NKMXJtsnrfqRsjLKCpGMdahYAZ67/6VZcFz
-  klRxjmomAyOo9CD1q4yktFuaOStoVZFz GTg9MjHpVcjMmCSvy4BNWWO5sjdjoQDVeQMMEqxI4
-  Jq0/PYmWjViswKqRkMw64qiwyuOcZ4z3q8c FsqGI/izUEqKHXnk9ABWMnrsTblVmUjtV+Qy54
-  PNV2V/KbBHtVtwTKOhUHHAqux2uu4jGeKuyd+4 4SkVfmyoztz1zUhB8wc4UDNPZVKlgcYH5VA
-  MqMhs/XuKHZ2Ha6GFS0yqxAXGSR3NIwJlBQYOMmpZ FJxnpmkUjadoOQehqua2qKsnoiMKqRtu
-  3EgcEGmFxJz82QMHFTgATkHJ7gE9qCdqA4C4PTFDehjz cujK2Ar9Dnjj1qOUhRgnqRyKsSAZI
-  zyevtUDpiQK/OSM1EprqDty6FcqfNyD7/SqEjYkPOT0IFXZ AVZtp5J69uKrv5bFixPJ5x61p0
-  7jgktbGcyAuD0x0xVZowzlOq+1XziOTP3htwRjoaqSkHkcYGM1 HLK4ubojkPvFSdoBOSas7AE
-  G0hhnINVQyliuGzjqDxU68lAXA44AFaJPe47qysTocN84wvYmpgBt +XrVc5zgncegx61OmTwS
-  OmD9aSuVyJa3LKKWVWI9gRUirhMkr1PB54qJcLgAE+ozTxh2ySAc0byu LVq0noSInO7D8HFXc
-  qrKuDuyfxqvgg4JHJ4xUi/NIm48jk570NXd29hP3tyyhOzcAF6EAjpV2I5l VhwCpJB61VjIyM
-  9CfzFXEJyWGBk4A9KzS966QnGz9S4p3Jwd3Ye1PQlY2DfezkVXjOG5DAjjd2q2 CDyPmboT2NU
-  48m5TdtCZJMKWB3ZGPpUgXMI2MRjjr1NV4353KoAqRcsSobGTnPvUweumg7u9yzuV IVJznNPV
-  wR94bD0JFVSdu0EhlBwaeJPkZgv0HYVnpzXKUmuhYXJlYKSBjIzUqs3mKmVAI5qgJDuL Drjmn
-  7jhXJwCPTkVcXd2Bxv1NNJCi4Cgj37UAsxP971FUxk42tz2FWQcsDnaaizT0Iah0ZaB3oWd WJ
-  xnIPFSId4XYhZsc+xzVRSuOjYX361ZR/3gI4B9KqT8tRtcsdUWN37wg/fLZAP8qnwS2SSv4VWU
-  rHPl+hGAT0qwHYkuMYGOKrXroVzNapElvn5vfnPrVwN0KnnuPSq6BQ4Byccn2q0CPlLcA5/Cp5
-  rv QiW5OobOQTz29KtRYHBP3ujZqCLDtlQ2QOM1MgOz5x0PGKe+5SldpFsBTtwCOevapgmcr19
-  ahjIZ eFbC9h3qbpJ0OSPzqW+g1fqxBncV56/ypwIJUknOaQGTaQVBJ6cUuMR5wOOM4qXbqH2h
-  8h/djODg 4x3pmSX6hR6kcUobcSCp68e9DcnJ4wO9XDXQE9NXqMCFSem007arjKsowOlCnEXBy
-  e3eg7SQccjj IqZKT6h7smOHC4PBPOaRi20fIVGOtPx8qgkHFBVi2T09qmLSdw5etyJC4TcQcZ
-  qYAFjgZPUUDqVw fpSjIO3+8OvrRJ3Fa6GthGVQNxx1FNb50IB255Apejlt2frScoMDBOemKd0
-  hpW1AYCjcDzySaXHz LkjIprPztJwAOKRQTk8nPr3pNuw3orpbgN3mfMOvHBoBfcegUHAzRk7t
-  vUA8HFRKWyQScn1quYnV u5M0jgHBBPXpTEOF+Y9cjFMwBwTlh70pY5zlcAdMUou1mSmuxIvTq
-  SM9u1OWQZIYYOOCahVwEzkf 7VIXDBmAyQcGm3HZlpq6uWc5XaSBgdqrlmLDaQe5UCm4IkHzA8
-  c0xxhmBb5s8e1NJb7mkZa+RYZm DYztOO9J95sFlA+lRo+Y8MAcjJ9qRc7gwzjHc9KOVcphysn
-  C4TBIJ6cVH0bdznpjNGcNjB/wppKs oKsAwoW4SWgz5wzEnoKbzuwSAByD9aduycAn+lNwfIO5
-  TnGAattpotJ7MhcsPQ9jx0ph3NCM7Tg4 HvTmHOPmI9B2NM+QykANjHek3Ym12J8ipuY5YdR61
-  XOCQcgDv7VY6jrtB65qu+ORxzyKT9NQd9iB yGZhk5A4A9ar7vMxnltozU7DJ3Y4Ze3aoSAIsj
-  vxmqjazuVFt6FR2YSbVBIIzxUBVjggexBFWzgI eRnHBqrsJhUcjPOfWiTe6DmuyqyEKxbJOeB
-  3qFsHB2MMHknuasOSM5Ukg4TmoWGGIySOhyetOXMt yNempWPO5cYBppXC7QOVP5VI3DAAdev4
-  U1wGHOVLfeOajV69DRu6sR43HGfb6UwoVcZBwB1FThcM No3etRF3MhJVuTz9K0jonZkp6asGJ
-  6gD61Ccs5DKT6e1WAGw2VyQeKaWGSp6gVN0tLApLsVnBZkI IL4IpoX5NxYFyp21MQS3GMdc1A
-  WLnHAYfnSvpfYznC+xA5xGobBJGRxVR24G5So7/Wr5Q7SrMAcd COao/el28HgHPrTg9BK1io4
-  VmByCx5J7VUkVckHOPbvV9ioUjgLyBntVNvv4PHcVd3fmKsrHCs4A JzgZ/WrMeUAYENniqabV
-  y+dw6gVZQltwyFOKpT1aREoO1uxZGS2cFsnp6VaHXd2FV0w0KnOCDzip kxkgnPpUxipFddSwv
-  LbtrKNufxqwpRh3BPP1NV494Qcg/hUi4Dlic44wDTabauO/ctIMoRjkdR70 DktuBJ2kU2Mkjd
-  jaAck+9ShxtJ2nGaiKd9iabd9CaD5XxlSFOBmrkZUzAnIxyeaqJgK2whcc5Izi rS+WyI/8Q4I
-  FTK6Zc1zKz3L4KKp3MuC1OQpuPPHb1NVlEXKHnHfPalVUMm4E+mKrlb6kq0VroW1K hyACMjgV
-  JvZSMkZA9Kq4c5JcZB5x3qfefLBGCp7YqOZCV97DkcEAPkjrkU7IIJw3QnGagLjACgk9 8elER
-  z8vTHB5qancqK5ndE8TAncrY453U9STMy9eeKqqymTAbkA4GamRmEgUZ6c+1S79zVxu9S+j EA
-  MNp4yTUyliqsDwRVRGJj3YwmfwqxG6s+3BCf1pRm9yHpsifB3evParablTIxgjBz2qoGw+CDx3
-  NTxk4OMkHsa0c+rFzXLgctDtYAkdxU6nJJ45HPtVRFQg5OCe2atg7WPBA71CcFsOL5XoWULMdp
-  Gc 9cHrVtSTyV9s+lUo5GVCzHHt6VajYSBSSVHrn3rSLb2QSve7LaEqCBkHpmrqBnChuD1qivM
-  pI5bv zVlM7QxbDZwTUyfUvR77l0ElxnoBjjvSsZQpyQAvbFQopwDv5I4HpVgIOm73+tVFRQnK
-  2lwDOQu4 HI6gdxT+DyuWA5poOMNuDMBgAVIMNICflUjpWc22tQe1xSR8u0Y96XaQVx827nFRq
-  ylM5LY6c9KA SGJXp/DSSsKy3Q8d/lxzxgUhQEv/AHjjimCbkECpl4O853N29KPeiXyu2ogwSM
-  UpyJNrEEegphwT nawPQDNPUuGDHAOeuOtCVtSLu+40BSm3BGCSDSZO7g5OOfanNnftA3c9R0o
-  OMt8vQYzVPcL3XcEC 9W4PrjioyzHKtnAPBFPCj7rHr71ExypAPvRC8gTtLVXHMGCbmXcN/FRj
-  7/3sAngUMSyKCTtHPB61 GrfvcnIB9fWlumXyt6Cl8ZCgkg4HvQCGIDDoeTmmM2COmF60ze2d4
-  6UPVE8rS1JSwK8Yz3JoJ2jI PamEfPnIwByaVFCpkHdgnrTjZLUNtRCyliBkg9hT1wApXHI5qM
-  AGZmORTcAcjI9OetVdNBKVlZD2 bDdB1496UMG6kEDvQHyvPODzx2pnmDAIHOKSetlqTZtbD94
-  4BXHbPrTgxZsggKBgjFV925+AQONw PWpMp3DdOvrVyaTVg9nJLUkZcg5fIJ4+lIGb5sLxnGaY
-  7sQMD5T3xSKxZckMOefShXaHeyuLnEpU jk8k0g3k/eGMU0yKxwMjPIJqHe3lY/DP8qOVvoFlL
-  R6ExJD5TaOMHioWIDLgjOMU4EBipbf6ketR yKu4NtIbriohDUGmpWSGEkqVZgSOtQORuAU4PY
-  VK23ZuIYHBzUJx5anBGRyaq73CU2RFzu29s8kd 6rktjpgZqd3BO0YA3Yz61DKWCAYAI5px7Eq
-  pJ+RHKoVMnG4DkVUkOIQR261MzfvWOC2Tk88VH+7U 53cEcjvTk+hUYpLUiYq0obepxwBVZ2Bc
-  hlzj0qaTBwwBHQAmoHUMc9+MAGs7q7uJWIcrszg49M00 kH72eRz7VMyAOFHT161C3DgkgjIAq
-  opJ3KcvdtEQBOmcHd601lRZGwe2BmnkHeTzuBz9aQkSOR1G 0+1PmSepOuxGM5x3HvUL5DtgDI
-  +YHHWrGQkJbGD71Fu3tvAbrg47U4xdr20HKKWr0IZMiMltxBPH PIpgUKpZc8HP1FPk3FVCklS
-  agAMjKORj360ON1uRb3dxj/MCWIAJ4XviqzIFlPUMOOv6VYZguAyM AD96q5ZndiQpHUcc+9Uk
-  76E3sUpN2/bwRnioZVxl3bPGAF71ZfiWQH5cEYPYmqsvzYK9O496HC5b fVs84R2AYbcYOFwOt
-  XI2yyMM4Ixu9aqLtL71O4dMmrkbjcowvfpTSM38VlqWo/uBSWUE8GrUYVYz 13AcelVY8BWx85
-  x8oqePJwSu0AHH0qlrpcat1LYHyqADgHjmphjaQeR3xwahRlEOcHOelPicknO3 g4pxTWpa12R
-  cGQcDC80qsFnJwORxTIySoB6E8kdqmVdvyfKMEjLd6ykv5jO6UtSRPM2nbgKfUVMv yocHAzjJ
-  FQJ8seSx9zUyNubJ5XPSqjF9Byk2ix0ZmXG3PrVpWROSBheCfU1XQuWZSVUDse9SDIJY gHIII
-  Hb0rKXM3YrSyvuKwypKZVsjK+tSOSFyGyR1wOlKq/KRnnHBoEacqWJPpnpU86e41JOOpHuV UG
-  0Zz0yakRgRjODnJHemupOdowMcH3pEG6QgZB6YNNxTSuyNL7kvfK4BHUkVYiO5m3lcD8KhWPLg
-  kZ9hVlQHKlcHPUd6hJPRG0dOpImAdgJXsQasxjawAGMnkGq6lVnJxnnH0q3zkjPfGarpsRK6aT
-  ZN jhufoT0p6SNtwe3GcVCqknaCCAM4qYcKwzuz0AoXK99y5rSxbUq8jZbGDkVYT98nU7emapR
-  D5iww uF6N3q3CwEG0NnDU5abGMrpouZIk6ggdqtRsocgkbQetU+d+TgjHFW1I2ZI4OM02rW7F
-  u76FtHUZ AxgHHH86tR4xk8gjNUozk/KeM81YXk/Id3baPSlyrqLmaL4KhAnDDqMVIpz8wByD6
-  1TUsspzjHGB irHKwBjkY5PpSa6I1cLJXe5L0bOQAO38qcSdyjrtPJxUR8tlC5OCMHB704AZXL
-  EgHnnvT6ahovUc NoZiCMN93NOVy0Q2j5sc0HhBgZOO3egHK4zjNRZ9NQUtbsXy1IOVx2z2Bpx
-  YiM45IOKZvJbB4GOD mlj5AJbJx0Bq9be8TNO97kjcw5CkECpVKeWrMGJpMAZIIwRSbcBiTkbe
-  3SpWqNJO6sKANrMemaib 3O0HvmnAtnnOBxStngEgVPK76C5bakIyvzDP3T15pBhgMEBunNLkg
-  YKlU7saGIVc8Z6gVdnuydLX IwSHbcQRTWcA4bkAce9O6zcDJpSMYbIwexHUVOtx8sXKxGCDtI
-  AzjPPvTGxtH97HSrG1WTnqTyem KgUDcSwJYHr2qU3dg1Faobt/dkK2455poyJFye3SnbSJSRy
-  SM8dKMDhwwIwQRWkX3JlorDRsaQBm IGOcGmlSAQvOemKGCbG2LknjOaQBgpGeBjH+FCknqNKy
-  0Yi/LhS3Q8GpG7kYAHQ0w5CnC5oPmEjI CjuSOKaSbuym2noxQABnrntUaSFUwcjnBzSkgnCk4
-  xnPpSAkldwHQ9qclbSxMpRa11JztI+U9+/r TWwS3BHPTPeoySytIBkdsUwlSmWbIx196m7urF
-  RejfQA2JFO0/WnbhkgLgYz7ZpOkQbjpjJ70xiG CjPA5JrR8vVC01Y8bcBdrHb6Hk1GTtbC88c
-  k9qeCQTg9fX1qNmEfmF1znHA71mnYzbTZE+OVyTnt moWYlAQOg4FSN9/c+cnOMdqhyuOWyQO1
-  XZNjjdvQY3IC7MN14qFiRIBgZxzUhwW3Bvm9PWoiSykA c5wKlvUbkra7EGQf4TkDFQE4dhlcH
-  n8KmLDldrKCeCTVZnLYLHg8VTTew4yitRsg+UbTu9PYmo3A DKBj1OKexAcEHPXP0pGZnjGAAo
-  GCSOtDctmRyIiJXlSDuzzjtSPFkDq2R1HSl5ySwJHTI/lQ27dw VAz0PahSl00HGTjezIG/1QQ
-  NkmmbFVjyW7A1Lg7MdRnP0qPYCHCkqpbrnpTcrIUX2InG6Tg4cdc9 KEyqjcCpPB96kbAcgr0H
-  B9aYR+7BwxGM4pSldFtXepAWKv1xlc4qAtnayDDemanckS/dzjp9KiZQ qgMTg+ntVJkVHFWTd
-  iuQxQn5iOpx2qB8/MAwBY9D1/CpnPyl92Ez09aquTztb/cNJe90DlS1uR5U qM5J7+1Z5YbiGB
-  9jVuRm5jUZ+YZPr61TZAFDbScngD0pyavYSTtc87ixsQKeec1bGFkAABHXFVVE eGVD1PAHarE
-  IXzVdcjj5iTVuV7a3Q4zsrXL0ZGwFR0PHtVhRluCc5yQD2qqpyfkOBnknvVuJwpAB DNmjmdrk
-  pxT0JwvzblBOexqwuSuCAORg1GxYxZACkHrUiBccg8UuZ213CKb1J4wc7WPy+pHWpesi gnAx3
-  7mqyHMyhmyAMfWrAwYgwHI9KLNOzHLe5MpZiFA2/L0I6VMpfy92Ax74qFEK3GSTyKl2soAG QW
-  Hc0khtxvYsfwDOemCfepg42luhJxk1AjbSdxUknke9TKA2A3A5ODWeq0Y07bCgsfunJ9RUqFto
-  wQSSckimxhAxxuAx1oVgZAT8v8PNOydgt0SFCfMRlyoGSe1SAbWUg7gOtOU5+RjjJ/SpG3kHao
-  Ax 6VEm7ibb0sEe5pl9WP6VPG6rMAOQM9KbhgDgcjgZFS42MQMZzSdt0OmlLRk6KNnbGD1qfLG
-  PCkHA HBqBAzIvb1qwF4AXk45xTstFcTjrrqSKuCOeCcilCsJFJI46cdRSD7ucccZqQuCOCMk9
-  xT1T0Qcz Ww/7pJDAsTVoEBME8DgEVAGAO9zyFySasRhfL6gA9aTk1rYuMu5YTaxXBx3ye9Wt2
-  EUDOD1NVkOY 0Cge9WAm9VVux4NTz2SbBSu0pFuNj5pXv296mVtrj5s8cYqpGnIOcsTwAasoGO
-  1gvfJ47VpHlLdk X42/ixn6mp9w5YHPYiqiq52v0XH51KuTwpyAMfWhW2M5RVxYx84fIwRwDVl
-  eFAAzk5qNUBReMEDF OG7ewOQc5z2oqT1Vyp3k7IcMSDAzx+pp5RgrOoBbHI9cVEnXjIXNWTnp
-  0PbNEk4kt9GRkBsDjjqO 9TZ4Hy9+/eoVADswyTmrC/NtJBA7kdqzfmXJJWHgfJ0Aye/anAMmV
-  fBBHQd6a2FOSS3vS9cAKWAH WoSuHKnsxrcIOABngnvTAGLDPzZPb0qXAaPAwwz1xSqsm8sF2g
-  DtWnoKM+UY4zDuOcg4AqJgzDJA Crz05qwpyQGIHHpUZ3BieAOmCKIprcIbtkeDuBxgdeRTScg
-  579KmGSF/rTHUjAGCR6UpJXHFvqQy sVxgY4wajA3YBOPpUx5cAjnsKT58j5Rj6U0tBOViA/cA
-  2sB2+lLtJ3K65QnjHepmXbGV5bPSohu2 YY5XOFIq17y2Ji7bETDkAYVccEimlWEYCjJBqT5WB
-  G7GTwaQ/e8vuO9Zv3XsU5PsNziIE5zmo9+S 3JxnkUuG3AE5UnimswHyMMA9CKtJkpxTIyq/L8
-  56dzTkILfN8x6AU18bhyO/5Uwbig5ByOaJ2a3N LpbEzPhBheD61EwJwSvy5xigMxIUMoXqCaY
-  pVW+ZiRjjB604NWtYjl0JQ5CFcj5egIpuAYznAx2P Wm5J3E8YOM0EER5B+b0qWS7XGFxtLc4J
-  xj0puQckndmlCtyTnHVhTAp2sBjHqa0TQ1roGVMuVJK+ lQyJG+4rzxzg0YAPI4J4NNYDeckjn
-  J96lysEbt77ERDBVJ2kN7VAygMfmIbPNSSBmjyT3zxUZXA4 OeRyfemtdWJu6K8pG3uSeeDUWc
-  lQpUkL1x0qRvlySRuP3jUBKHAGAGPrUt23GrdCJmcPuK9BgDFO WQNER8qjOeaR/vZznj0/Wq+
-  D5oKk4xkVbUXZFOKepIW+YgnHtTCW3HjoKUDdzjnuKQLiQYbBXjBo uuUTmrWGniMdeTk+9MJ4
-  OMnNSjHkr8pHXgnkVEWO7GKaV9h0+wmNqKW6kdTTONjYJAx1PQU4McKv 3hg5FI20dTgHsam7u
-  ZXalZlUsSm3BbnOc9qZIpB2McjBqVyQ3TAH3ahYhw5LY+tDjLmukO22hA4A jC5DA8darZzCVU
-  g4qZ/kUMMEHggVBjO48DPFVLSxMdXcpyttQ8nPt+tVXBK5ByoH61ckC7diqSPX PaqTDGRk4z0
-  9qLrSxS+E873DDLjkHr61ZBAZTn0yBVNPMSLLkMw68VbQLnewbLeh9KttWeu5MlFL YtxZMf8A
-  cye9XE27lLEDA7VWAX95huBg/jVhcmXPDLu6+lZX1Ha6si+CGfIzsPr61KhYgchWxjFV k++Cc
-  jP6VYUETbu2Oc09X1M9k0TbNhwPvZ/Onpy5Cgpz0NMT95yxAAGOalj25JXcwzyaqTdrGu6e pY
-  yWPXHTBqQAsm7dkZOKQGP+LIAqQhfLYLu3LgVClZp2JtrqIiuYyM5I6mpSVZGL5OBxikBwxUL1
-  pGJUggZBGD35pNu+ptT31LDBBIGbcvy9/wCVOxmJeCfm5FNAKSGRnVs44IqcDLqVOBu5FHM1pc
-  mT UXYWJW8ggkZB+WpxH8oIz7/X0pvUlcEYPapVA3kFuOg96h3uKKbTuKu8ybenPBqyPmZecHG
-  fwFRK p8sgDBLcH1qwEIwTwONpppsG0x6lQOCORkj0qVeUBGTnsOtIEyoUDgdDUu0cc7ferc4/
-  ChSn1uOU MMhuB6HqKcqgHBJPNCr8ud2cjJPvUrR4iXJ5HXFTKdnbuNSkxVCiFSTu9vSpxgfNn
-  BBweKhjDNE4 4GSCPcVJgBSCQ+DzSTsF3HZlhJdhK5VgQSMCpkyQobrgc+9VyoI3cg8AAVYi++
-  RgMq9xSvFJ2RSU Wty4vEn38EDr71bUs6hQSQOpqmoBw4PzA4YZq0GGFVSPT/8AXTitBa6WLPI
-  UnPBqwDsKFSpK9cVX TOFB5wKlVl8s4GT0U+9PltoNp2SLOTuPoTjpRywPPfrUKu2BgEjOalU/
-  Jg/LzjFTblKcZfMmxggE fMOTin7v3hAy2T+VIuGVW3bh6ipo1IBLAZxwacprRii0tGhgzgjHO
-  4U8u+WG3cM/dWl24+Y04ZKc MBkVDs9UFpIcqqFBLKWPYnpinDIbbuyG9KaFyvBUHGfpT0IT5g
-  u4nsaNWOT6CEqVA6Y7CmsHLDaa njjDOcgHnkCmvHj5lO0981UJpj92/L37jX5iwAcetMVJATu
-  +nSnlmA5KrkdMdabglQRyP4setONl qOV4dhpyOMd/yphA5K8MDx78VO5UJnPzMckZqA8rnBAP
-  SktRNcqIlU4GcjnrT2+UsecZ4NLtHmIr HaOetOCsVyQdopylsTe0tSPBJAOGGDUDcr2AHarB7
-  YOc9hUfJcgEKO5I71PNbcSTTuQNjaNqkf7W KjOBOSzAqR+dSSKVLbRkgjimsOWPdTjGKZUOVO
-  7GMdx+XqOeahLDOD97vmpNoL8sOnzVD97cMDOe TVWSiHKlsN35KnaRtGMnpTc8sScZ6cVL90f
-  ezngccVFsHkkNnJPrUc0dWyelkIfkUMRz0znpUZ3Z P8QJ7dqe2ApVidh6+1R4USPubGcc1am7
-  rqSko6XBV+TLHgHtQeMlckgfMc0mVDE8njof0pSNifK2 T/EAaTlc0vZaiFiQo6Meuab8vz8+m
-  OafuUkZ4brVZztAJHQYFCvs0TFJ6j5JFEeGXnOD61DLJhQM Yz09hTmysW7GTjnio2BJBOMnnG
-  OlOLsEbbkLMyhj2A/WomJIU4PQcVLksXyNvOCCKrmTpubsCcUW bb6icbIhD/vgS2QTnHrUTcS
-  c4Ck8EipJGDSbeAP61AVyqqwPc7aqST0M5JrXYhYsVJYgYPXFKxOz jGGFMJCyDP3M8j09ajZg
-  pDLz754FG0i0uVXHKF3jduyDliDTiwMvUDPTNR5bJLDHYUAZTLYyD0FW pNi57eg4l/MHQL61E
-  5bIAHyjnipC22M54FBcCQggEgUlUaaVgTTVkMVnk5VMHPTHNMfJX7w3HrxT s/6QCFJ9SDS9mA
-  AIzxmolP3hSdtCsC7Lt28k5we1QSMPL5UlurAVJJncSAxHIAHeoDgDoTxVx01K dmiLg78gjJy
-  BVNiRJlgd3UDPSrbLsUEA8jpmqLuASwDHI70Xv0IptJtdCCRz5uw4UpyWHQ1TkGSC HBLA5C+l
-  XsgIzMADjvWax3YUIw56miM0nsXDV3jsefgsdyqA2CMmrYIJBQ9OoPrVE8bemDx8tWou GYEHn
-  APtVSXKm0ZO+7Lkb87cjsT71fUdSCAx5wRVJFXaB/FjrVuHzDArEZOMKfWlOF2pJmr6P8y/ CM
-  k5G4ntUw7gg5OKrRsGbK/fU5zVsllJOMZpRSvqZuVxdoB2qee2R1q1Fnapwc96gQ9CQeCfxqVS
-  ehO3PSrUtGW4uSLIO1/mUN6CpF3NMyg7ecmokGIyZDnI5PvU+R5KgZzt59aye+w3Lp3H4AgHyN
-  vI 496OhRcEHoc+tIUyuDkDqM9qfGr/ADcBiT37U6clcUb8trljaXkYsjEHgVJGCMEABc8imAk
-  8dV9q mCfLwGU+9EovUHK2iJV2gSEg5zzzUyqiDPUkcVCnO5SQRjJqUZDoPLPy8DIrNRaZpfrc
-  kxu43fLn irURJTDjPcCmooDcYbdzUyFVHGS2cE0m76WJVncevy52thsd6kT5W5xkjqaAuHI6g
-  9falLELgYLd qqEuZWQpaj8YQ/KRxgUuFCjG4kfeye9NXeXxnJ6gEdalDqwwQWOMDFDlYfNdWF
-  QcKSpBPGc0+NC6 ttZeeo9KaC2wK3GetKMK+A4I9Kh33Qoxdrkq7gy57DOfWrKoFAIJBPqaqDI
-  GMHaauhFIyT8w6iql JrdFyjH0J02qSeemTzVuL7o+6Sc4/wAKpKMsArAnuvtVwMoIO3kdqfK7
-  DUL6J2LYKiNQCUYdQak4 bIVl3dsVCq7hllKn1PvU8S+UVbaWAGMUaJeZLvF6EyAiLYzADvx3q
-  RQ5Vdy7sDkAVBltxYLu5B9a urnduHLEdBScrPUavFkijg49cY9KeciPackn3pi7mXGw89frUy
-  5ITIPHU0l7u4pNSWgg2hQvJ5pP 48EEc5Ap5X5/lIOeRUjACIc8HuaTbsKLaV7jVXqcc5wBU2H
-  BALIGbtiq4DBCSAQORzT18wgMWXP0 5FO19bml2KU2S7MnB64NOHQgAbS2eaaH/eZyC+O/ak3M
-  2FwPU4FJvUqbskrgAPNy2ScVLujSMdTn oO31qJQyynOCMc5605l6HJOeAPaok13M5STdhPmbI
-  KgDPWmncI8feHsKk3nagTHTkmo3yF3D8QKa auJybeoE7iWyDTSV8gZbOcZA9akDAgnYQ2PmNR
-  Md6gEr1p7ly9NBhUFyfmGcVWJAdN3G5Sx9varT kAnad1QO6nICgYwCTVQeu1xOV9LXRA25lDt
-  yQe1RcKflbLHn1qct+76dT2qry78HC4xnFO7e+xSl aOpICokwcEc9BUPl7W4PGM5zS5AJCtjt
-  zSFl3lmPTr2FKO9kzNq5Ex2oFTO71J4NRlgX5baQ2SKl b7vp+FRyDcAcgYHJIpy8h82uhG+Sv
-  Xv+dIMrIQenFOJPlhQM49RmmseORgk5B9KTTaDV3EO7Chuu MZHalAKklRnHQ0jOhHIYkYyaaA
-  AM5LZGeDxT3uNu0dR2CS2c5x26VAyjJGCRwMelTDduy+BG1RBR v45GeTnpSunsRGdncQ4VQoB
-  LBehNQMWdQVG3Pb0qRwDyxII6EVC5XYBuG4ngU0+ZBZXuyJziY9el VpCpi3A855qeRT5hySST
-  1qCQgDYwwM9cVUddAT8yFyoj3kc54yeoqq0iAfezj3qZshcHHI4qux3D sW6dKpIm1yLPRTkA5
-  xmlfDRDhT601gUTaTvXoAOpNRD/AFIYqwGfm56VN0nqU+e+iHdQGyMU9Xyh ABHPU1CcrMQeRn
-  IPajcxK7gADyMd6q/NuOUko7DiwAAI5I70mSI0zxnjB60qYxjGD15pA+ZMMVPH 5UOavawlG+o
-  8sBCdqncO/vTH3gglgvHUU1nGNwJb6Um/12kHqTWV12FJtLRaCZOAVB5PXqKrswGA e/A4qRid
-  pAHocCq8m4nkAHvmtORNh53IflDFdxyF71Ucose7nkcVO/31BBBJqCVVI2Kc+nvRdpak ucb7l
-  Vy5baBkd8VRlYHhvlIORirjMSwAypA6mqLsvmY43E8H0pWQk9Tz8KpjJDFgO3pVqHAtx8pL E5
-  BzUChIpujONw4FW12F8E4I4rZWWjRKqPlS3LaffXH3ic5q1HzGrfN16dhVKHkxkZy3I5rSjc4J
-  I4J5A7VHLJbMq6jqSqQANox6+1XomDIN3JAPPUVUTmRQoAJHQirCLhlGCAOtFr+opJPUlBUqrD
-  Ab r7VYXPDsASTnj2qCM/OwwAM8ZGashQ5BcgqAfu+tN8yfkaaLUdGHkUZxnGasqo2jLbiQcKO
-  tRKmR hRgYJ68inqSsiY+7twKE+bWxklfW5YjJ+VcEt/dNTKMIG3Luzk8dPaoVBV+Dn196lUDa
-  3t/D9KV0 nojWy2JMDbyQzHONtTooG4knHHNQJ83JUDPIOKtpvEI3Lyeg/pR0stxxajoJySxwT
-  zjIq1FxKuQe mMGoUwQepOMfSnqCZPXuSKmWq1Y3YljO6VVIKnGB9KtooE45xkY57VXUkyLkj7
-  tWgcle+BzUXtsT JvZDt+JTnJGe1TrzGVAJXvnqKrZ6dAOpzT45SBuyDn06VVna6C2mhOA20FT
-  vA9OopSxVidnBHGO9 RlnKrg4PAp+T0JyAODjrSk4p6iV7oAflUkdD3NTHbkA9AB0FRBXJUYYn
-  HFSP9xF3Ddijmje472ej JshpAoI2jgipRu3KVyQDzVSMb1O1stnJJqzGxKk5xxwaUk7jcGti0
-  rLn7uCOM1ZyXG48jPFUlYlF Lde4Aq2kgEcfqRyKIxafcIt3ukWs7Y8iTI3DrVtQfmzzz1qih4
-  AwMdR71dDkNwcelKo5dR2luiwM LwBxjgk1OnyKQoJPc5qIEFACBjP409VyMgj3oik9bDb93sX
-  EwARzxwOaUfK5xkIetRxklxjr+hqT d8w6An1ovyuxLbt5D9+F6cdD9KVgNw3nGRkc05mwoPyk
-  49Ka+PL+YZ44OKEwjN20QDiU+XkjPc9a d8y5bB3E0ijcvAKnGeOhoEjPnkL+FQm3ctvqG1DI2
-  44yOMUb1BAGSSOQO1DGMg8nIOevWmgHYflx 82QfarUrIIO6Ji29BjAwcc+lDEeQCOe4qBR+/w
-  C4X1p+cuMlR7VD3FyNvUXdhSPvetB3CPkYY8ke lIWZlzlR+HWmM2VGQSc4x7U1eW5Suh7PkAA
-  84wfeo88KBgtio2YuxXBPTBpWxwOVApyVlqLlVtRj MzEHG1c1G2OR8pB/SnM/zYbkED8KjYnb
-  kcjuaq7W+hU1MhLgkgnA7ZFRMyD937Zp8o7gYOM4JppC qSxxnGckcVNnYhxttqRA5k6gEdc0O
-  +EVtpIPX2prHKliQD14FIZCUyFHsDVKydxxetxh6sXIOeQB 2pn8POQemeooOGl3g4bFMBONzZ
-  HfHpmktdWKT5XYT5WRc5B9QakPEHPXvTHIkIKnnoP60gLNuwVJ zTTuKb2YnO3HGO9KcKByOBk
-  H1qPc3CjB5546UbS7ZzznI+lVJdxTaaJWc/LyvTn2qsTjncCM9hUj KB909ByM1GwG5iAC23JW
-  iDgtCIciegh5UAj+HOf8arSKoZT0zz9KezNtzjaCBkU1pQFJzyOoHaqb lH4TTkb0WxGzNhQAC
-  MZ5qkfkQ5+YZ4PrU5kZyw+ZT6mqrnaFUnJ5zU6MXLb1GM5zlVLehqEswTgd uuOKeS6ttGCeB0
-  qs7Yf7rZ579az0voC0VmhpYEEpyAc47ioeWYgA46nmnOxDKyjjZ27mmBSGyCCc c4q5WWw7voR
-  lHKgHAyN2acmQoO7JOce1NO5txPUnJA9qe7jyVClSx7DtTdSTtZD57jix8tS5AJOS MUpaPYxC
-  nkY96rjO5QQWJ/KkYsEyeB3I70pQ6tEQsP6SgjB5GRS5bzmGR6jiogf3bHIB/XFMZ2ST KsOec
-  EVad2kiUkk2JJuaYOHGc9qa7Ycg84OCKc+DEoCkAdvX3qq0owxwPcGh2Za1WiB2ONxB3AcE 9q
-  ol9wH8QBzuFTOTI20KykcnP8qqMCAQflwOhppxvZkxtfXcYSqtnJYEdfT0qhNuMrbQCoHX1qy7
-  rsIRh1/Sq0j7V27i2eeB0NCdpbWEna7OBjLrcgyqT34q1GvKNtYk8cGq0QO/5zyw5J9Par8ZKQ
-  4O OeFNaKKixSUlui1Ep+UYPX8h6VdiQjoG5PQ1SjOUwuR6k96vh2CrgjJ65FJyadkEd9CdOHH
-  zZPoO 1WFKYBBye9V1XEoKsGJ9quRgA7SoBx19aXNd6blOcbk65CBSQT16danwR8qg5POagVm2
-  qrLjaMA1 bQqqhiRzwKcrp6oIpLzQ7bv27Th8/NS/MzgNkbR9MilC7SCp5H86k2tkM4JyP1oTX
-  cjn7f8ABJUK mJwGABHyk09B8rBcnA596ZCRtA6sOOKl5Ac7eSeah26LUpSbRYiZSNjIV2jjNT
-  DhVPU44HpVYOS3 KHgdh14qbBaMGs0rajknFpskTJkPG0A9+9T4POM7SaroMRbG5HHNT7hyw3d
-  fWolZsaqST10JsgKN 3UcVKpCSYBPoc1WDYOeWBxUpbc20AMc9/Wrd4vTQcnZ2ROhyWx90HmhW
-  B42j1BHpTchF54Oe5pqn bHzwTVpXQ7LcslsJk5G09RSo75IBAye4qBWIX5sjihWxkEgqTkGs7
-  LZ7iastNS3ucyZJyMYGKAxW VlCsx3dahYgIdvXsKlUkrgHBbrSdkitbX2LEfJ+VgpI6Y61MgH
-  mEBlyBwPWqu4hl4yvX3qWJjjad pbGOByKLahHa5cQncp64HfvVxVBTIK4Pas9XPC5B9asoWUA
-  44oS0ugvZdjQUgyEggLwB7VaQlgwO Ce+KqIyBgRk9yD0NWFbdHlQQSMginH3mRz3diynKEnJJ
-  6j0qwvRMZyOoHeqiHG7nBzzmp0fadwPT pnvUSUraGlu7Lqv84HAOQcCpFTPLNli35VSUBRuOd
-  zcA5zVkNgYzk5GTWlraoU79CT+IqzAk+lOG DjPJHUCoULeYN3DE9COtSBwDsIAbqTRPunqTKo
-  3uPBZQT37Ugww+Vc8cgUxm+fgHavSkLYOTgYqI pmlpJXH7gCFw24npSbgVIJOOn1phb5g4PX7
-  xNIpBlZ/4c4ApuKWqTJfw3bJozxtY5WkYgHK5Oema YDjIU8Z545oYFkUYJwucipi7SuxqUn6D
-  95Em08EHnjv6Um853bScnr6U0H58nrjvSFvlBwVB7Vcm mKKtqOBbcCMNgc0yXnaPmzu9aQnK7
-  kYEHoaYzhXGWww6A0t3oHQa7EggjAA4Pf6UxORxuzt6mnkk RAZU46Co2ZSSQ4HajWzByfLYgl
-  B6McA9aYPvYGcEkYNSO4XGQSe1QNJlkHXvn1oTk42Y76CEcjJI I9aYx+ckEnjIx6U44bkHnJx
-  moJTtAABxkHNS7kryEcsWLAjoBjvSlMKScn3qMsN5zxk9D2pu5t5x 86YzxTk5dNAVO7JFPy9V
-  zt49qUYCYHPTkVAhJhztOfbtS5AMgXOd2atxSbQSbegrsAMLxzxmgFsj CnkZyD0PpTfTuBjJp
-  ruTFlfuk4oa6WFKAfMcsx9M8UwkdCc9uO9Mzt+UHqcZ9qiB2uTtNEvImEls h7FtoA5UdCB1qA
-  suWGC307VI0hOcjAYZzmq2TlyF6EfjSd+U1jGUU7sVmLP2UDnJFVnALYIJ460r 5KjqSfQVCzA
-  uCxGSOMdqmDa0Iv1GEnc2OhqBlHzbvl9z2pzOvGC27GDVc5GSx3Y4xVxWlx2k1dDM qBvHHPy8
-  00u2SMKG3dMdKRSGB9M5xUJIOCTknk+xqFHmTZTk0tR2SsuQMAr1NIULOjA/MwzxUTZV 9ucZ7
-  ntR5gV9xJwea0SaWhE6bvpuSMWWTHLEelM8xS6gZzjBz3o85TICSMAHFRNIPLD8ccAYqEm9 ZI
-  E7rRakm4lmXCnnrURxj5/vZqMFcsTkEnkZxikkC79yt823nPNN6MnlvuSNJk8YHHB9aqM20tuO
-  4Me3YCpN/wA7AgAYyc1XLsycYwy9SKuF9hW5XqhrFN+QTtHU5qvM3ICjJbgnOcUjEH5FPINRMQ
-  xA OVLcYB5qrK97jvHQgZPk7YI7dAaqsCsjgHB75q1ICq8ZfmqTjc53EqCKOfm0voEXdO7OOUj
-  zF+cE dh9KvoWZo2ypXb0xWdGSQPfjNXot4QKE4J3DNae0bCSdrMuwhS6hsEYyAK0Yvmj2kEkd
-  CKpxkM46 YI5AFXEUmIEMN4GM1EbvYybu9CULmJeAFBwR0NXN5BH8LDgk1XjVSSVyST8wzU0RG
-  4koTim02+Yt O/QskZB2LtVj1z1qyhOeQox61XRsDplQcfn3qyAQxkwS3AI/rSumrMWpOQxLbg
-  Cc4BoX7+WcD19q i39CPqQaeOHPQkgcVlGLvfsEJ6PsTL94lTjI6irEbkPh0bb3NU1CrErZIP8
-  AFz3q0h3x8sc7uRVS lfRAn1LC8KDnHf6UsbjyyRwM/eqKM8HJOOQOakT5QCOVzihrqUlH5lkN
-  lV6EYORilUkgbSD9KgDB 3AY4bGB71LnfGAg24GBUxTiU5cr0Jy6CNskAjoM0oBOSGHTg1CcEB
-  iMPtAyacSQgZSG5xTdltcLt 6LQduywyS+DnOaejfvgx5zke1V1ZuQBk+1OVgHJUcAHNNyfUuN
-  +m5cJJZRjnufpSYJCsB823oKgD 5YkkA4596AxKHJwAO1TTk73YlK3Uubl8vkbGyAMmpI+ZgDk
-  ADHJqmADLw+H9D3qRXy4HIyOppyin 1J3TLSkh/vcY71KrfviRnnrz1qupDfNnvU6fMVGPmB7C
-  lJdy+ZblxXQsDjCscD2q4gG1MsDxjGf0 rOU4IBx1/KrcQIj5OBUPR2XUlzvHVl5MmTDcY6GrU
-  U3zFTngZGKoxv8Au++OhA61ZR8OuVx7049g 1toaMUihQzKST61JGCy7eAR0zVIM2Bt+bnGM1Y
-  DAxnIII75oQ4rtoXg2FI9B19KkjI8xx3H61VQq eTnb9alXaXwThQM5HehWdkNJJWJvNcxgsrA
-  5wD6CnqGWQh+gXvUcZDKFB/E05WzknIIPQ1T0dloR a6FBUgDPvTyxzkABQOtQh1VjgcHOBSKw
-  8woT9PpQrvVjlAnRlCHHzHdTSPkLcjB4/CmsF8vjOAOv rQFQIM7sEHPNZ8yvuCjyq7GrIS2Oz
-  HJp5kCH5mHFRLsU4zyBwfamsCAG3AnFaJxbsXzJsl+8MFgx BHSnbsSAEEjHGahRv3OSQWzk4p
-  u4MSec9AM1m1d3uNkiyElRwo7DFMO4jAIZsZBo6qG4zSAZdWJH XnFXzaaEuKirsRuyngk5zUT
-  OhdCFIwMZ9akdzvPTj261AwO08HcOnHFKyW+j9SkrLcj5YAqRjFMw pXcGAYHAqQ8n5QNpHFQk
-  FkBQAE8nNCm0gspDWUFm5xnmomBO7d0B59qlwA5Qg9Ofr7VCTtRiSfoe 9SpXVkyXroMccEHHT
-  J4pmQY1XcFwMk0u0MysTheuKiPRiULHGMA1XLrqxqSTSaAyeXFxjrT92Y2X bgdSR2qDBO4MNo
-  B4pwZmwQQvrx1FVaSsyZWtckLZTtx6VE4PlkZwueBipN4VT0AHTPpVZiruMucd cE4pRm7jWm4
-  0nbCQxIPIFNZgB8xzwKQMecjg9CaiLDCknGOufSm5N9NAlKLsx+4spG4Edj6VE7bl U5LAc5X6
-  0jN8+ARsx1A601G29BgHORUpNq4p8rSbImIR2AYgHqPSoWJ3YAPrT3YEMRjrmoCQS+GI JpXuh
-  +VyNiS/ODt4+tRZwgxktnk1IwYsF3Dbjiq0nB2c4BBq4S3QOXQa/CnjC54yOajI/d5AP5VI ZC
-  FcfeUtkH6VBJJIXDBTt9BUpyetiOW+vRDB8wCk5HXIppAMTBSODhaQvmQj7vFQOcgqeBjPHHPp
-  VR10RXs5Rt9485wSBgg85/nR5gORj5VqKNS0LKTgHpzSNjIXJVfX6UNO+opqO7HeYfMACk57+t
-  IW QuScHA7U3eABxyehqsTlAAGxuzk+lOe3mRTS5idpBtDYZc9agbhz1Cg8Uudm4daiZgAoYdO
-  BikuZ 7lp+RDkl8bSoHrUL7V2u2ckZ4PepGV+X5yemKruchQykHr7YrX7VhcuuhHIwzlTgexql
-  Ix2Nhhz0 Bq2xBBGRuPI4qhKxDk4yB2p00kyVHXU5WIPgA/Kd3TFacbHYM9CeMCscvm4AVmZFP
-  PbNaceMgsTg t096cIppSe4oQdveZfhU+YeeM8CrUf3mYfdPvVeIncdw4Pp2qyqho9xOPl49qa
-  31B1d7F2LiIgkZ xjHerYOVAY4XntyKpL9xVzweCcd6tDccLwAG5JqJKzUuwKVtbEqn5gUxgcc
-  +lWI/u5LZ5yBnrVcB t+Bjk849KsIACUK4zycGkpNsi2t7DwckqMktzmnD5hnkc4564qLJLjgh
-  exFPBbaMnopyfeqcXpct Su/dHsSzsNwx64qxESyBcgKO4qqB8vUcDp3qdXAI4KkfeqbJ+Zb8y
-  yrNsYgfP7VOrYUBmJY/rVJW RQ5JIG4Y96lWQPGNnDdBnvUTve2we0didWywC7SM5b2NWFbMi/
-  3vSqQLo42kBe4I5NO4JZt25uow ad76kc3NKzLgIIO7JK/ewabuwMgg5GcHtVbAC5IIGRg5608
-  Hk4H+9mk7l1Hd9hxyuMnGTz9alU4P tnJNV0O1/mDHJyfapI2UrlclT696mV2hy12J94BYYLEn
-  I9qkJTyzhtxJ6f1qtyZSHODnqKdgAk5z 7UJx0voJSTdkWS6hyQcfhT4h+9y2eDwKpqGExYsCM
-  8CrCtgEEng9fU1F7PRluLtYthgpcjIOe9Tx bsh0OCfWqZYspPXBH4VYVzs+8oDD8jWqatohpO
-  yRfUlQTkAk4GatRnIznORgVnIExgszccc1Yhbk FidvQKDWTjzEWT2NKNmO4NxgdRVgHLrwTn0
-  qipWRv3bDGOc1aTy9u1m556U3ZO1hve5cUtuKqOCc VbVSAehPQ1TiK+UD2xVuMk9hgqKcm3r0
-  QStLoTJklSwzxjC1Lg7lAIVQOM1ArFMsMdOB7VIrgxqS ec8j0qk29hWcWTpkKMMB6e9SEneDk
-  HnBqEFdoK9hkCnZLLlVbJGcmm2+oJXWmhPG+ZmIC8c8iohg yjcBk9KcG2Rg8ZxyPSkDqcDgMe
-  pFTFNXaCKiODYO1jgLwR60KN8h+b5cZ+tMYswXaBz0NMLFc5Bc AYODilyaaGyjpZMmZflxwoH
-  eoxjaf4mB4pT+8AIOBtzg1AASCoO0g9SaairE+9Lcn2gcgH5l7dBT VZApbhiDjg0zls5bjouO
-  KamDn5WH9fepkronybJfMAk5+Yd81FuYEkHPPbpQW/esAMHbQMFkG5Sc Z4pOKaG1FbiYfYGYk
-  U08qPmKgDn2pWJVflHbpmoHLAAjPv71XvSe4K+iYhOGyOw6CkyMhiMEjqPW lXOct1DcZpjDL9
-  T1zUpp+odbXGM2wl1OXPvUBILIT09aectk4/D0prAbQOrY6elKLj1FfR3ISylT jJCjFRMGVXJ
-  OB1B9amcEJtUbsjJA9fSmHLR/Mp+lOUtdBR03GphHLHJZhjFNdnyNoAH0pGKonck/ 3jSO7Lyg
-  GAvI9qbb0E0ubUiZ8SHcSQTgYHFNJBBUsu7AIGKc3zbWUnGM/SqxY88jIPHHJzTSG7dx zNghi
-  eAOMDrUTsrSA/eHTA707dmM7uD0AqEKxXIXAB60PVXvYmLsrLccVUIpOc9jnioyYtuBk8fN z3
-  pxb5twO4jjHamEfeIGB/OhOyTuDhciZsqQoBNMJznO0euRTyPnycAZ60xuWAJGAfSnv0KurWKs
-  jFcYPA4zTGwTubn/ABqdii43Ju5/CoGBEXHXGcelSlfQr2t0QSMVGMAsB0qEO5UnIz6YqTlosD
-  rx zUMshUkDH9aqTSurERtuiOTb5YycMDjNV9xwTkccHFSuysfm7rkc4qH5TDwCCPyoVt2Cm3o
-  MGQD1 BPIJody7M2cLn86YzKYs8l88AGneYwjw6YHvROVlexXNqMZkYKqdcVG+WTb368GgqPu5
-  wB3qMD94 R3xkGtoqDs0wtZWuPATGMtk9CTTC43MAR+NGAB7fyqJt2PlGQeR71D1l7pDV72Gqj
-  LIdxyR0qJ2O MLgt/EfSnklfvZHrmoyDypXhl7VMoO+pm5JNMrsMxkrgtjvWZNkQspPzAf5NXi
-  eOAwYDnFUJs5Zc 5OevrW9JvpsXFOMrtHNwKAFBYMScjHetCF87Wbam0YOfSstFO7cSPp6VfVs
-  NgDdu5OPSs4qLd0Ja q5qxvldxwUzzVhY2Mqsp3DHOKrQqRlScjsPWrilhGQN3J/Orje/MiG0r
-  8rLqgbQeQccg9jUiFjuG CTuAxUMZwuHwSefepkJDll4c0ScloKCstSVMA8ghgeecUoblMZwR6
-  9aiAORgFjnluxp5faQGG054 PrSUXzaDdtEiZT8uPm5PQ9qkz8uN25h1+tRIMyckZzjJp7IpkL
-  Ek5ORipvFsttbk5kAx90NSugd9 24rzwPUU0FQG3dB1NM3dGB+mO9KnJ3skCT3uTO2U2EfKp6m
-  pgVUgJ1B4J71W3YOMFjn9KlKn76hv qe1Nyv5BBPUsB3Eg+RmKipN4+V8HHt2qDLBSQQSOpp4I
-  P8SjPNRFue5UoqLLDOcKu0AkdaaNzcEg rjFMUEDcpL8/L3NOyrEhmAA6g0pNJ3QLmXmKWY5+Y
-  eoxTg4C9Qfp61CVBG9enYCpDgKTtx9fypXY udOKDzB5I5781OHEjEoM88VWiKbyB+JNTK+0n5
-  MDoDVW622CKS0sS+ZsfdkYPQd6nV2JGcdPTqaq 7htUnle/t7ipVQkKwJ2rkY96W+5bk3HYvq3
-  yqdw3Z5WrMcnzdm4x0qjGNoBYjGeo71bDDIUfpURm m7WEloWlbDYxwO9SIwyrAH3qBSNp3ckH
-  oPWrMZ3rgYJBzVRnZbBbsi3HgkscYPAAq2iN8wAHHVjV FFZl5YDvirIBwu3K/Ng5NEn5iXxWu
-  aSsoVFBwvcCrKEAtnP0qggJjKnbkDOcdasoDsUg9PWnN3Wj HZbEjt/CDwecjtVlSBncPmA5NQ
-  BcFQVOegp4Y43ngHr7Uoy7FxkraEylcHHBzyDVne7TFVIA61VB woB4PBI9alz1ZelEo66slyb
-  RNht+5iMY4wKe+1o9xPscDqarA7WQYzxzz3pzEhwGUnjnFFpJlXF3 7DtByMjHrim7ShJHIJzz
-  3oY7WG7oB6UhfAIyNmeDTadrIcJauw7cDxtJUDk/0qPy24xnceoPamBg rHJy3UUquTIxJx7+t
-  JOUdkEnLuOG3zfmDeoxSfLuY/NjPODTfMCyHnIIwaY2GYkZLEYIBoctrkPV 6inAYsMkAcjPNI
-  rKr+uO9NHQEEbv4hmgFsDcoGGyaHJNWKkiRmQrnkccGmE/KAOVApCQCoYgZ7Zq PI3YXcDnj2p
-  uy3Jd2tGDZGC2cHrn1pgYgZPrn1pc8sXwwzjHpUXykswOc9qS5Wxy0Qrk7QFYMSOv qaiJUD+8
-  3c04hD1JJzxg9KRVz0IwTyPSiVSCTfYhy2ZDIu3ocE8ioy2EAY4APX3qRvl2AfMp61Vc HcB94
-  fw+1SrSdmXGLkxjjdIkhODjilIOCScHOPanHBAOctTWweeDx+taXb2JmrvcR8KjBcg9OarF WB
-  5wf73tUzMSncc9fWoGJJIUEnHBPem/dVib2dxkpbegUAn1HekYZbkbexx0p45kUlh6sMVHklWO
-  Cc96zUrrQtSXYa0ZTJUg4681EWcOA3TsfWnO+IgT1xyKaSdv3SCeMU+l5BJNIRmAYgjd6H1phK
-  rG ASMAdCacQPN5YEY4xUUgHBIJA6e9OEbbmfuN2sV3zv4OVJPJ7Uxcqwyy7duQcdanLNvZSpw
-  AOKrn DBsrsGOAaOddTXV+hXZgcYYFgckAdagchs7Rk9Qo61OxCyA8MT1qttOeCO+D60JrbuDV
-  newwg7SQ Ac8cjpUBkJypAU55OKldiqbXHU5qqQGlY5znGMd6laXRiovqIwKuwIwAfvAVCPMAI
-  fLMTkGldynG QADgmohvZevGOfrWkNVdm0bN3X/DjxzGcMAT3Peo844OSxHPtS7ioIABY8gYpA
-  Bt3Akdcj3ppva+ gOpaLQ0BgAOdw6/jSO+F2hTkcDmlLsY1XK/722ojlZgQMjj5vU1XNd3fQzu
-  t2DszSnI2gDkY61Dy Mj+NutWS+ZCRjOOpqgWBdwFJOeTQouXQatezRC5LHpgDg8VSc7Fz6nqa
-  tyA/Pk5x29aoykkHd8oL fLQuW2oSbscvEXB3N0HUHvWhEAATjHGV5rNgceUzltwPQetXomAUM
-  Qxz94U3F3aasT8PwmxGSU3b vmOMe9XEfaoHKjOBjnis+3G4ggjYq45/lV5CCwyvy579qFCysh
-  Xu7dS6Dld2R14NS5CEHIJJ4qoA d3UYHBFWVIbjac4x9fehwT3ZK0JFdgeOFzyalCKTnDH0qDG
-  Fznv0qSMFgRg8HjNVL+6Va71Jd7KR 8wJPQVKWAYAdCcE+hqujqJRwNygjPapAGweMemai10KS
-  8rEgQK2c8Hkg+tKPuEkY5qNVwCS3U5NS bCBgklQeRUu17FRaHn5lxzn+I+tSoSFIBwB6+tVVf
-  ORjBzhfcd6njUM5xuwf1pTWlnsOcblnduxu UghsfWkOBM67h97oBSKTGCf4u+ecUiBmf5uAe9
-  EYJq/RCT0vHYsLuIBJKrgjPYGmtIwTG0DI5OKX DDojAY6noTTWfcF44OaElo0aQemmogB24BO
-  Ac/SpWHDBWzznB71Dvw5wCASMj3p7EOcjIYcnHpV2 bJcFLqSEKZAo4HU49KcBtAcE4xzk0wMh
-  JxnJ64peUCYO5AORWEZu9gndLyLOAxwMFs8VLGWwvXB6 1SXesi844I5qaORiegwBjNU4y5bvY
-  bskncuq245XO0Hmrsajdy3zHkc9KooPlJ6BQB9TU8LZ5IJI bn3FTvpHYpu0dy6rkoqjBz6CrM
-  YbaT3PcVVTZ1Ugk9u9TI58xQcL/e9qpXtYWltGaEO5lJIG7PQd atKAY1bsRwKqL9xQA/Xr61Z
-  ickfwlQeKXJLdMSRbT5ARnag6GrAJLp/e9+9VUfeCcHnpxU5diBu5 7Ad6qFuZ33HFSUtiz5jb
-  23HhjwKeoVQwLfMBjGelVjzjJwOwqUMdw45NJJLbQNVt1LQZWIODtI5N P3oMYI56k9BVNZOgJ
-  z3x61MAShYY+hokrEyunqywHUD5myCeo705STjHQAgfWq2/quDjscUuS020 EjA5Oe9EdtirW2
-  Jzgq28YYjjPpTcbcDdxjkVG0mTg8sMA+1EcqLMSQxAPr1os+XQlybdkOZwJPmX K5GPpTGYLJx
-  1I9aN5KjcFVevNMbeu45UjORx+lCkirJhkiHaMZ9x1pCMMmWGTyCO1RF22MxTPWgP iE8AEf5x
-  R1KvfdKw7euCcMMDFMySmwsGJ6GoSSAOhXv7GgsxYlfl9eKTTuHLtaxMSWy5IJHA9qYC dzHID
-  DpxUO7Oed3c4oDgxkkgMBjFVJMlwWo9m3AABgAevqaZtYMTn5c8UEqDhSffmoncbM5AGMcV F7
-  6WFboPXBlHOcGkLnO3BxUGSGU5Bx0AphdnYnjj0qlRT2Y4au9ywx+U8/w9PxqNiDEW6cimLKS4
-  LbdvUkd6Vj5iuSAVJ7UJNOwnF3SYwcg/UEVGzH94QdpzgDFPHTYDt96TehfO5cdTQ3dkR0ukVi
-  Qs Pynvj3pN/wC5YL1zg56ipyEaL1btioXVgzbSvXoKlyj3EktmyAqythTzjmkYsiK2Rk4PSpM
-  KEOSd x/Wq5yHAAyB0qU5PU2u7DmZc5wCfWo+THubnBwMUH+7kDI4yKR2xGAOfWr5Laoydo2Eb
-  arBiSCeM VCzFmQHsMfWpc8c9e2KjfcTkOARV3TKtdDcgjdzkngVUk28lsgnoKmztnbecY+6Kj
-  b5n3EcEcmpb irNAlZ67FVmUM7gDBHeqzE+XnrjJwPrVqZx8uQSuB+VU2fdJgKetJy5TS7b22K
-  7kc43FTzzVd5dq Y4Ge+OtTSBQ4CnHt61C5VtpAwAeAeorRxW7J5o3vYPl3hB+vvULZIC7Tx1N
-  K2dmWyQDmkVkZujZ6 4rNcqRN1zXEEny8DvlcjtURkG4b/AJVPb0pzkYK5yWGQF7VCS0jbSR26
-  itb2d7D5Fa6HEkMSD26e ntTS+dwB2kcn2PpTG2iUjOPm7/zpp/iLE57+5qtRJXsmSFsBGP3jz
-  VRzk+hxyfWpBvaLocVE5UPG OhBxTp3TEmkRuwE2Wxg+lULggN1wMA81ckZQxU4K5+UiqExOeR
-  uQjrjrQtdNrgpdzlLcLt2nue/r V5CDcKT17g1TVmEYBKqSCcEdKnjyp6goRxn1pxmpRV9xcrR
-  sqSIwFwcHnFWY2YcBwQKzF/eR9Tw2 G9quptC5Vvm4xnuB1qFbW7ErPQ1g4OC3c4qZJcSbkPAH
-  f+VUIwSmVPfuasglUzgjjOe1WlGWjMuV bssmYmFRgcYzxzUivuIXlXHBqHLBjnAA6kipQqgoc
-  8k4J9aJuNti+aNuxOFUHO3cR90jvUse0yY2 sGAHWq4DKxDAlQ3B9KkQcr13Dk1k0mm2UpO2g5
-  QDPySd2fyoO7eu4nBFI3EhOcL0zT2zxyDjnFCY 7dmPGDjAO5epqQf3s8YxioEJ8tTzyOR3zUg
-  OUwzYHXP0qbu9rijpLQnX7xLHginKwMeXGCTUKA7Q Mg7jU552pj5geBim7LSxd3fcUM28bySN
-  pwBSfOCAD25GKjLOW4+THHI6ikjU/OfmLA8VUYpapgpv XUnBAj+YZYnj2pW2FxtIA24z60Fw2
-  Mqxz/FTCVYZA2gHPX9KNXrYyTe9iRGRdxYEgDjFODqUyAWV uuOxqH5ZGbAIBHTPenKxCJzg9R
-  7Vnyxi79S0kt1qyePGdrA5xjJqWNV285GTjmojk5crtxUqkG2Y k7z14FP2lxxeti4BmE4557V
-  ZR8EYZeOnpioIyFOBgAjBz3qUDg8AjHbtWSnG9jaLi4l8EBV6MT/d 71YABbI45qjCFb7pIGOR
-  6VawAB97d654q+ZNkpR2vY0oxmHk8dRnvU0WDJllwM96pRD5gCe3HPtV 5WXCBlOSOue1Jc1tD
-  Nx6LUn8shixb5cZODUytmIdMDoTVZDuBwdwJzipWKiLGCCCCaHZ9Q12LHmf N8oUEAcmpFLlmx
-  jAPp0quDuUkDL5FTLkPgZG73pylG4XdrJC5AHzcMD1/pUqOcDLDkflUDZMzIeA uDk96RDgtxw
-  OgzV8nPqXJpKzJiWLAnB9cVIZG3HLA9s1AN23Bz/hSY2p3Yk5Yil7t0Q5XsiZD++D MwPHPvSg
-  nBGB1yCahyHwRkDHQinA/MduSDyD6CqcmU273uSbsyKcbgTSOxy2eFx61Hu3IMHJA59q iJBY5
-  BIPIJrJJp3C33Em4mDryp549aZuA/2Wx0Paos4yM9emKXdn+JQQOBjvTkne4pX7A0uZXB5R ue
-  D0pA2EBDHA61Az5IIQ5Jwab0Hy/Pxzmh9UEGm9SYuBk5xjj61BG4JI7Z/E0zcMckEn17VCXKue
-  wzwR0rS9o2YOyLJkG4rjn69KYGCtlhnnj0quXbeSB8vGfembgWVhnJPc1HvdGOfTm1sWgyqAc5
-  5z SkqVDD5SeeKr72YLhcADoKRSzsRnr93j86Ol7hJR6FjLAAgDIyMAU3ewjQFSF7ketRlmwOm
-  WPIpy ksm0YUA5we9Ta24003ddBWcA5/p0NIrAKC4UkjsKQkLxtLHdwR6U6QgQBgCAOORVwu1a
-  xKvIYGHz Y5HsaiJcyZCkc80rn5xkgITkgdqjLeYCoODn8aU421Y5JSkrobI53YZCee1QgrwcN
-  05Ge9PYqsIU /M/cUw5ZAQRVr3V6kPYYxAm7n1wcUEgRMU4U+v8AOgsMKWIzjkVE6kng4Hfnis
-  5PYbswZioBOHx3 FR7gz4Gdx7D2okKiJuTnoTUAbEhAPAAJwOa2i9DSUdE0xzk7y2OAeMjp9aq
-  vuZAM9QMAVYEm5Sg6 EZqAgeVgj5T3704zsmmjL3272sRHgnLDaowc1VdiR8hHP3j3xUrqC2GY
-  sSc9euO1VmYZZh8ox0NZ JXC+mpAzjaFK98Bqru2A5XGCcZxxUhy0o+7jGM9qiYbot3Bwegq52
-  SL1lZCMvzjJ+UDmoCxzkrgA 8mlYtglgctyfbFJIVXf8w3HHFZp9EJaaDfNydwPU56U1RmZstt
-  PPXvTQSFHzDI6D1p24hgGGTtNW 9CXGw1SAdg5XPJpPlDFEJPuaa20LlGPH60Fj8zgj3x2oe+r
-  G72uMbgkk5QnjFR5DjAPQ9+tBYHcx Ofl4AqM+oPPc+tW5XVzJS11K8u3e/GFU9aoyktje6g5/
-  MetWJGYI2RuGc/Sq0pVTlFJ479jVOTlG yZautf8AI5SMtKRwR6A96uIMRkvztzgVQi3ZJzkMc
-  DHarS+aCfYDGRSg76tk2cn2NGDLg46Edv4q tIWBIUFRjlj/ACrOjkOGz94A4CjGKtJlgNxIXP
-  AzTs7astrlgaSEh1O4qDyCatpuEqh2Jfb09az0 KeV3yDgjPSraksDI5Jx6U4prXoRFrYuId0o
-  BJDHOM96srgJt5z3HrVIK7Mr5AYcirEeTnuTgDAqb LdBbXcsB2aZfmO2p1yIjtOXzwB1NVeQw
-  QnA5O4jgVMpwwYn5QOtHu9LBp3JlbABCtjHPFNLfJtJy yjkAc89KGZxvAPyjHNIoOZGLBvXFV
-  G6V7jSVtCdSuxcNtcgcmn/dIUAMevFVQ5WLOFHapFLBtzDg 8E9vrWbpu92aOF47FknCphfwBp
-  4bMYf5s98/yqJPvbicANjrSNIFyAOjc0lByZMVJqyROwVlO0nr gUAKrhQ2GJyMmo8hWYtnO7j
-  3pw+djgEknjFTy9wimtCQFi/JGAccjrSgkvkfdB6VF1YAnjvz0pFP +kDdwo6Z7Vak0i5OKehI
-  h/dEcbi3GO9Skny2+XjcMYqsXCttB6HginjcioSCV7+9Z1IpPzGnqtCy WDMx3deasBsY2jO0Y
-  PvVPzE3jIyuKmhYs+Typ9qhpJik4vVFoHJ4ywPbNXkPyYbIU/mazyMNuALD 2PWrYKkDkqfQ+l
-  Obi2mNSfQvRHPygMBmrCu+/DLuAbg/1qou/goRluoNWkIWXG8EDgiiKT95jcW0 y7ESQSPvdDV
-  xQUVQysR0+maoQPjb1GRmrMbnbnJGPXmh/F5Ecr6F4Hy4Tzk9x3pUJfGSMDqMVEGx uZj6dafv
-  XaQrAgcHHWk0gu7WJsjzRtJI9qN37veu4E9aqpIN2Oq59amG5WY7sqT0rT4dRqNupYST OflJx
-  xUhZVjU4JzwKqxHI3MduTkink/u2wQcdDU/MTUWyRmZioDdjg0FyBjBJI7VArDcCM7s4p4J bB
-  bIbg1EnYNVp0LGW2bgdxxzx3pAxL9QGPXiq4O0sOeT60iFlLbs4/h9abcXqg0ZMZSIsdTjBIHF
-  DkeXGD90Dj3quzjeQVYgjpS5XYDg5B6Z6Umr6hyajzIWITjIYYNM5MjAnoRzTC5eY7SMk/Lx+V
-  Re Zg8tznJq3toilFW0JJCGIAb5hy3tVdnKMGwfmPTPanMAZHYA5LDAFQOT5uCc4PGaFq7MqPY
-  eSDnI ZQOBk1A7nkxlQMdSP1p5ZjGSRk96hZ9q/Njbjn1xTjduxKuhWcsgBK9QRjvSbgH6Ajoc
-  DvUGcqCO gPSlyhcBj3zwalvoyZJvRonZgAAThgeSPWlVgp6E88c1XEuG+ccnue9CnccqRgdhT
-  vrqwTsixE37 3kEHOeTU/mZyEA39c1TEkaz7gWz2p6kFgUYBei+tDjZ3a0CUepbA+QkMCB3xUR
-  J3krx7Z4qNiyFl PcY49aUMhUZ4yPWnDmtcLisQVLEdeMmmvnawXHHem4DHhjjPAph8wgYyfXF
-  S9VqNOMhJCSEPAzxU OSHb+HnPPSpSNpyPTjPrUEj/ACsAOeBTbVhJdENdhtTZtb+8RUO4AlSe
-  e1K4ZITk44qDqSw+4OAe tVpYdl0ZKzA5yTioy2NwyMjofam9X5yQR096iZmUsTjavAoTjazHK
-  0WrClhuwOucZHpTHD7Gw459 ulIz/ug2BuIOAOtQblRck/Nt6ZqeRPYUY3I2l+ZdpUgDP4VXMg
-  MZAUnBJBpAzCViFyOhpu/94eR0 xjFXyRWlhcq16jH24Vty4B6Adc1UkkI3JhQAe4709w/PKbB
-  3xVZ93m/Ng88E0RjHVFQ31FILxgZA 44GKrF1D/Nz1GfU1K+4jeO3FRsBtAce+aatorkyu3zDQ
-  Dx37kU0LtZiSSccc08ZUqOQDn/8AVTXO 11BGPX/ClOWtgc3JaC7gykg59qiB4yWUKRnn0pec4
-  4A6moZWG0EAYB5I6CiGl0jPmauhQY1QYPP6 VGZG344A9xTSf3TBCAcdD2pj/KQcj0OPWnNt6W
-  uNxtqROWxhsbjxnHBqnL5iySE8j+H2qVjtUt82 BkcnpVZyzEnO0gZwTUrnirrcqk3FnMoFZSM
-  nIPPsam3MqZyc5G6qyFDtByB61KSwK7fulT1Nb02p PkbFCfOXBOD1YZ+nXFXbeUmND/F/Ks1N
-  vm4PzY4AFWomKjA4IGeaThFaW1JaSdjTjZSCFHG45zzj 61MjgySDJOOlZsMrgeUFwauI24ggB
-  eOR60rSStYIxcXroaCy5QY5bp+FWklGAOQV61nAbnyCQe5q VQiyHcwI4ORRypPbUtST3NMN8h
-  JU5wM5qRJS3yMPlAwDjrVNGBJ35H49qkRwQevqvtVciT0Kv5bF osQNucZ7U9WY4I645I7mq6k
-  EAntyc08PlvMAxyciqTSexE2nsSxmQjgKTnk4qT5sNuPfp61WL/IM kkjsKkTax3fMWHbNZOLS
-  ci2tidB90BiQRkg1YVhjoMZ9KqAgAqM5wATUwRRCGLcdeKzlNaLqTKLW o/zMR53oVye3NPDNs
-  4YAbutV2UeWQAVwRtzTztb5NxY5HT+VaqXLG44vlSaHnaYiQQW3cnPFCnbJ nIJ9xTPlRDkHIy
-  eaQujfN944zgVF27dhqzW1yQyq2xM5OetOUzSOSBhe31qDzNpBMZweoxzVjcfL BQrzyBUybto
-  S5vsSA4ZiSd2fwqyPmiYAhXBqiCS+Xz6nHaplY4CgEg1EU76Cv1ZfRxsIZieRg1bj dTM2RgDu
-  azI5CJAxPy9GJHQ1c3Hy02+mC2M5ob63K5tDQibDgEH5hn6VZjI6Lwcck1RR+FUN8xGc elWVY
-  7h3GODRF2K23Reib94MOMhcgYq6shBIY8HI+tZiY3jHLY5x2qwrbiRnqauotnuKW2rLgkYf KC
-  ckdDVhjj5Mc7dwqisgG2Rh16D+dTGTc6nhvQ09biU1cs+YDtBHG3kjvThKMb9rECqxZhHy6g/T
-  ofSnBm8plbkg8epNFkDkm7ItiRWdgSMgYwO9GflxkYYVAM7gDwSckgU7cAcFx0NZKLvfcXXQlO
-  0K Q3zD245pDNu2kcHOPoKrmRQwRiXGM8HrTy2JMAqAOuacoq1maKyWo9WZXBYgnHSpeDzkjnH
-  Xiq6u zA4BJHT3pWkURnggZ5FKdrabmUtWmTl03D+Jj+mKiZsPkKykng9qg3MjoY1Zwe4/lQST
-  FvOd3YZp xSTsy2rInQZJzjI6c1FvVAey+4/Wog5zvORk460oCnJORgc+/NUopJpkKbUrsVpAE
-  65weTUb8kk4 B64PWlDYBPBXd0qu7MA2GXI6Aj9KlRUmXFtrQC7MeCMY4pCcsSQ3A7UbiAASOn
-  YUxuFBJ4H605WS CU76XGNjgYO3tUeflyGUYPzE9qCQyEbu361BuInA5IAzz3qqabjdFNN2J8/
-  KOdx7VIoB+YEe1VlI LKd2MHjPepuTu4ycZPNQp3eo5/DclHI5OR1z/SnoQuGGNpORVeMHAJwC
-  vT2pzMwj3ZJx6Cq5r3I2 67lnfucjIzjOD3pPMbLJ8u/OR/hUO5XjQ888/WlDK7Es2DnPPYYo0
-  S1JSTeqJTy69jjioSSzHk4z g4pxfMTHjp8opm44APB6kd6Oa6uO3RBIQGGM4Ax1qBypJy4Az0
-  70rP8AJ1yQ3PtUZfJwAMepHein a9hra41i+0Asufeo9xMJXIUDBzimtJkAnp1J9aY7Mq4JB7c
-  d6bTfQGlLqIznLZ7ntwTUDOC3cknI 9qldm8oAKC3fFVVYb2JIyetSo21auIWORTKQWzkHmoWw
-  ASGzx1NTOyiM44B6MB0qoVAlJzv+Xrmq VrdhOXYQsHQ4wr+lQH5lY5A5HSib5ckZBGDTVfgsS
-  o6np1qpNdCYySdrETAFT83IPrVZidzNkHtj FTtIARhSQc81A58uMOgJJ4ORRdtFvfyItwYspB
-  OB2prL/o4LHljnGeKU4YnjBx9KgYqI+pLA560J pNJEtdEDsfl5AGaRtvmMfmPI6GmuS6rgZwc
-  emTSrw4O5cE/NmrltZEpaNtjQ5MZPJB7Y5qFlxGzI cHuD3pWYtKcDJPSq7FgwQsGIB6Ci2uhX
-  PZWHO+bfI4yO45FRO2QQx4OMmnsy8YOFPXNRMwwU424y OKm7a02Jb6WK7kqzBsHBwM96rvgxb
-  jnrxUhO6Rh94YBzmqUhbywp+bk4Naq0ZJX1Hfn0OaVmBw2O OelSCUNtKHcvIqrHiQ78nKnnnr
-  VxDhfkwPTIpKKb5uoc0bNrqTq+VYDO4kfjVrBJzzjg7qrKSrkM ue4x2qwjbshc4PJJ9aG1cSl
-  ZbFtWCyEg5weoqyGBjHXLHNUlZFBAYccEVZRiHxjgD07VD91Dbk1c vrgOBndyCMVZYgMB1GDt
-  OKpoTgBCCMfL/jVgblxlgSDyxHFCfVCk3uWkYr8p5JGcjoanJwPTjnmq qEgKQRycCnqxySxUj
-  2FUtWJa6l778RAYcenehThixIK5waqKQV3Ipz9aCxymDjHUUkpWZcWnp0L2 7AZGxjtx1oBHlk
-  LgHpzVXeTtZ+BgYAp4kB+bgc85ocJLYOVK6SLqkbwrNyVxxSkjYOcDIyKqiQ7g WxwMcDvS7+j
-  jle4qfZtvUtKz3LIYgkHLAHpUuWRC4AA3DHvVQElcHC89TR5hGd2WA5FW7WaQra/o WncswLDA
-  waiB+fPPHpQZAzEHAGR/+qotxwAMH09qhb6ExbtZqxM8hwzbScfrSJJ1G5Rxx7VXL/Ju H5e1K
-  N4fGzI7nFTy2+I2SsXQxfcSdw3DO2pEdhls/TFU1fYjKDwx9KsIxchPup9OtTNSvqZKbitC 5F
-  Io2jgluevFXRKTIEJwO2Ky4yAcKQVBJJx0qzC28lyDg5/Cl7jfMLmcmaQbCb8jhueeatLIzHrw
-  elZqksSCpVeM81ZSQKMD5gXz9KSSvoyoq2xphwp8wn5c4wOoqZWbPDDJ5OOlZccn77BG5Tzx7V
-  dV wMEcZGTU8/Ky57abl9GUjG7d7elPWTqvJJ6Gs9HbqBxg4zU0LuwUEEgLkt6GtL2V2yaitZp
-  F4N9z JJyccVMCobnkY79RVIvhVPTj73anKxKgnJ5GeetO8rXuKMVqjQV/lPzDJqMygwg7SWHB
-  qMSKof5c 5OMelJhd+7kDvRdaihZbkhZty52gZ9Ke0gyeRjFQAOJSeo4xn0ppYYAP0pWTVjRS1
-  0LBmIfCHHAJ JoeXEhLdevHvVbdjnHQflSblKN1YD35NDjGJPLbct7yqqPfJpTKM4PUHt3quGV
-  iOchvSmJgH7rHa MHmp5Y31E9XqtiXeS5JXqeMUrKzSAbdox92oXZnU+x4pu5mdxnGDketXEpw
-  2bH7nLjO3AFNdSpPB L9aYWGGJPWo5pG2BOcj86Uua+hV76iuRvBz0HamBizNwRt9+tBx8rbXA
-  2VGwKsPmOxuQauLurDbW 0RJCBIpz82OcUAEHhgVNMBO4MT14z6VG2clFDDkEZqeS79A5+ZrXY
-  mfgLjv+lSEEREr8pz371CCu SGBwB0qMj90x5GW4PahxStYlSu73LasScMw47Cl8zJTuuccGqw
-  bDh8hmyQRinq6iNhkKO+exqGnb QN3ZFkkLEMck9famkgEvkF81XD8rn1/KpGkVkJKkDuaTi1o
-  Db2JCB5YGTu6ioncHaeQT1/wpuT5K tzwcnJqMOzBtykKTnPvVJcruhRl+A5mC8DJz3pm9lG11
-  IZumaU4AJYhR1x3qJ2BbeMgD5sH071Sd 9LCnNRFYKVCg9Bgiq7MFlIc4HT6Uu9ch+vHTvUBYt
-  IzldyZArWF0rkpNK4M5KEg9DnH0qENmDpli Tx60skp35UYUcEe1RO4weOMYX1qJPsK1la2orE
-  BNmd2R3/hqvwAVB4xkihpBkDn0YUw4ZGyMccYq oRvuNq71GHexJHzY9aiJf5m4PTIpzMyOCAW
-  Ug/yqPK+WE2NnBwc0QulsU7Kz6EW0+SwLZ9R+NRs3 y4ZsnPBFOH3/AJQRxyDURwM78Ar2pv3m
-  J2bI3I3MAQA3vyKiLHJC8sODTz87EEHnmo1IBw3IzQ2k tR8sVqwHACBucc+1Rs23O0n3zTcru
-  Y5O4DkZpnmbc56+9K2l0Q5/IduZW+XHGSeKruQWDZySOR6V MMKBkj3NVzlpCSyZI+UAdKFbuV
-  HRa7jG27cLxnrk1CThWHJwOQKkcbtuMFfb3qu0qguFU5HynFXL
-  l5dTOd1qxgYfaS4U4KY4NUJA23byzdMDrVl2D2+5c9gT71Rk++cB85yMmiEXF2Jb5ndH/9k=
 UID:934731C6-1C95-4C40-BE1F-FA4215B2307B
 END:VCARD

Added: CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/1.vcf
===================================================================
--- CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/1.vcf	                        (rev 0)
+++ CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/1.vcf	2013-08-10 02:35:04 UTC (rev 11592)
@@ -0,0 +1,8 @@
+BEGIN:VCARD
+VERSION:3.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+UID:78b64b6b-80b9-4b8a-bd81-8f36645d8bbf
+FN:Shared Group
+N:shared group;;;;
+X-ADDRESSBOOKSERVER-KIND:group
+END:VCARD

Added: CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/10.xml
===================================================================
--- CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/10.xml	                        (rev 0)
+++ CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/10.xml	2013-08-10 02:35:04 UTC (rev 11592)
@@ -0,0 +1,13 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<invite-reply xmlns='http://calendarserver.org/ns/'>
+  <href xmlns='DAV:'>$cuaddrurn1:</href>
+  <invite-accepted/>
+  <hosturl>
+    <href xmlns='DAV:'>$addressbookpath2:/1.vcf</href>
+  </hosturl>
+  <in-reply-to>$inviteuid:</in-reply-to>
+  <summary>Shared Group</summary>
+  <common-name>$username1:</common-name>
+  <first-name>$firstname1:</first-name>
+  <last-name>$lastname1:</last-name>
+</invite-reply>

Added: CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/11.xml
===================================================================
--- CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/11.xml	                        (rev 0)
+++ CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/11.xml	2013-08-10 02:35:04 UTC (rev 11592)
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<MM:multiput xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:carddav"  xmlns:MM="http://me.com/_namespace/">
+<MM:resource>
+<D:set>
+<C:address-data><![CDATA[BEGIN:VCARD
+VERSION:3.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+UID:78b64b6b-80b9-4b8a-bd81-8f36645d8bb1
+FN:Top Group
+N:top group;;;;
+X-ADDRESSBOOKSERVER-KIND:group
+X-ADDRESSBOOKSERVER-MEMBER:urn:uuid:ED7A5AEC-AB19-4CE0-AD6A-2923A3E5C4E2
+X-ADDRESSBOOKSERVER-MEMBER:urn:uuid:78b64b6b-80b9-4b8a-bd81-8f36645d8bb0
+X-ADDRESSBOOKSERVER-MEMBER:user1 at example.com
+X-ADDRESSBOOKSERVER-MEMBER:group2 at example.com
+END:VCARD
+]]>
+</C:address-data>
+</D:set>
+</MM:resource>
+<MM:resource>
+<D:set>
+<C:address-data><![CDATA[BEGIN:VCARD
+VERSION:3.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+UID:78b64b6b-80b9-4b8a-bd81-8f36645d8bb0
+FN:Added Group
+N:added group;;;;
+X-ADDRESSBOOKSERVER-KIND:group
+X-ADDRESSBOOKSERVER-MEMBER:urn:uuid:ED7A5AEC-AB19-4CE0-AD6A-2923A3E5C4E1
+X-ADDRESSBOOKSERVER-MEMBER:urn:uuid:FCBA0FA3-00B2-4C95-B4EC-4CCC4843F8B1
+X-ADDRESSBOOKSERVER-MEMBER:urn:uuid:78b64b6b-80b9-4b8a-bd81-8f36645d8bb0
+X-ADDRESSBOOKSERVER-MEMBER:urn:uuid:78b64b6b-80b9-4b8a-bd81-8f36645d8bb1
+END:VCARD
+]]>
+</C:address-data>
+</D:set>
+</MM:resource>
+<MM:resource>
+<D:set>
+<C:address-data><![CDATA[BEGIN:VCARD
+VERSION:3.0
+N:Thompson;Default;;;
+FN:Default Thompson
+EMAIL;type=INTERNET;type=WORK;type=pref:lthompson at example.com
+TEL;type=WORK;type=pref:1-555-555-5555
+TEL;type=CELL:1-444-444-4444
+item1.ADR;type=WORK;type=pref:;;1245 Test;Sesame Street;California;11111;USA
+item1.X-ABADR:us
+UID:ED7A5AEC-AB19-4CE0-AD6A-2923A3E5C4E1
+END:VCARD
+]]>
+</C:address-data>
+</D:set>
+</MM:resource>
+<MM:resource>
+<D:set>
+<C:address-data><![CDATA[BEGIN:VCARD
+VERSION:3.0
+N:Contact;Mulberry;;;
+FN:Mulberry Contact
+NICKNAME:mulberry
+ORG:Apple Inc.;
+EMAIL;type=INTERNET;type=WORK;type=pref:mulberry at example.com
+TEL;type=HOME;type=pref:777-777-7777
+TEL;type=WORK:8888888888
+TEL;type=WORK;type=FAX:5555555555
+item1.ADR;type=WORK;type=pref:;;1234 Infinite Circle;Exampletino\, CA 99999;USA;;
+item1.X-ABADR:us
+NOTE:This is a contact created in Mulberry.
+item2.URL;type=pref:http://www.example.com/~magic
+item2.X-ABLabel:_$!<HomePage>!$_
+UID:ED7A5AEC-AB19-4CE0-AD6A-2923A3E5C4E2
+END:VCARD
+]]>
+</C:address-data>
+</D:set>
+</MM:resource>
+<MM:resource>
+<D:set>
+<C:address-data><![CDATA[BEGIN:VCARD
+VERSION:3.0
+N:Kawado;Saeko;;;
+FN:Snow Leopard
+ORG:Snow Leopard;
+EMAIL;type=INTERNET;type=WORK;type=pref:snowleopard at example.com
+TEL;type=WORK;type=pref:777-777-7777
+item1.ADR;type=WORK;type=pref:;;1 Fidel Ave. Suite 100;Mountain Top;CA;99999;USA
+item1.X-ABADR:us
+X-ABShowAs:COMPANY
+UID:FCBA0FA3-00B2-4C95-B4EC-4CCC4843F8B1
+END:VCARD
+]]>
+</C:address-data>
+</D:set>
+</MM:resource>
+</MM:multiput>

Added: CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/12.xml
===================================================================
--- CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/12.xml	                        (rev 0)
+++ CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/12.xml	2013-08-10 02:35:04 UTC (rev 11592)
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<MM:multiput xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:carddav"  xmlns:MM="http://me.com/_namespace/">
+<MM:resource>
+<D:set>
+<C:address-data><![CDATA[BEGIN:VCARD
+VERSION:3.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+UID:78b64b6b-80b9-4b8a-bd81-8f36645d8bb1
+FN:Top Group
+N:top group;;;;
+X-ADDRESSBOOKSERVER-KIND:group
+X-ADDRESSBOOKSERVER-MEMBER:urn:uuid:ED7A5AEC-AB19-4CE0-AD6A-2923A3E5C4E2
+X-ADDRESSBOOKSERVER-MEMBER:urn:uuid:78b64b6b-80b9-4b8a-bd81-8f36645d8bb0
+X-ADDRESSBOOKSERVER-MEMBER:user1 at example.com
+X-ADDRESSBOOKSERVER-MEMBER:group2 at example.com
+END:VCARD
+]]>
+</C:address-data>
+</D:set>
+</MM:resource>
+<MM:resource>
+<D:set>
+<C:address-data><![CDATA[BEGIN:VCARD
+VERSION:3.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+UID:78b64b6b-80b9-4b8a-bd81-8f36645d8bb0
+FN:Added Group
+N:added group;;;;
+X-ADDRESSBOOKSERVER-KIND:group
+X-ADDRESSBOOKSERVER-MEMBER:urn:uuid:ED7A5AEC-AB19-4CE0-AD6A-2923A3E5C4E1
+X-ADDRESSBOOKSERVER-MEMBER:urn:uuid:FCBA0FA3-00B2-4C95-B4EC-4CCC4843F8B1
+X-ADDRESSBOOKSERVER-MEMBER:urn:uuid:78b64b6b-80b9-4b8a-bd81-8f36645d8bb0
+X-ADDRESSBOOKSERVER-MEMBER:urn:uuid:78b64b6b-80b9-4b8a-bd81-8f36645d8bb1
+END:VCARD
+]]>
+</C:address-data>
+</D:set>
+</MM:resource>
+<MM:resource>
+<D:set>
+<C:address-data><![CDATA[BEGIN:VCARD
+VERSION:3.0
+N:Thompson;Default;;;
+FN:Default Thompson
+EMAIL;type=INTERNET;type=WORK;type=pref:lthompson at example.com
+TEL;type=WORK;type=pref:1-555-555-5555
+TEL;type=CELL:1-444-444-4444
+item1.ADR;type=WORK;type=pref:;;1245 Test;Sesame Street;California;11111;USA
+item1.X-ABADR:us
+UID:ED7A5AEC-AB19-4CE0-AD6A-2923A3E5C4E1
+END:VCARD
+]]>
+</C:address-data>
+</D:set>
+</MM:resource>
+<MM:resource>
+<D:set>
+<C:address-data><![CDATA[BEGIN:VCARD
+VERSION:3.0
+N:Contact;Mulberry;;;
+FN:Mulberry Contact
+NICKNAME:mulberry
+ORG:Apple Inc.;
+EMAIL;type=INTERNET;type=WORK;type=pref:mulberry at example.com
+TEL;type=HOME;type=pref:777-777-7777
+TEL;type=WORK:8888888888
+TEL;type=WORK;type=FAX:5555555555
+item1.ADR;type=WORK;type=pref:;;1234 Infinite Circle;Exampletino\, CA 99999;USA;;
+item1.X-ABADR:us
+NOTE:This is a contact created in Mulberry.
+item2.URL;type=pref:http://www.example.com/~magic
+item2.X-ABLabel:_$!<HomePage>!$_
+UID:ED7A5AEC-AB19-4CE0-AD6A-2923A3E5C4E2
+END:VCARD
+]]>
+</C:address-data>
+</D:set>
+</MM:resource>
+</MM:multiput>

Added: CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/13.xml
===================================================================
--- CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/13.xml	                        (rev 0)
+++ CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/13.xml	2013-08-10 02:35:04 UTC (rev 11592)
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<MM:multiput xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:carddav" xmlns:MM="http://me.com/_namespace/">
+<MM:resource>
+<D:href>$addressbookhome1:/$userguid2:/1.vcf</D:href>
+<MM:delete/>
+</MM:resource>
+<MM:resource>
+<D:href>$href1:</D:href>
+<MM:delete/>
+</MM:resource>
+</MM:multiput>

Added: CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/2.vcf
===================================================================
--- CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/2.vcf	                        (rev 0)
+++ CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/2.vcf	2013-08-10 02:35:04 UTC (rev 11592)
@@ -0,0 +1,12 @@
+BEGIN:VCARD
+VERSION:3.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+UID:78b64b6b-80b9-4b8a-bd81-8f36645d8bb1
+FN:Top Group
+N:top group;;;;
+X-ADDRESSBOOKSERVER-KIND:group
+X-ADDRESSBOOKSERVER-MEMBER:group2 at example.com
+X-ADDRESSBOOKSERVER-MEMBER:urn:uuid:78b64b6b-80b9-4b8a-bd81-8f36645d8bb0
+X-ADDRESSBOOKSERVER-MEMBER:urn:uuid:ED7A5AEC-AB19-4CE0-AD6A-2923A3E5C4E2
+X-ADDRESSBOOKSERVER-MEMBER:user1 at example.com
+END:VCARD

Added: CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/3.vcf
===================================================================
--- CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/3.vcf	                        (rev 0)
+++ CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/3.vcf	2013-08-10 02:35:04 UTC (rev 11592)
@@ -0,0 +1,12 @@
+BEGIN:VCARD
+VERSION:3.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+UID:78b64b6b-80b9-4b8a-bd81-8f36645d8bb0
+FN:Added Group
+N:added group;;;;
+X-ADDRESSBOOKSERVER-KIND:group
+X-ADDRESSBOOKSERVER-MEMBER:urn:uuid:78b64b6b-80b9-4b8a-bd81-8f36645d8bb0
+X-ADDRESSBOOKSERVER-MEMBER:urn:uuid:78b64b6b-80b9-4b8a-bd81-8f36645d8bb1
+X-ADDRESSBOOKSERVER-MEMBER:urn:uuid:ED7A5AEC-AB19-4CE0-AD6A-2923A3E5C4E1
+X-ADDRESSBOOKSERVER-MEMBER:urn:uuid:FCBA0FA3-00B2-4C95-B4EC-4CCC4843F8B1
+END:VCARD

Added: CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/4.vcf
===================================================================
--- CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/4.vcf	                        (rev 0)
+++ CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/4.vcf	2013-08-10 02:35:04 UTC (rev 11592)
@@ -0,0 +1,11 @@
+BEGIN:VCARD
+VERSION:3.0
+N:Thompson;Default;;;
+FN:Default Thompson
+EMAIL;type=INTERNET;type=WORK;type=pref:lthompson at example.com
+TEL;type=WORK;type=pref:1-555-555-5555
+TEL;type=CELL:1-444-444-4444
+item1.ADR;type=WORK;type=pref:;;1245 Test;Sesame Street;California;11111;USA
+item1.X-ABADR:us
+UID:ED7A5AEC-AB19-4CE0-AD6A-2923A3E5C4E1
+END:VCARD

Added: CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/5.vcf
===================================================================
--- CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/5.vcf	                        (rev 0)
+++ CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/5.vcf	2013-08-10 02:35:04 UTC (rev 11592)
@@ -0,0 +1,17 @@
+BEGIN:VCARD
+VERSION:3.0
+N:Contact;Mulberry;;;
+FN:Mulberry Contact
+NICKNAME:mulberry
+ORG:Apple Inc.;
+EMAIL;type=INTERNET;type=WORK;type=pref:mulberry at example.com
+TEL;type=HOME;type=pref:777-777-7777
+TEL;type=WORK:8888888888
+TEL;type=WORK;type=FAX:5555555555
+item1.ADR;type=WORK;type=pref:;;1234 Infinite Circle;Exampletino\, CA 99999;USA;;
+item1.X-ABADR:us
+NOTE:This is a contact created in Mulberry.
+item2.URL;type=pref:http://www.example.com/~magic
+item2.X-ABLabel:_$!<HomePage>!$_
+UID:ED7A5AEC-AB19-4CE0-AD6A-2923A3E5C4E2
+END:VCARD

Added: CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/6.vcf
===================================================================
--- CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/6.vcf	                        (rev 0)
+++ CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/6.vcf	2013-08-10 02:35:04 UTC (rev 11592)
@@ -0,0 +1,12 @@
+BEGIN:VCARD
+VERSION:3.0
+N:Kawado;Saeko;;;
+FN:Snow Leopard
+ORG:Snow Leopard;
+EMAIL;type=INTERNET;type=WORK;type=pref:snowleopard at example.com
+TEL;type=WORK;type=pref:777-777-7777
+item1.ADR;type=WORK;type=pref:;;1 Fidel Ave. Suite 100;Mountain Top;CA;99999;USA
+item1.X-ABADR:us
+X-ABShowAs:COMPANY
+UID:FCBA0FA3-00B2-4C95-B4EC-4CCC4843F8B1
+END:VCARD

Added: CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/7.vcf
===================================================================
--- CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/7.vcf	                        (rev 0)
+++ CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/7.vcf	2013-08-10 02:35:04 UTC (rev 11592)
@@ -0,0 +1,64 @@
+BEGIN:VCARD
+VERSION:3.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+UID:78b64b6b-80b9-4b8a-bd81-8f36645d8bb1
+FN:Top Group
+N:top group;;;;
+X-ADDRESSBOOKSERVER-KIND:group
+X-ADDRESSBOOKSERVER-MEMBER:urn:uuid:ED7A5AEC-AB19-4CE0-AD6A-2923A3E5C4E2
+X-ADDRESSBOOKSERVER-MEMBER:urn:uuid:78b64b6b-80b9-4b8a-bd81-8f36645d8bb0
+X-ADDRESSBOOKSERVER-MEMBER:user1 at example.com
+X-ADDRESSBOOKSERVER-MEMBER:group2 at example.com
+END:VCARD
+BEGIN:VCARD
+VERSION:3.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+UID:78b64b6b-80b9-4b8a-bd81-8f36645d8bb0
+FN:Added Group
+N:added group;;;;
+X-ADDRESSBOOKSERVER-KIND:group
+X-ADDRESSBOOKSERVER-MEMBER:urn:uuid:ED7A5AEC-AB19-4CE0-AD6A-2923A3E5C4E1
+X-ADDRESSBOOKSERVER-MEMBER:urn:uuid:FCBA0FA3-00B2-4C95-B4EC-4CCC4843F8B1
+X-ADDRESSBOOKSERVER-MEMBER:urn:uuid:78b64b6b-80b9-4b8a-bd81-8f36645d8bb0
+X-ADDRESSBOOKSERVER-MEMBER:urn:uuid:78b64b6b-80b9-4b8a-bd81-8f36645d8bb1
+END:VCARD
+BEGIN:VCARD
+VERSION:3.0
+N:Thompson;Default;;;
+FN:Default Thompson
+EMAIL;type=INTERNET;type=WORK;type=pref:lthompson at example.com
+TEL;type=WORK;type=pref:1-555-555-5555
+TEL;type=CELL:1-444-444-4444
+item1.ADR;type=WORK;type=pref:;;1245 Test;Sesame Street;California;11111;USA
+item1.X-ABADR:us
+UID:ED7A5AEC-AB19-4CE0-AD6A-2923A3E5C4E1
+END:VCARD
+BEGIN:VCARD
+VERSION:3.0
+N:Contact;Mulberry;;;
+FN:Mulberry Contact
+NICKNAME:mulberry
+ORG:Apple Inc.;
+EMAIL;type=INTERNET;type=WORK;type=pref:mulberry at example.com
+TEL;type=HOME;type=pref:777-777-7777
+TEL;type=WORK:8888888888
+TEL;type=WORK;type=FAX:5555555555
+item1.ADR;type=WORK;type=pref:;;1234 Infinite Circle;Exampletino\, CA 99999;USA;;
+item1.X-ABADR:us
+NOTE:This is a contact created in Mulberry.
+item2.URL;type=pref:http://www.example.com/~magic
+item2.X-ABLabel:_$!<HomePage>!$_
+UID:ED7A5AEC-AB19-4CE0-AD6A-2923A3E5C4E2
+END:VCARD
+BEGIN:VCARD
+VERSION:3.0
+N:Kawado;Saeko;;;
+FN:Snow Leopard
+ORG:Snow Leopard;
+EMAIL;type=INTERNET;type=WORK;type=pref:snowleopard at example.com
+TEL;type=WORK;type=pref:777-777-7777
+item1.ADR;type=WORK;type=pref:;;1 Fidel Ave. Suite 100;Mountain Top;CA;99999;USA
+item1.X-ABADR:us
+X-ABShowAs:COMPANY
+UID:FCBA0FA3-00B2-4C95-B4EC-4CCC4843F8B1
+END:VCARD

Added: CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/8.vcf
===================================================================
--- CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/8.vcf	                        (rev 0)
+++ CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/8.vcf	2013-08-10 02:35:04 UTC (rev 11592)
@@ -0,0 +1,62 @@
+BEGIN:VCARD
+VERSION:3.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+UID:78b64b6b-80b9-4b8a-bd81-8f36645d8bb1
+FN:Top Group
+N:top group;;;;
+X-ADDRESSBOOKSERVER-KIND:group
+X-ADDRESSBOOKSERVER-MEMBER:urn:uuid:ED7A5AEC-AB19-4CE0-AD6A-2923A3E5C4E2
+X-ADDRESSBOOKSERVER-MEMBER:urn:uuid:78b64b6b-80b9-4b8a-bd81-000000000000
+END:VCARD
+BEGIN:VCARD
+VERSION:3.0
+PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN
+UID:78b64b6b-80b9-4b8a-bd81-8f36645d8bb0
+FN:Added Group
+N:added group;;;;
+X-ADDRESSBOOKSERVER-KIND:group
+X-ADDRESSBOOKSERVER-MEMBER:urn:uuid:ED7A5AEC-AB19-4CE0-AD6A-2923A3E5C4E1
+X-ADDRESSBOOKSERVER-MEMBER:urn:uuid:FCBA0FA3-00B2-4C95-B4EC-4CCC4843F8B1
+X-ADDRESSBOOKSERVER-MEMBER:urn:uuid:78b64b6b-80b9-4b8a-bd81-8f36645d8bb0
+X-ADDRESSBOOKSERVER-MEMBER:urn:uuid:78b64b6b-80b9-4b8a-bd81-8f36645d8bb1
+END:VCARD
+BEGIN:VCARD
+VERSION:3.0
+N:Thompson;Default;;;
+FN:Default Thompson
+EMAIL;type=INTERNET;type=WORK;type=pref:lthompson at example.com
+TEL;type=WORK;type=pref:1-555-555-5555
+TEL;type=CELL:1-444-444-4444
+item1.ADR;type=WORK;type=pref:;;1245 Test;Sesame Street;California;11111;USA
+item1.X-ABADR:us
+UID:ED7A5AEC-AB19-4CE0-AD6A-2923A3E5C4E1
+END:VCARD
+BEGIN:VCARD
+VERSION:3.0
+N:Contact;Mulberry;;;
+FN:Mulberry Contact
+NICKNAME:mulberry
+ORG:Apple Inc.;
+EMAIL;type=INTERNET;type=WORK;type=pref:mulberry at example.com
+TEL;type=HOME;type=pref:777-777-7777
+TEL;type=WORK:8888888888
+TEL;type=WORK;type=FAX:5555555555
+item1.ADR;type=WORK;type=pref:;;1234 Infinite Circle;Exampletino\, CA 99999;USA;;
+item1.X-ABADR:us
+NOTE:This is a contact created in Mulberry.
+item2.URL;type=pref:http://www.example.com/~magic
+item2.X-ABLabel:_$!<HomePage>!$_
+UID:ED7A5AEC-AB19-4CE0-AD6A-2923A3E5C4E2
+END:VCARD
+BEGIN:VCARD
+VERSION:3.0
+N:Kawado;Saeko;;;
+FN:Snow Leopard
+ORG:Snow Leopard;
+EMAIL;type=INTERNET;type=WORK;type=pref:snowleopard at example.com
+TEL;type=WORK;type=pref:777-777-7777
+item1.ADR;type=WORK;type=pref:;;1 Fidel Ave. Suite 100;Mountain Top;CA;99999;USA
+item1.X-ABADR:us
+X-ABShowAs:COMPANY
+UID:FCBA0FA3-00B2-4C95-B4EC-4CCC4843F8B1
+END:VCARD

Added: CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/9.xml
===================================================================
--- CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/9.xml	                        (rev 0)
+++ CalDAVTester/trunk/Resource/CardDAV/sharing/bulk/9.xml	2013-08-10 02:35:04 UTC (rev 11592)
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<CS:share xmlns:D="DAV:" xmlns:CS="http://calendarserver.org/ns/">
+    <CS:set>
+        <D:href>$cuaddrurn1:</D:href>
+        <CS:summary>Shared Group</CS:summary>
+        <CS:read-write/>
+    </CS:set>
+</CS:share>

Modified: CalDAVTester/trunk/scripts/tests/CardDAV/sharing-access.xml
===================================================================
--- CalDAVTester/trunk/scripts/tests/CardDAV/sharing-access.xml	2013-08-07 22:36:54 UTC (rev 11591)
+++ CalDAVTester/trunk/scripts/tests/CardDAV/sharing-access.xml	2013-08-10 02:35:04 UTC (rev 11592)
@@ -36,7 +36,7 @@
 			<ruri>$notificationpath2:/</ruri>
 		</request>
 
-		<description>add 7 persons and 3 groups to user2 address book</description>
+		<description>add 5 persons and 2 groups to user2 address book</description>
 		<request user="$userid2:" pswd="$pswd2:">
 			<method>PUT</method>
 			<ruri>$addressbookpath2:/1.vcf</ruri>

Added: CalDAVTester/trunk/scripts/tests/CardDAV/sharing-bulk.xml
===================================================================
--- CalDAVTester/trunk/scripts/tests/CardDAV/sharing-bulk.xml	                        (rev 0)
+++ CalDAVTester/trunk/scripts/tests/CardDAV/sharing-bulk.xml	2013-08-10 02:35:04 UTC (rev 11592)
@@ -0,0 +1,933 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE caldavtest SYSTEM "caldavtest.dtd">
+
+<!--
+ Copyright (c) 2006-2013 Apple Inc. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<caldavtest>
+	<description>Test bulk POST method in CardDAV</description>
+
+	<require-feature>
+		<feature>carddav</feature>
+		<feature>bulk-post</feature>
+		<feature>shared-addressbooks</feature>
+	</require-feature>
+
+	<start>
+	</start>
+	
+	<test-suite name='POST with circular groups' ignore='no'>
+		<test name='0' ignore='no'>
+			<description>clean up old data</description>
+			<request user="$useradmin:" pswd="$pswdadmin:">
+				<method>DELETEALL</method>
+				<ruri>$addressbookhome1:/</ruri>
+				<ruri>$addressbookhome2:/</ruri>
+				<ruri>$notificationpath1:/</ruri>
+				<ruri>$notificationpath2:/</ruri>
+			</request>
+			<request user="$userid2:" pswd="$pswd2:">
+				<method>PUT</method>
+				<ruri>$addressbookpath2:/1.vcf</ruri>
+				<data>
+					<content-type>text/vcard; charset=utf-8</content-type>
+					<filepath>Resource/CardDAV/sharing/bulk/1.vcf</filepath>
+				</data>
+			</request>
+			<description>user2 POSTs invitation</description>
+			<request user="$userid2:" pswd="$pswd2:" print-response="no">
+				<method>POST</method>
+				<ruri>$addressbookpath2:/1.vcf</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CardDAV/sharing/bulk/9.xml</filepath>
+				</data>
+			</request>
+			<description>Check user1 notification collection and get invite uid</description>
+			<request print-response="no">
+				<method>WAITCOUNT 1</method>
+				<ruri>$notificationpath1:/</ruri>
+			</request>
+			<request print-response="no">
+				<method>GETNEW</method>
+				<ruri>$notificationpath1:/</ruri>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid:</variable>
+				</grabelement>
+			</request>
+			<description>user1 replies ACCEPTED and deletes notification</description>
+			<request print-response="no">
+				<method>POST</method>
+				<ruri>$addressbookhome1:/</ruri>
+				<data substitutions="yes">
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/CardDAV/sharing/bulk/10.xml</filepath>
+				</data>
+			</request>
+			<request>
+				<method>DELETE</method>
+				<ruri>$notificationpath1:/$inviteuid:</ruri>
+			</request>
+		</test>
+		<test name='1' ignore='no'>
+			<description>POST multiple new vcards</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$addressbookhome1:/$userguid2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/vcard; charset=utf-8</content-type>
+					<filepath>Resource/CardDAV/sharing/bulk/7.vcf</filepath>
+				</data>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}getetag</value>
+					</arg>
+					<arg>
+						<name>notexists</name>
+						<value>$verify-property-prefix:/{urn:ietf:params:xml:ns:carddav}address-data</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>$multistatus-href-prefix:</name>
+					<variable>$href1:</variable>
+					<variable>$href2:</variable>
+					<variable>$href3:</variable>
+					<variable>$href4:</variable>
+					<variable>$href5:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>Check valid data</description>
+			<request>
+				<method>GET</method>
+				<ruri>$href1:</ruri>
+				<verify>
+					<callback>addressDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CardDAV/sharing/bulk/2.vcf</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>header</callback>
+					<arg>
+						<name>ETag</name>
+						<value>$etag1:</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>Check valid data</description>
+			<request>
+				<method>GET</method>
+				<ruri>$href2:</ruri>
+				<verify>
+					<callback>addressDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CardDAV/sharing/bulk/3.vcf</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>header</callback>
+					<arg>
+						<name>ETag</name>
+						<value>$etag2:</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>Check valid data</description>
+			<request>
+				<method>GET</method>
+				<ruri>$href3:</ruri>
+				<verify>
+					<callback>addressDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CardDAV/sharing/bulk/4.vcf</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>header</callback>
+					<arg>
+						<name>ETag</name>
+						<value>$etag3:</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='5' ignore='no'>
+			<description>Check valid data</description>
+			<request>
+				<method>GET</method>
+				<ruri>$href4:</ruri>
+				<verify>
+					<callback>addressDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CardDAV/sharing/bulk/5.vcf</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>header</callback>
+					<arg>
+						<name>ETag</name>
+						<value>$etag4:</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='6' ignore='no'>
+			<description>Check valid data</description>
+			<request>
+				<method>GET</method>
+				<ruri>$href5:</ruri>
+				<verify>
+					<callback>addressDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CardDAV/sharing/bulk/6.vcf</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>header</callback>
+					<arg>
+						<name>ETag</name>
+						<value>$etag5:</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='-1' ignore='no'>
+			<description>Clean up</description>
+			<request user="$userid2:" pswd="$pswd2:" print-response='no'>
+				<method>DELETEALL</method>
+				<ruri>$href1:</ruri>
+				<ruri>$href2:</ruri>
+				<ruri>$href3:</ruri>
+				<ruri>$href4:</ruri>
+				<ruri>$href5:</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+	
+	<test-suite name='POST with circular groups and one bad reference' ignore='no'>
+		<test name='0' ignore='no'>
+			<description>clean up old data</description>
+			<request user="$useradmin:" pswd="$pswdadmin:">
+				<method>DELETEALL</method>
+				<ruri>$addressbookhome1:/</ruri>
+				<ruri>$addressbookhome2:/</ruri>
+				<ruri>$notificationpath1:/</ruri>
+				<ruri>$notificationpath2:/</ruri>
+			</request>
+			<request user="$userid2:" pswd="$pswd2:">
+				<method>PUT</method>
+				<ruri>$addressbookpath2:/1.vcf</ruri>
+				<data>
+					<content-type>text/vcard; charset=utf-8</content-type>
+					<filepath>Resource/CardDAV/sharing/bulk/1.vcf</filepath>
+				</data>
+			</request>
+			<description>user2 POSTs invitation</description>
+			<request user="$userid2:" pswd="$pswd2:" print-response="no">
+				<method>POST</method>
+				<ruri>$addressbookpath2:/1.vcf</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CardDAV/sharing/bulk/9.xml</filepath>
+				</data>
+			</request>
+			<description>Check user1 notification collection and get invite uid</description>
+			<request print-response="no">
+				<method>WAITCOUNT 1</method>
+				<ruri>$notificationpath1:/</ruri>
+			</request>
+			<request print-response="no">
+				<method>GETNEW</method>
+				<ruri>$notificationpath1:/</ruri>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid:</variable>
+				</grabelement>
+			</request>
+			<description>user1 replies ACCEPTED and deletes notification</description>
+			<request print-response="no">
+				<method>POST</method>
+				<ruri>$addressbookhome1:/</ruri>
+				<data substitutions="yes">
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/CardDAV/sharing/bulk/10.xml</filepath>
+				</data>
+			</request>
+			<request>
+				<method>DELETE</method>
+				<ruri>$notificationpath1:/$inviteuid:</ruri>
+			</request>
+		</test>
+		<test name='1' ignore='no'>
+			<description>POST multiple new vcards</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$addressbookhome1:/$userguid2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/vcard; charset=utf-8</content-type>
+					<filepath>Resource/CardDAV/sharing/bulk/8.vcf</filepath>
+				</data>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}getetag</value>
+					</arg>
+					<arg>
+						<name>notexists</name>
+						<value>$verify-property-prefix:/{urn:ietf:params:xml:ns:carddav}address-data</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>$multistatus-href-prefix:</name>
+					<variable>$href1:</variable>
+					<variable>$href2:</variable>
+					<variable>$href3:</variable>
+					<variable>$href4:</variable>
+					<variable>$href5:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='2' ignore='yes'>
+			<description>Check valid data</description>
+			<request>
+				<method>GET</method>
+				<ruri>$href1:</ruri>
+				<verify>
+					<callback>addressDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CardDAV/sharing/bulk/2.vcf</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>header</callback>
+					<arg>
+						<name>ETag</name>
+						<value>$etag1:</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3' ignore='yes'>
+			<description>Check valid data</description>
+			<request>
+				<method>GET</method>
+				<ruri>$href2:</ruri>
+				<verify>
+					<callback>addressDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CardDAV/sharing/bulk/3.vcf</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>header</callback>
+					<arg>
+						<name>ETag</name>
+						<value>$etag2:</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>Check valid data</description>
+			<request>
+				<method>GET</method>
+				<ruri>$href3:</ruri>
+				<verify>
+					<callback>addressDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CardDAV/sharing/bulk/4.vcf</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>header</callback>
+					<arg>
+						<name>ETag</name>
+						<value>$etag3:</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='5' ignore='no'>
+			<description>Check valid data</description>
+			<request>
+				<method>GET</method>
+				<ruri>$href4:</ruri>
+				<verify>
+					<callback>addressDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CardDAV/sharing/bulk/5.vcf</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>header</callback>
+					<arg>
+						<name>ETag</name>
+						<value>$etag4:</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='6' ignore='no'>
+			<description>Check valid data</description>
+			<request>
+				<method>GET</method>
+				<ruri>$href5:</ruri>
+				<verify>
+					<callback>addressDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CardDAV/sharing/bulk/6.vcf</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>header</callback>
+					<arg>
+						<name>ETag</name>
+						<value>$etag5:</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+	
+	<test-suite name='CRUD POST with circular groups' ignore='no'>
+		<test name='0' ignore='no'>
+			<description>clean up old data</description>
+			<request user="$useradmin:" pswd="$pswdadmin:">
+				<method>DELETEALL</method>
+				<ruri>$addressbookhome1:/</ruri>
+				<ruri>$addressbookhome2:/</ruri>
+				<ruri>$notificationpath1:/</ruri>
+				<ruri>$notificationpath2:/</ruri>
+			</request>
+			<request user="$userid2:" pswd="$pswd2:">
+				<method>PUT</method>
+				<ruri>$addressbookpath2:/1.vcf</ruri>
+				<data>
+					<content-type>text/vcard; charset=utf-8</content-type>
+					<filepath>Resource/CardDAV/sharing/bulk/1.vcf</filepath>
+				</data>
+			</request>
+			<description>user2 POSTs invitation</description>
+			<request user="$userid2:" pswd="$pswd2:" print-response="no">
+				<method>POST</method>
+				<ruri>$addressbookpath2:/1.vcf</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CardDAV/sharing/bulk/9.xml</filepath>
+				</data>
+			</request>
+			<description>Check user1 notification collection and get invite uid</description>
+			<request print-response="no">
+				<method>WAITCOUNT 1</method>
+				<ruri>$notificationpath1:/</ruri>
+			</request>
+			<request print-response="no">
+				<method>GETNEW</method>
+				<ruri>$notificationpath1:/</ruri>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid:</variable>
+				</grabelement>
+			</request>
+			<description>user1 replies ACCEPTED and deletes notification</description>
+			<request print-response="no">
+				<method>POST</method>
+				<ruri>$addressbookhome1:/</ruri>
+				<data substitutions="yes">
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/CardDAV/sharing/bulk/10.xml</filepath>
+				</data>
+			</request>
+			<request>
+				<method>DELETE</method>
+				<ruri>$notificationpath1:/$inviteuid:</ruri>
+			</request>
+		</test>
+		<test name='1' ignore='no'>
+			<description>POST multiple new vcards</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$addressbookhome1:/$userguid2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CardDAV/sharing/bulk/11.xml</filepath>
+				</data>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}getetag</value>
+					</arg>
+					<arg>
+						<name>notexists</name>
+						<value>$verify-property-prefix:/{urn:ietf:params:xml:ns:carddav}address-data</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>$multistatus-href-prefix:</name>
+					<variable>$href1:</variable>
+					<variable>$href2:</variable>
+					<variable>$href3:</variable>
+					<variable>$href4:</variable>
+					<variable>$href5:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>Check valid data</description>
+			<request>
+				<method>GET</method>
+				<ruri>$href1:</ruri>
+				<verify>
+					<callback>addressDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CardDAV/sharing/bulk/2.vcf</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>header</callback>
+					<arg>
+						<name>ETag</name>
+						<value>$etag1:</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>Check valid data</description>
+			<request>
+				<method>GET</method>
+				<ruri>$href2:</ruri>
+				<verify>
+					<callback>addressDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CardDAV/sharing/bulk/3.vcf</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>header</callback>
+					<arg>
+						<name>ETag</name>
+						<value>$etag2:</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>Check valid data</description>
+			<request>
+				<method>GET</method>
+				<ruri>$href3:</ruri>
+				<verify>
+					<callback>addressDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CardDAV/sharing/bulk/4.vcf</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>header</callback>
+					<arg>
+						<name>ETag</name>
+						<value>$etag3:</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='5' ignore='no'>
+			<description>Check valid data</description>
+			<request>
+				<method>GET</method>
+				<ruri>$href4:</ruri>
+				<verify>
+					<callback>addressDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CardDAV/sharing/bulk/5.vcf</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>header</callback>
+					<arg>
+						<name>ETag</name>
+						<value>$etag4:</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='6' ignore='no'>
+			<description>Check valid data</description>
+			<request>
+				<method>GET</method>
+				<ruri>$href5:</ruri>
+				<verify>
+					<callback>addressDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CardDAV/sharing/bulk/6.vcf</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>header</callback>
+					<arg>
+						<name>ETag</name>
+						<value>$etag5:</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+	
+	<test-suite name='crud POST with circular groups and one bad reference' ignore='no'>
+		<test name='0' ignore='no'>
+			<description>clean up old data</description>
+			<request user="$useradmin:" pswd="$pswdadmin:">
+				<method>DELETEALL</method>
+				<ruri>$addressbookhome1:/</ruri>
+				<ruri>$addressbookhome2:/</ruri>
+				<ruri>$notificationpath1:/</ruri>
+				<ruri>$notificationpath2:/</ruri>
+			</request>
+			<request user="$userid2:" pswd="$pswd2:">
+				<method>PUT</method>
+				<ruri>$addressbookpath2:/1.vcf</ruri>
+				<data>
+					<content-type>text/vcard; charset=utf-8</content-type>
+					<filepath>Resource/CardDAV/sharing/bulk/1.vcf</filepath>
+				</data>
+			</request>
+			<description>user2 POSTs invitation</description>
+			<request user="$userid2:" pswd="$pswd2:" print-response="no">
+				<method>POST</method>
+				<ruri>$addressbookpath2:/1.vcf</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CardDAV/sharing/bulk/9.xml</filepath>
+				</data>
+			</request>
+			<description>Check user1 notification collection and get invite uid</description>
+			<request print-response="no">
+				<method>WAITCOUNT 1</method>
+				<ruri>$notificationpath1:/</ruri>
+			</request>
+			<request print-response="no">
+				<method>GETNEW</method>
+				<ruri>$notificationpath1:/</ruri>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid:</variable>
+				</grabelement>
+			</request>
+			<description>user1 replies ACCEPTED and deletes notification</description>
+			<request print-response="no">
+				<method>POST</method>
+				<ruri>$addressbookhome1:/</ruri>
+				<data substitutions="yes">
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/CardDAV/sharing/bulk/10.xml</filepath>
+				</data>
+			</request>
+			<request>
+				<method>DELETE</method>
+				<ruri>$notificationpath1:/$inviteuid:</ruri>
+			</request>
+		</test>
+		<test name='1' ignore='no'>
+			<description>POST multiple new vcards</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$addressbookhome1:/$userguid2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CardDAV/sharing/bulk/12.xml</filepath>
+				</data>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}getetag</value>
+					</arg>
+					<arg>
+						<name>notexists</name>
+						<value>$verify-property-prefix:/{urn:ietf:params:xml:ns:carddav}address-data</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>$multistatus-href-prefix:</name>
+					<variable>$href1:</variable>
+					<variable>$href2:</variable>
+					<variable>$href3:</variable>
+					<variable>$href4:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='2' ignore='yes'>
+			<description>Check valid data</description>
+			<request>
+				<method>GET</method>
+				<ruri>$href1:</ruri>
+				<verify>
+					<callback>addressDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CardDAV/sharing/bulk/2.vcf</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>header</callback>
+					<arg>
+						<name>ETag</name>
+						<value>$etag1:</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='3' ignore='yes'>
+			<description>Check valid data</description>
+			<request>
+				<method>GET</method>
+				<ruri>$href2:</ruri>
+				<verify>
+					<callback>addressDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CardDAV/sharing/bulk/3.vcf</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>header</callback>
+					<arg>
+						<name>ETag</name>
+						<value>$etag2:</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>Check valid data</description>
+			<request>
+				<method>GET</method>
+				<ruri>$href3:</ruri>
+				<verify>
+					<callback>addressDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CardDAV/sharing/bulk/4.vcf</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>header</callback>
+					<arg>
+						<name>ETag</name>
+						<value>$etag3:</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+		<test name='5' ignore='no'>
+			<description>Check valid data</description>
+			<request>
+				<method>GET</method>
+				<ruri>$href4:</ruri>
+				<verify>
+					<callback>addressDataMatch</callback>
+					<arg>
+						<name>filepath</name>
+						<value>Resource/CardDAV/sharing/bulk/5.vcf</value>
+					</arg>
+				</verify>
+				<verify>
+					<callback>header</callback>
+					<arg>
+						<name>ETag</name>
+						<value>$etag4:</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<test-suite name='crud POST delete cannot delete (unshare) read-write shared group' ignore='no'>
+		<test name='0' ignore='no'>
+			<description>clean up old data</description>
+			<request user="$useradmin:" pswd="$pswdadmin:">
+				<method>DELETEALL</method>
+				<ruri>$addressbookhome1:/</ruri>
+				<ruri>$addressbookhome2:/</ruri>
+				<ruri>$notificationpath1:/</ruri>
+				<ruri>$notificationpath2:/</ruri>
+			</request>
+			<request user="$userid2:" pswd="$pswd2:">
+				<method>PUT</method>
+				<ruri>$addressbookpath2:/1.vcf</ruri>
+				<data>
+					<content-type>text/vcard; charset=utf-8</content-type>
+					<filepath>Resource/CardDAV/sharing/bulk/1.vcf</filepath>
+				</data>
+			</request>
+			<description>user2 POSTs invitation</description>
+			<request user="$userid2:" pswd="$pswd2:" print-response="no">
+				<method>POST</method>
+				<ruri>$addressbookpath2:/1.vcf</ruri>
+				<data>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CardDAV/sharing/bulk/9.xml</filepath>
+				</data>
+			</request>
+			<description>Check user1 notification collection and get invite uid</description>
+			<request print-response="no">
+				<method>WAITCOUNT 1</method>
+				<ruri>$notificationpath1:/</ruri>
+			</request>
+			<request print-response="no">
+				<method>GETNEW</method>
+				<ruri>$notificationpath1:/</ruri>
+				<grabelement>
+					<name>{http://calendarserver.org/ns/}invite-notification/{http://calendarserver.org/ns/}uid</name>
+					<variable>$inviteuid:</variable>
+				</grabelement>
+			</request>
+			<description>user1 replies ACCEPTED and deletes notification</description>
+			<request print-response="no">
+				<method>POST</method>
+				<ruri>$addressbookhome1:/</ruri>
+				<data substitutions="yes">
+					<content-type>application/xml; charset=utf-8</content-type>
+					<filepath>Resource/CardDAV/sharing/bulk/10.xml</filepath>
+				</data>
+			</request>
+			<request>
+				<method>DELETE</method>
+				<ruri>$notificationpath1:/$inviteuid:</ruri>
+			</request>
+		</test>
+		<test name='1' ignore='no'>
+			<description>POST multiple new vcards</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$addressbookhome1:/$userguid2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CardDAV/sharing/bulk/11.xml</filepath>
+				</data>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>exists</name>
+						<value>$verify-property-prefix:/{DAV:}getetag</value>
+					</arg>
+					<arg>
+						<name>notexists</name>
+						<value>$verify-property-prefix:/{urn:ietf:params:xml:ns:carddav}address-data</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>$multistatus-href-prefix:</name>
+					<variable>$href1:</variable>
+					<variable>$href2:</variable>
+					<variable>$href3:</variable>
+					<variable>$href4:</variable>
+					<variable>$href5:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='2' ignore='no'>
+			<description>Delete shared group and other group</description>
+			<request print-response='no'>
+				<method>POST</method>
+				<ruri>$addressbookhome1:/$userguid2:/</ruri>
+				<data substitutions='yes'>
+					<content-type>text/xml; charset=utf-8</content-type>
+					<filepath>Resource/CardDAV/sharing/bulk/13.xml</filepath>
+				</data>
+				<verify>
+					<callback>xmlElementMatch</callback>
+					<arg>
+						<name>notexists</name>
+						<value>$verify-property-prefix:/{urn:ietf:params:xml:ns:carddav}address-data</value>
+					</arg>
+				</verify>
+				<grabelement>
+					<name>$multistatus-href-prefix:</name>
+					<variable>$href1:</variable>
+					<variable>$href2:</variable>
+				</grabelement>
+			</request>
+		</test>
+		<test name='3' ignore='no'>
+			<description>group still here</description>
+			<request>
+				<method>GET</method>
+				<ruri>$addressbookhome1:/$userguid2:/1.vcf</ruri>
+				<verify>
+					<callback>statusCode</callback>
+				</verify>
+			</request>
+		</test>
+		<test name='4' ignore='no'>
+			<description>Data gone</description>
+			<request>
+				<method>GET</method>
+				<ruri>$href2:</ruri>
+				<verify>
+					<callback>statusCode</callback>
+					<arg>
+						<name>status</name>
+						<value>404</value>
+					</arg>
+				</verify>
+			</request>
+		</test>
+	</test-suite>
+
+	<end>
+		<description>clean up old data</description>
+		<request user="$useradmin:" pswd="$pswdadmin:">
+			<method>DELETEALL</method>
+			<ruri>$addressbookhome1:/</ruri>
+			<ruri>$addressbookhome2:/</ruri>
+			<ruri>$notificationpath1:/</ruri>
+			<ruri>$notificationpath2:/</ruri>
+		</request>
+	</end>
+	
+</caldavtest>

Modified: CalDAVTester/trunk/scripts/tests/CardDAV/sharing-unshare.xml
===================================================================
--- CalDAVTester/trunk/scripts/tests/CardDAV/sharing-unshare.xml	2013-08-07 22:36:54 UTC (rev 11591)
+++ CalDAVTester/trunk/scripts/tests/CardDAV/sharing-unshare.xml	2013-08-10 02:35:04 UTC (rev 11592)
@@ -160,7 +160,7 @@
 			</request>
 			<request>
 				<method>DELETE</method>
-				<ruri>$notificationpath1:/$inviteuid:-reply</ruri>
+				<ruri>$</ruri>
 				<verify>
 					<callback>statusCode</callback>
 				</verify>
@@ -225,7 +225,7 @@
 			</request>
 			<request>
 				<method>DELETE</method>
-				<ruri>$notificationpath1:/$inviteuid:-reply</ruri>
+				<ruri>$</ruri>
 				<verify>
 					<callback>statusCode</callback>
 				</verify>
@@ -357,7 +357,7 @@
 			</request>
 			<request>
 				<method>DELETE</method>
-				<ruri>$notificationpath1:/$inviteuid:-reply</ruri>
+				<ruri>$</ruri>
 				<verify>
 					<callback>statusCode</callback>
 				</verify>
@@ -422,7 +422,7 @@
 			</request>
 			<request>
 				<method>DELETE</method>
-				<ruri>$notificationpath1:/$inviteuid:-reply</ruri>
+				<ruri>$</ruri>
 				<verify>
 					<callback>statusCode</callback>
 				</verify>
@@ -554,7 +554,7 @@
 			</request>
 			<request>
 				<method>DELETE</method>
-				<ruri>$notificationpath1:/$inviteuid:-reply</ruri>
+				<ruri>$</ruri>
 				<verify>
 					<callback>statusCode</callback>
 				</verify>
@@ -615,7 +615,7 @@
 			</request>
 			<request>
 				<method>DELETE</method>
-				<ruri>$notificationpath1:/$inviteuid:-reply</ruri>
+				<ruri>$</ruri>
 				<verify>
 					<callback>statusCode</callback>
 				</verify>
@@ -747,7 +747,7 @@
 			</request>
 			<request>
 				<method>DELETE</method>
-				<ruri>$notificationpath1:/$inviteuid:-reply</ruri>
+				<ruri>$</ruri>
 				<verify>
 					<callback>statusCode</callback>
 				</verify>
@@ -949,7 +949,7 @@
 			</request>
 			<request>
 				<method>DELETE</method>
-				<ruri>$notificationpath1:/$inviteuid:-reply</ruri>
+				<ruri>$</ruri>
 				<verify>
 					<callback>statusCode</callback>
 				</verify>
@@ -1190,7 +1190,7 @@
 			</request>
 			<request>
 				<method>DELETE</method>
-				<ruri>$notificationpath1:/$inviteuid:-reply</ruri>
+				<ruri>$</ruri>
 				<verify>
 					<callback>statusCode</callback>
 				</verify>
@@ -1255,7 +1255,7 @@
 			</request>
 			<request>
 				<method>DELETE</method>
-				<ruri>$notificationpath1:/$inviteuid:-reply</ruri>
+				<ruri>$</ruri>
 				<verify>
 					<callback>statusCode</callback>
 				</verify>
@@ -1386,7 +1386,7 @@
 			</request>
 			<request>
 				<method>DELETE</method>
-				<ruri>$notificationpath1:/$inviteuid:-reply</ruri>
+				<ruri>$</ruri>
 				<verify>
 					<callback>statusCode</callback>
 				</verify>
@@ -1451,7 +1451,7 @@
 			</request>
 			<request>
 				<method>DELETE</method>
-				<ruri>$notificationpath1:/$inviteuid:-reply</ruri>
+				<ruri>$</ruri>
 				<verify>
 					<callback>statusCode</callback>
 				</verify>
@@ -1582,7 +1582,7 @@
 			</request>
 			<request>
 				<method>DELETE</method>
-				<ruri>$notificationpath1:/$inviteuid:-reply</ruri>
+				<ruri>$</ruri>
 				<verify>
 					<callback>statusCode</callback>
 				</verify>
@@ -1647,7 +1647,7 @@
 			</request>
 			<request>
 				<method>DELETE</method>
-				<ruri>$notificationpath1:/$inviteuid:-reply</ruri>
+				<ruri>$</ruri>
 				<verify>
 					<callback>statusCode</callback>
 				</verify>
@@ -1778,7 +1778,7 @@
 			</request>
 			<request>
 				<method>DELETE</method>
-				<ruri>$notificationpath1:/$inviteuid:-reply</ruri>
+				<ruri>$</ruri>
 				<verify>
 					<callback>statusCode</callback>
 				</verify>
@@ -1843,7 +1843,7 @@
 			</request>
 			<request>
 				<method>DELETE</method>
-				<ruri>$notificationpath1:/$inviteuid:-reply</ruri>
+				<ruri>$</ruri>
 				<verify>
 					<callback>statusCode</callback>
 				</verify>
@@ -1974,7 +1974,7 @@
 			</request>
 			<request>
 				<method>DELETE</method>
-				<ruri>$notificationpath1:/$inviteuid:-reply</ruri>
+				<ruri>$</ruri>
 				<verify>
 					<callback>statusCode</callback>
 				</verify>
@@ -2182,7 +2182,7 @@
 			</request>
 			<request>
 				<method>DELETE</method>
-				<ruri>$notificationpath1:/$inviteuid:-reply</ruri>
+				<ruri>$</ruri>
 				<verify>
 					<callback>statusCode</callback>
 				</verify>

Modified: CalendarServer/trunk/twistedcaldav/storebridge.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/storebridge.py	2013-08-07 22:36:54 UTC (rev 11591)
+++ CalendarServer/trunk/twistedcaldav/storebridge.py	2013-08-10 02:35:04 UTC (rev 11592)
@@ -631,20 +631,40 @@
             raise HTTPError(StatusResponse(BAD_REQUEST, "Could not parse valid data from request body"))
 
         # Build response
-        xmlresponses = []
-        for ctr, component in enumerate(components):
+        xmlresponses = [None] * len(components)
+        indexedComponents = [idxComponent for idxComponent in enumerate(components)]
+        yield self.bulkCreate(indexedComponents, request, return_changed, xmlresponses)
 
-            code = None
-            error = None
-            dataChanged = None
+        result = MultiStatusResponse(xmlresponses)
+
+        newctag = (yield self.getInternalSyncToken())
+        result.headers.setRawHeaders("CTag", (newctag,))
+
+        # Setup some useful logging
+        request.submethod = "Simple batch"
+        if not hasattr(request, "extendedLogItems"):
+            request.extendedLogItems = {}
+        request.extendedLogItems["rcount"] = len(xmlresponses)
+
+        returnValue(result)
+
+
+    @inlineCallbacks
+    def bulkCreate(self, indexedComponents, request, return_changed, xmlresponses):
+        """
+        Do create from simpleBatchPOST or crudCreate()
+        Subclasses may override
+        """
+        for index, component in indexedComponents:
+
             try:
                 # Create a new name if one was not provided
-                name = md5(str(ctr) + component.resourceUID() + str(time.time()) + request.path).hexdigest() + self.resourceSuffix()
+                name = md5(str(index) + component.resourceUID() + str(time.time()) + request.path).hexdigest() + self.resourceSuffix()
 
                 # Get a resource for the new item
                 newchildURL = joinURL(request.path, name)
                 newchild = (yield request.locateResource(newchildURL))
-                dataChanged = (yield self.storeResourceData(newchild, component, returnChangedData=return_changed))
+                changedData = (yield self.storeResourceData(newchild, component, returnChangedData=return_changed))
 
             except HTTPError, e:
                 # Extract the pre-condition
@@ -652,65 +672,70 @@
                 if isinstance(e.response, ErrorResponse):
                     error = e.response.error
                     error = (error.namespace, error.name,)
+
+                xmlresponses[index] = (
+                    yield self.bulkCreateResponse(component, newchildURL, newchild, None, code, error)
+                )
+
             except Exception:
-                code = BAD_REQUEST
+                xmlresponses[index] = (
+                    yield self.bulkCreateResponse(component, newchildURL, newchild, None, code=BAD_REQUEST, error=None)
+                )
 
-            if code is None:
+            else:
+                if not return_changed:
+                    changedData = None
+                xmlresponses[index] = (
+                    yield self.bulkCreateResponse(component, newchildURL, newchild, changedData, code=None, error=None)
+                )
 
-                etag = (yield newchild.etag())
-                if not return_changed or dataChanged is None:
-                    xmlresponses.append(
-                        davxml.PropertyStatusResponse(
-                            davxml.HRef.fromString(newchildURL),
-                            davxml.PropertyStatus(
-                                davxml.PropertyContainer(
-                                    davxml.GETETag.fromString(etag.generate()),
-                                    customxml.UID.fromString(component.resourceUID()),
-                                ),
-                                davxml.Status.fromResponseCode(OK),
-                            )
+
+    @inlineCallbacks
+    def bulkCreateResponse(self, component, newchildURL, newchild, changedData, code, error):
+        """
+        generate one xmlresponse for bulk create
+        """
+        if code is None:
+            etag = (yield newchild.etag())
+            if changedData is None:
+                returnValue(
+                    davxml.PropertyStatusResponse(
+                        davxml.HRef.fromString(newchildURL),
+                        davxml.PropertyStatus(
+                            davxml.PropertyContainer(
+                                davxml.GETETag.fromString(etag.generate()),
+                                customxml.UID.fromString(component.resourceUID()),
+                            ),
+                            davxml.Status.fromResponseCode(OK),
                         )
                     )
-                else:
-                    xmlresponses.append(
-                        davxml.PropertyStatusResponse(
-                            davxml.HRef.fromString(newchildURL),
-                            davxml.PropertyStatus(
-                                davxml.PropertyContainer(
-                                    davxml.GETETag.fromString(etag.generate()),
-                                    self.xmlDataElementType().fromTextData(dataChanged),
-                                ),
-                                davxml.Status.fromResponseCode(OK),
-                            )
+                )
+            else:
+                returnValue(
+                    davxml.PropertyStatusResponse(
+                        davxml.HRef.fromString(newchildURL),
+                        davxml.PropertyStatus(
+                            davxml.PropertyContainer(
+                                davxml.GETETag.fromString(etag.generate()),
+                                self.xmlDataElementType().fromTextData(changedData),
+                            ),
+                            davxml.Status.fromResponseCode(OK),
                         )
                     )
-
-            else:
-                xmlresponses.append(
-                    davxml.StatusResponse(
-                        davxml.HRef.fromString(""),
-                        davxml.Status.fromResponseCode(code),
+                )
+        else:
+            returnValue(
+                davxml.StatusResponse(
+                    davxml.HRef.fromString(""),
+                    davxml.Status.fromResponseCode(code),
                     davxml.Error(
                         WebDAVUnknownElement.withName(*error),
                         customxml.UID.fromString(component.resourceUID()),
                     ) if error else None,
-                    )
                 )
+            )
 
-        result = MultiStatusResponse(xmlresponses)
 
-        newctag = (yield self.getInternalSyncToken())
-        result.headers.setRawHeaders("CTag", (newctag,))
-
-        # Setup some useful logging
-        request.submethod = "Simple batch"
-        if not hasattr(request, "extendedLogItems"):
-            request.extendedLogItems = {}
-        request.extendedLogItems["rcount"] = len(xmlresponses)
-
-        returnValue(result)
-
-
     @inlineCallbacks
     def crudBatchPOST(self, request, xmlroot):
 
@@ -723,14 +748,13 @@
         # Look for return changed data option
         return_changed = self.checkReturnChanged(request)
 
-        # Build response
-        xmlresponses = []
+        # setup for create, update, and delete
+        crudDeleteInfo = []
+        crudUpdateInfo = []
+        crudCreateInfo = []
         checkedBindPrivelege = None
         checkedUnbindPrivelege = None
-        createCount = 0
-        updateCount = 0
-        deleteCount = 0
-        for xmlchild in xmlroot.children:
+        for index, xmlchild in enumerate(xmlroot.children):
 
             # Determine the multiput operation: create, update, delete
             href = xmlchild.childOfType(davxml.HRef.qname())
@@ -743,17 +767,7 @@
                 if xmldata is None:
                     raise HTTPError(StatusResponse(BAD_REQUEST, "Could not parse valid data from request body without a DAV:Href present"))
 
-                # Do privilege check on collection once
-                if checkedBindPrivelege is None:
-                    try:
-                        yield self.authorize(request, (davxml.Bind(),))
-                        checkedBindPrivelege = True
-                    except HTTPError, e:
-                        checkedBindPrivelege = e
-
-                # Create operations
-                yield self.crudCreate(request, xmldata, xmlresponses, return_changed, checkedBindPrivelege)
-                createCount += 1
+                crudCreateInfo.append((index, xmldata))
             else:
                 delete = xmlchild.childOfType(customxml.Delete.qname())
                 ifmatch = xmlchild.childOfType(customxml.IfMatch.qname())
@@ -764,21 +778,17 @@
                         raise HTTPError(StatusResponse(BAD_REQUEST, "Could not parse valid data from request body - no set_items of delete operation"))
                     if xmldata is None:
                         raise HTTPError(StatusResponse(BAD_REQUEST, "Could not parse valid data from request body for set_items operation"))
-                    yield self.crudUpdate(request, str(href), xmldata, ifmatch, return_changed, xmlresponses)
-                    updateCount += 1
+                    crudUpdateInfo.append((index, str(href), xmldata, ifmatch))
                 else:
-                    # Do privilege check on collection once
-                    if checkedUnbindPrivelege is None:
-                        try:
-                            yield self.authorize(request, (davxml.Unbind(),))
-                            checkedUnbindPrivelege = True
-                        except HTTPError, e:
-                            checkedUnbindPrivelege = e
+                    crudDeleteInfo.append((index, str(href), ifmatch))
 
-                    yield self.crudDelete(request, str(href), ifmatch, xmlresponses, checkedUnbindPrivelege)
-                    deleteCount += 1
+        # now do the work
+        xmlresponses = [None] * len(xmlroot.children)
+        yield self.crudDelete(crudDeleteInfo, request, xmlresponses)
+        yield self.crudCreate(crudCreateInfo, request, xmlresponses, return_changed)
+        yield self.crudUpdate(crudUpdateInfo, request, xmlresponses, return_changed)
 
-        result = MultiStatusResponse(xmlresponses)
+        result = MultiStatusResponse(xmlresponses) #@UndefinedVariable
 
         newctag = (yield self.getInternalSyncToken())
         result.headers.setRawHeaders("CTag", (newctag,))
@@ -788,181 +798,171 @@
         if not hasattr(request, "extendedLogItems"):
             request.extendedLogItems = {}
         request.extendedLogItems["rcount"] = len(xmlresponses)
-        if createCount:
-            request.extendedLogItems["create"] = createCount
-        if updateCount:
-            request.extendedLogItems["update"] = updateCount
-        if deleteCount:
-            request.extendedLogItems["delete"] = deleteCount
+        if crudCreateInfo:
+            request.extendedLogItems["create"] = len(crudCreateInfo)
+        if crudUpdateInfo:
+            request.extendedLogItems["update"] = len(crudUpdateInfo)
+        if crudDeleteInfo:
+            request.extendedLogItems["delete"] = len(crudDeleteInfo)
 
         returnValue(result)
 
 
     @inlineCallbacks
-    def crudCreate(self, request, xmldata, xmlresponses, return_changed, hasPrivilege):
+    def crudCreate(self, crudCreateInfo, request, xmlresponses, return_changed):
 
-        code = None
-        error = None
-        try:
-            if isinstance(hasPrivilege, HTTPError):
-                raise hasPrivilege
+        if crudCreateInfo:
+            # Do privilege check on collection once
+            try:
+                yield self.authorize(request, (davxml.Bind(),))
+                hasPrivilege = True
+            except HTTPError, e:
+                hasPrivilege = e
 
-            componentdata = xmldata.textData()
-            component = xmldata.generateComponent()
+            #get components
+            indexedComponents = []
+            for index, xmldata in crudCreateInfo:
 
-            # Create a new name if one was not provided
-            name = md5(str(componentdata) + str(time.time()) + request.path).hexdigest() + self.resourceSuffix()
+                component = xmldata.generateComponent()
 
-            # Get a resource for the new item
-            newchildURL = joinURL(request.path, name)
-            newchild = (yield request.locateResource(newchildURL))
-            yield self.storeResourceData(newchild, component, componentdata)
+                if hasPrivilege is not True:
+                    e = hasPrivilege # use same code pattern as exception
+                    code = e.response.code
+                    if isinstance(e.response, ErrorResponse):
+                        error = e.response.error
+                        error = (error.namespace, error.name,)
 
-            # FIXME: figure out return_changed behavior
+                    xmlresponse = yield self.bulkCreateResponse(component, None, None, None, code, error)
+                    xmlresponses[index] = xmlresponse
 
-        except HTTPError, e:
-            # Extract the pre-condition
-            code = e.response.code
-            if isinstance(e.response, ErrorResponse):
-                error = e.response.error
-                error = (error.namespace, error.name,)
+                else:
+                    indexedComponents.append((index, component,))
 
-        except Exception:
-            code = BAD_REQUEST
+            yield self.bulkCreate(indexedComponents, request, return_changed, xmlresponses)
 
-        if code is None:
-            etag = (yield newchild.etag())
-            xmlresponses.append(
-                davxml.PropertyStatusResponse(
-                    davxml.HRef.fromString(newchildURL),
-                    davxml.PropertyStatus(
-                        davxml.PropertyContainer(
-                            davxml.GETETag.fromString(etag.generate()),
-                            customxml.UID.fromString(component.resourceUID()),
-                        ),
-                        davxml.Status.fromResponseCode(OK),
-                    )
-                )
-            )
-        else:
-            xmlresponses.append(
-                davxml.StatusResponse(
-                    davxml.HRef.fromString(""),
-                    davxml.Status.fromResponseCode(code),
-                    davxml.Error(
-                        WebDAVUnknownElement.withName(*error),
-                        customxml.UID.fromString(component.resourceUID()),
-                    ) if error else None,
-                )
-            )
 
-
     @inlineCallbacks
-    def crudUpdate(self, request, href, xmldata, ifmatch, return_changed, xmlresponses):
-        code = None
-        error = None
-        try:
-            componentdata = xmldata.textData()
-            component = xmldata.generateComponent()
+    def crudUpdate(self, crudUpdateInfo, request, xmlresponses, return_changed):
 
-            updateResource = (yield request.locateResource(href))
-            if not updateResource.exists():
-                raise HTTPError(NOT_FOUND)
+        for index, href, xmldata, ifmatch in crudUpdateInfo:
 
-            # Check privilege
-            yield updateResource.authorize(request, (davxml.Write(),))
+            code = None
+            error = None
+            try:
+                componentdata = xmldata.textData()
+                component = xmldata.generateComponent()
 
-            # Check if match
-            etag = (yield updateResource.etag())
-            if ifmatch and ifmatch != etag.generate():
-                raise HTTPError(PRECONDITION_FAILED)
+                updateResource = (yield request.locateResource(href))
+                if not updateResource.exists():
+                    raise HTTPError(NOT_FOUND)
 
-            yield self.storeResourceData(updateResource, component, componentdata)
+                # Check privilege
+                yield updateResource.authorize(request, (davxml.Write(),))
 
-            # FIXME: figure out return_changed behavior
+                # Check if match
+                etag = (yield updateResource.etag())
+                if ifmatch and ifmatch != etag.generate():
+                    raise HTTPError(PRECONDITION_FAILED)
 
-        except HTTPError, e:
-            # Extract the pre-condition
-            code = e.response.code
-            if isinstance(e.response, ErrorResponse):
-                error = e.response.error
-                error = (error.namespace, error.name,)
+                yield self.storeResourceData(updateResource, component, componentdata)
 
-        except Exception:
-            code = BAD_REQUEST
+            except HTTPError, e:
+                # Extract the pre-condition
+                code = e.response.code
+                if isinstance(e.response, ErrorResponse):
+                    error = e.response.error
+                    error = (error.namespace, error.name,)
 
-        if code is None:
-            xmlresponses.append(
-                davxml.PropertyStatusResponse(
-                    davxml.HRef.fromString(href),
-                    davxml.PropertyStatus(
-                        davxml.PropertyContainer(
-                            davxml.GETETag.fromString(etag.generate()),
-                        ),
-                        davxml.Status.fromResponseCode(OK),
+            except Exception:
+                code = BAD_REQUEST
+
+            if code is None:
+                if not return_changed or dataChanged is None:
+                    xmlresponses[index] = davxml.PropertyStatusResponse(
+                        davxml.HRef.fromString(href),
+                        davxml.PropertyStatus(
+                            davxml.PropertyContainer(
+                                davxml.GETETag.fromString(etag.generate()),
+                            ),
+                            davxml.Status.fromResponseCode(OK),
+                        )
                     )
-                )
-            )
-        else:
-            xmlresponses.append(
-                davxml.StatusResponse(
-                    davxml.HRef.fromString(href),
-                    davxml.Status.fromResponseCode(code),
-                    davxml.Error(
-                        WebDAVUnknownElement.withName(*error),
-                    ) if error else None,
-                )
-            )
+                else:
+                    xmlresponses[index] = davxml.PropertyStatusResponse(
+                        davxml.HRef.fromString(href),
+                        davxml.PropertyStatus(
+                            davxml.PropertyContainer(
+                                davxml.GETETag.fromString(etag.generate()),
+                                self.xmlDataElementType().fromTextData(changedData),
+                            ),
+                            davxml.Status.fromResponseCode(OK),
+                        )
+                    )
+            else:
+                xmlresponses[index] = davxml.StatusResponse(
+                        davxml.HRef.fromString(href),
+                        davxml.Status.fromResponseCode(code),
+                        davxml.Error(
+                            WebDAVUnknownElement.withName(*error),
+                        ) if error else None,
+                    )
 
 
     @inlineCallbacks
-    def crudDelete(self, request, href, ifmatch, xmlresponses, hasPrivilege):
-        code = None
-        error = None
-        try:
-            if isinstance(hasPrivilege, HTTPError):
-                raise hasPrivilege
+    def crudDelete(self, crudDeleteInfo, request, xmlresponses):
 
-            deleteResource = (yield request.locateResource(href))
-            if not deleteResource.exists():
-                raise HTTPError(NOT_FOUND)
+        if crudDeleteInfo:
 
-            # Check if match
-            etag = (yield deleteResource.etag())
-            if ifmatch and ifmatch != etag.generate():
-                raise HTTPError(PRECONDITION_FAILED)
+            # Do privilege check on collection once
+            try:
+                yield self.authorize(request, (davxml.Unbind(),))
+                hasPrivilege = True
+            except HTTPError, e:
+                hasPrivilege = e
 
-            yield deleteResource.storeRemove(request)
+            for index, href, ifmatch in crudDeleteInfo:
+                code = None
+                error = None
+                try:
+                    if hasPrivilege is not True:
+                        raise hasPrivilege
 
-        except HTTPError, e:
-            # Extract the pre-condition
-            code = e.response.code
-            if isinstance(e.response, ErrorResponse):
-                error = e.response.error
-                error = (error.namespace, error.name,)
+                    deleteResource = (yield request.locateResource(href))
+                    if not deleteResource.exists():
+                        raise HTTPError(NOT_FOUND)
 
-        except Exception:
-            code = BAD_REQUEST
+                    # Check if match
+                    etag = (yield deleteResource.etag())
+                    if ifmatch and ifmatch != etag.generate():
+                        raise HTTPError(PRECONDITION_FAILED)
 
-        if code is None:
-            xmlresponses.append(
-                davxml.StatusResponse(
-                    davxml.HRef.fromString(href),
-                    davxml.Status.fromResponseCode(OK),
-                )
-            )
-        else:
-            xmlresponses.append(
-                davxml.StatusResponse(
-                    davxml.HRef.fromString(href),
-                    davxml.Status.fromResponseCode(code),
-                    davxml.Error(
-                        WebDAVUnknownElement.withName(*error),
-                    ) if error else None,
-                )
-            )
+                    yield deleteResource.storeRemove(request)
 
+                except HTTPError, e:
+                    # Extract the pre-condition
+                    code = e.response.code
+                    if isinstance(e.response, ErrorResponse):
+                        error = e.response.error
+                        error = (error.namespace, error.name,)
 
+                except Exception:
+                    code = BAD_REQUEST
+
+                if code is None:
+                    xmlresponses[index] = davxml.StatusResponse(
+                        davxml.HRef.fromString(href),
+                        davxml.Status.fromResponseCode(OK),
+                    )
+                else:
+                    xmlresponses[index] = davxml.StatusResponse(
+                        davxml.HRef.fromString(href),
+                        davxml.Status.fromResponseCode(code),
+                        davxml.Error(
+                            WebDAVUnknownElement.withName(*error),
+                        ) if error else None,
+                    )
+
+
     def notifierID(self):
         return "%s/%s" % self._newStoreObject.notifierID()
 
@@ -1426,7 +1426,7 @@
 
 
     def resourceType(self,):
-        return davxml.ResourceType.dropboxhome  #@UndefinedVariable
+        return davxml.ResourceType.dropboxhome #@UndefinedVariable
 
 
     def listChildren(self):
@@ -1478,7 +1478,7 @@
 
 
     def resourceType(self):
-        return davxml.ResourceType.dropbox  #@UndefinedVariable
+        return davxml.ResourceType.dropbox #@UndefinedVariable
 
 
     @inlineCallbacks
@@ -1728,7 +1728,7 @@
 
 
     def resourceType(self,):
-        return davxml.ResourceType.dropboxhome  #@UndefinedVariable
+        return davxml.ResourceType.dropboxhome #@UndefinedVariable
 
 
     def listChildren(self):
@@ -1831,7 +1831,7 @@
 
 
     def resourceType(self,):
-        return davxml.ResourceType.dropbox  #@UndefinedVariable
+        return davxml.ResourceType.dropbox #@UndefinedVariable
 
 
     @inlineCallbacks
@@ -2906,8 +2906,8 @@
         self._name = addressbook.name() if addressbook else name
 
         if config.EnableBatchUpload:
-            self._postHandlers[("text", "vcard")] = _CommonHomeChildCollectionMixin.simpleBatchPOST
-            self.xmlDocHandlers[customxml.Multiput] = _CommonHomeChildCollectionMixin.crudBatchPOST
+            self._postHandlers[("text", "vcard")] = AddressBookCollectionResource.simpleBatchPOST
+            self.xmlDocHandlers[customxml.Multiput] = AddressBookCollectionResource.crudBatchPOST
 
 
     def __repr__(self):
@@ -2987,7 +2987,7 @@
     @inlineCallbacks
     def storeRemove(self, request):
         """
-        handle handle remove of partially shared addressbook, else call super
+        handle remove of partially shared addressbook, else call super
         """
         if self.isShareeResource() and self._newStoreObject.shareUID() is None:
             log.debug("Removing shared collection %s" % (self,))
@@ -3001,7 +3001,158 @@
         returnValue((yield super(AddressBookCollectionResource, self).storeRemove(request)))
 
 
+    @inlineCallbacks
+    def bulkCreate(self, indexedComponents, request, return_changed, xmlresponses):
+        """
+        bulk create allowing groups to contain member UIDs added during the same bulk create
+        """
+        groupRetries = []
+        coaddedUIDs = set()
+        for index, component in indexedComponents:
 
+            try:
+                # Create a new name if one was not provided
+                name = md5(str(index) + component.resourceUID() + str(time.time()) + request.path).hexdigest() + self.resourceSuffix()
+
+                # Get a resource for the new item
+                newchildURL = joinURL(request.path, name)
+                newchild = (yield request.locateResource(newchildURL))
+                changedData = (yield self.storeResourceData(newchild, component, returnChangedData=return_changed))
+
+            except GroupWithUnsharedAddressNotAllowedError, e:
+                # save off info and try again below
+                missingUIDs = set(e.message)
+                groupRetries.append((index, component, newchildURL, newchild, missingUIDs,))
+
+            except HTTPError, e:
+                # Extract the pre-condition
+                code = e.response.code
+                if isinstance(e.response, ErrorResponse):
+                    error = e.response.error
+                    error = (error.namespace, error.name,)
+
+                xmlresponses[index] = (
+                    yield self.bulkCreateResponse(component, newchildURL, newchild, None, code, error)
+                )
+
+            except Exception:
+                xmlresponses[index] = (
+                    yield self.bulkCreateResponse(component, newchildURL, newchild, None, code=BAD_REQUEST, error=None)
+                )
+
+            else:
+                if not return_changed:
+                    changedData = None
+                coaddedUIDs |= set([component.resourceUID()])
+                xmlresponses[index] = (
+                    yield self.bulkCreateResponse(component, newchildURL, newchild, changedData, code=None, error=None)
+                )
+
+        if groupRetries:
+            # get set of UIDs added
+            coaddedUIDs |= set([groupRetry[1].resourceUID() for groupRetry in groupRetries])
+
+            # check each group add to see if it will succeed if coaddedUIDs are allowed
+            while(True):
+                for groupRetry in groupRetries:
+                    if bool(groupRetry[4] - coaddedUIDs):
+                        break
+                else:
+                    break
+
+                # give FORBIDDEN response
+                index, component, newchildURL, newchild, missingUIDs = groupRetry
+                xmlresponses[index] = (
+                    yield self.bulkCreateResponse(component, newchildURL, newchild, changedData=None, code=FORBIDDEN, error=None)
+                )
+                coaddedUIDs -= set([component.resourceUID()]) # group uid not added
+                groupRetries.remove(groupRetry) # remove this retry
+
+            for index, component, newchildURL, newchild, missingUIDs in groupRetries:
+                # newchild._metadata -> newchild._options during store
+                newchild._metadata["coaddedUIDs"] = coaddedUIDs
+
+                # don't catch errors, abort the whole transaction
+                changedData = yield self.storeResourceData(newchild, component, returnChangedData=return_changed)
+                if not return_changed:
+                    changedData = None
+                xmlresponses[index] = (
+                    yield self.bulkCreateResponse(component, newchildURL, newchild, changedData, code=None, error=None)
+                )
+
+
+    @inlineCallbacks
+    def crudDelete(self, crudDeleteInfo, request, xmlresponses):
+        """
+        Change handling of privileges
+        """
+        if crudDeleteInfo:
+            # Do privilege check on collection once
+            try:
+                yield self.authorize(request, (davxml.Unbind(),))
+                hasPrivilege = True
+            except HTTPError, e:
+                hasPrivilege = e
+
+            for index, href, ifmatch in crudDeleteInfo:
+                code = None
+                error = None
+                try:
+                    deleteResource = (yield request.locateResource(href))
+                    if not deleteResource.exists():
+                        raise HTTPError(NOT_FOUND)
+
+                    # Check if match
+                    etag = (yield deleteResource.etag())
+                    if ifmatch and ifmatch != etag.generate():
+                        raise HTTPError(PRECONDITION_FAILED)
+
+                    #===========================================================
+                    # # If unshared is allowed deletes fails but crud adds works work!
+                    # if (hasPrivilege is not True and not (
+                    #             deleteResource.isShareeResource() or
+                    #             deleteResource._newStoreObject.isGroupForSharedAddressBook()
+                    #         )
+                    #     ):
+                    #     raise hasPrivilege
+                    #===========================================================
+
+                    # don't allow shared group deletion -> unshare
+                    if (deleteResource.isShareeResource() or
+                        deleteResource._newStoreObject.isGroupForSharedAddressBook()):
+                        raise HTTPError(FORBIDDEN)
+
+                    if hasPrivilege is not True:
+                        raise hasPrivilege
+
+                    yield deleteResource.storeRemove(request)
+
+                except HTTPError, e:
+                    # Extract the pre-condition
+                    code = e.response.code
+                    if isinstance(e.response, ErrorResponse):
+                        error = e.response.error
+                        error = (error.namespace, error.name,)
+
+                except Exception:
+                    code = BAD_REQUEST
+
+                if code is None:
+                    xmlresponses[index] = davxml.StatusResponse(
+                        davxml.HRef.fromString(href),
+                        davxml.Status.fromResponseCode(OK),
+                    )
+                else:
+                    xmlresponses[index] = davxml.StatusResponse(
+                        davxml.HRef.fromString(href),
+                        davxml.Status.fromResponseCode(code),
+                        davxml.Error(
+                            WebDAVUnknownElement.withName(*error),
+                        ) if error else None,
+                    )
+
+
+
 class GlobalAddressBookCollectionResource(GlobalAddressBookResource, AddressBookCollectionResource):
     """
     Wrapper around a L{txdav.carddav.iaddressbook.IAddressBook}.
@@ -3240,7 +3391,7 @@
             log.debug("Resource not found: %s" % (self,))
             raise HTTPError(NOT_FOUND)
 
-        if self._newStoreObject.addressbook().owned():
+        if not self._parentResource.isShareeResource():
             returnValue((yield super(AddressBookObjectResource, self).accessControlList(request, *a, **kw)))
 
         # Direct shares use underlying privileges of shared collection

Modified: CalendarServer/trunk/txdav/carddav/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/carddav/datastore/sql.py	2013-08-07 22:36:54 UTC (rev 11591)
+++ CalendarServer/trunk/txdav/carddav/datastore/sql.py	2013-08-10 02:35:04 UTC (rev 11592)
@@ -25,6 +25,8 @@
     "AddressBookObject",
 ]
 
+from copy import deepcopy
+
 from twext.enterprise.dal.syntax import Delete, Insert, Len, Parameter, \
     Update, Union, Max, Select, utcNowSQL
 from twext.enterprise.locking import NamedLock
@@ -63,9 +65,7 @@
 
 from zope.interface.declarations import implements
 
-import copy
 
-
 class AddressBookHome(CommonHome):
 
     implements(IAddressBookHome)
@@ -102,7 +102,7 @@
 
 
     @classproperty
-    def _resourceIDAndHomeResourceIDFromOwnerQuery(cls):  #@NoSelf
+    def _resourceIDAndHomeResourceIDFromOwnerQuery(cls): #@NoSelf
         home = cls._homeSchema
         return Select([home.RESOURCE_ID, home.ADDRESSBOOK_PROPERTY_STORE_ID],
                       From=home, Where=home.OWNER_UID == Parameter("ownerUID"))
@@ -265,7 +265,7 @@
 
 
     @classproperty
-    def _syncTokenQuery(cls):  #@NoSelf
+    def _syncTokenQuery(cls): #@NoSelf
         """
         DAL Select statement to find the sync token.
         """
@@ -309,7 +309,7 @@
 
 
     @classproperty
-    def _changesQuery(cls):  #@NoSelf
+    def _changesQuery(cls): #@NoSelf
         rev = cls._revisionsSchema
         return Select(
             [rev.COLLECTION_NAME,
@@ -582,7 +582,7 @@
                       Where=obj.ADDRESSBOOK_HOME_RESOURCE_ID == Parameter("addressbookResourceID"),)
 
 
-    def _groupForSharedAddressBookRow(self):  #@NoSelf
+    def _groupForSharedAddressBookRow(self): #@NoSelf
         return [
             self._resourceID,  # obj.ADDRESSBOOK_HOME_RESOURCE_ID,
             self._resourceID,  # obj.RESOURCE_ID,
@@ -675,7 +675,7 @@
         )
         # get ownerHomeIDs
         for dataRow in dataRows:
-            bindMode, homeID, resourceID, bindName, bindStatus, bindRevision, bindMessage = dataRow[:cls.bindColumnCount]  #@UnusedVariable
+            bindMode, homeID, resourceID, bindName, bindStatus, bindRevision, bindMessage = dataRow[:cls.bindColumnCount] #@UnusedVariable
             ownerHome = yield home.ownerHomeWithChildID(resourceID)
             ownerHomeToDataRowMap[ownerHome] = dataRow
 
@@ -684,7 +684,7 @@
             home._txn, homeID=home._resourceID
         )
         for groupBindRow in groupBindRows:
-            bindMode, homeID, resourceID, bindName, bindStatus, bindRevision, bindMessage = groupBindRow[:AddressBookObject.bindColumnCount]  #@UnusedVariable
+            bindMode, homeID, resourceID, bindName, bindStatus, bindRevision, bindMessage = groupBindRow[:AddressBookObject.bindColumnCount] #@UnusedVariable
             ownerAddressBookID = yield AddressBookObject.ownerAddressBookIDFromGroupID(home._txn, resourceID)
             ownerHome = yield home.ownerHomeWithChildID(ownerAddressBookID)
             if ownerHome not in ownerHomeToDataRowMap:
@@ -707,7 +707,7 @@
 
             # Create the actual objects merging in properties
             for ownerHome, dataRow in ownerHomeToDataRowMap.iteritems():
-                bindMode, homeID, resourceID, bindName, bindStatus, bindRevision, bindMessage = dataRow[:cls.bindColumnCount]  #@UnusedVariable
+                bindMode, homeID, resourceID, bindName, bindStatus, bindRevision, bindMessage = dataRow[:cls.bindColumnCount] #@UnusedVariable
                 additionalBind = dataRow[cls.bindColumnCount:cls.bindColumnCount + len(cls.additionalBindColumns())]
                 metadata = dataRow[cls.bindColumnCount + len(cls.additionalBindColumns()):]
 
@@ -802,7 +802,7 @@
             returnValue(None)
 
         row = rows[0]
-        bindMode, homeID, resourceID, bindName, bindStatus, bindRevision, bindMessage, ownerAddressBookID, cachedBindStatus = row[:cls.bindColumnCount + 2]  #@UnusedVariable
+        bindMode, homeID, resourceID, bindName, bindStatus, bindRevision, bindMessage, ownerAddressBookID, cachedBindStatus = row[:cls.bindColumnCount + 2] #@UnusedVariable
 
         # if wrong status, exit here.  Item is in queryCache
         if (cachedBindStatus == _BIND_STATUS_ACCEPTED) != bool(accepted):
@@ -838,7 +838,7 @@
         bindRows = yield cls._bindForNameAndHomeID.on(home._txn, name=name, homeID=home._resourceID)
         if bindRows and (bindRows[0][4] == _BIND_STATUS_ACCEPTED) == bool(accepted):
             bindRow = bindRows[0]
-            bindMode, homeID, resourceID, bindName, bindStatus, bindRevision, bindMessage = bindRow[:cls.bindColumnCount]  #@UnusedVariable
+            bindMode, homeID, resourceID, bindName, bindStatus, bindRevision, bindMessage = bindRow[:cls.bindColumnCount] #@UnusedVariable
 
             # alt:
             # returnValue((yield cls.objectWithID(home, resourceID)))
@@ -853,7 +853,7 @@
         )
         if groupBindRows and (groupBindRows[0][4] == _BIND_STATUS_ACCEPTED) == bool(accepted):
             groupBindRow = groupBindRows[0]
-            bindMode, homeID, resourceID, bindName, bindStatus, bindRevision, bindMessage = groupBindRow[:AddressBookObject.bindColumnCount]  #@UnusedVariable
+            bindMode, homeID, resourceID, bindName, bindStatus, bindRevision, bindMessage = groupBindRow[:AddressBookObject.bindColumnCount] #@UnusedVariable
 
             ownerAddressBookID = yield AddressBookObject.ownerAddressBookIDFromGroupID(home._txn, resourceID)
             # alt:
@@ -892,7 +892,7 @@
         )
         if bindRows and (bindRows[0][4] == _BIND_STATUS_ACCEPTED) == bool(accepted):
             bindRow = bindRows[0]
-            bindMode, homeID, resourceID, bindName, bindStatus, bindRevision, bindMessage = bindRow[:cls.bindColumnCount]  #@UnusedVariable
+            bindMode, homeID, resourceID, bindName, bindStatus, bindRevision, bindMessage = bindRow[:cls.bindColumnCount] #@UnusedVariable
 
             ownerHome = yield home.ownerHomeWithChildID(resourceID)
             if accepted:
@@ -905,7 +905,7 @@
         )
         if groupBindRows and (groupBindRows[0][4] == _BIND_STATUS_ACCEPTED) == bool(accepted):
             groupBindRow = groupBindRows[0]
-            bindMode, homeID, resourceID, bindName, bindStatus, bindRevision, bindMessage = groupBindRow[:AddressBookObject.bindColumnCount]  #@UnusedVariable
+            bindMode, homeID, resourceID, bindName, bindStatus, bindRevision, bindMessage = groupBindRow[:AddressBookObject.bindColumnCount] #@UnusedVariable
 
             ownerAddressBookID = yield AddressBookObject.ownerAddressBookIDFromGroupID(home._txn, resourceID)
             ownerHome = yield home.ownerHomeWithChildID(ownerAddressBookID)
@@ -942,7 +942,7 @@
             home._txn, homeID=home._resourceID
         )
         for row in rows:
-            bindMode, homeID, resourceID, bindName, bindStatus, bindRevision, bindMessage = row[:cls.bindColumnCount]  #@UnusedVariable
+            bindMode, homeID, resourceID, bindName, bindStatus, bindRevision, bindMessage = row[:cls.bindColumnCount] #@UnusedVariable
             ownerHome = yield home._txn.homeWithResourceID(home._homeType, resourceID, create=True)
             names |= set([ownerHome.shareeAddressBookName()])
 
@@ -950,7 +950,7 @@
             home._txn, homeID=home._resourceID
         )
         for groupRow in groupRows:
-            bindMode, homeID, resourceID, bindName, bindStatus, bindRevision, bindMessage = groupRow[:AddressBookObject.bindColumnCount]  #@UnusedVariable
+            bindMode, homeID, resourceID, bindName, bindStatus, bindRevision, bindMessage = groupRow[:AddressBookObject.bindColumnCount] #@UnusedVariable
             ownerAddressBookID = yield AddressBookObject.ownerAddressBookIDFromGroupID(home._txn, resourceID)
             ownerHome = yield home._txn.homeWithResourceID(home._homeType, ownerAddressBookID, create=True)
             names |= set([ownerHome.shareeAddressBookName()])
@@ -1021,7 +1021,7 @@
             readWriteGroupIDs = []
             readOnlyGroupIDs = []
             for groupBindRow in groupBindRows:
-                bindMode, homeID, resourceID, bindName, bindStatus, bindRevision, bindMessage = groupBindRow[:AddressBookObject.bindColumnCount]  #@UnusedVariable
+                bindMode, homeID, resourceID, bindName, bindStatus, bindRevision, bindMessage = groupBindRow[:AddressBookObject.bindColumnCount] #@UnusedVariable
                 if bindMode == _BIND_MODE_WRITE:
                     readWriteGroupIDs.append(resourceID)
                 else:
@@ -1069,7 +1069,7 @@
         readWriteGroupIDs = []
         readOnlyGroupIDs = []
         for groupBindRow in groupBindRows:
-            bindMode, homeID, resourceID, bindName, bindStatus, bindRevision, bindMessage = groupBindRow[:AddressBookObject.bindColumnCount]  #@UnusedVariable
+            bindMode, homeID, resourceID, bindName, bindStatus, bindRevision, bindMessage = groupBindRow[:AddressBookObject.bindColumnCount] #@UnusedVariable
             if bindMode == _BIND_MODE_WRITE:
                 readWriteGroupIDs.append(resourceID)
             else:
@@ -1267,7 +1267,7 @@
     # _homeChildMetaDataSchema = schema.ADDRESSBOOK_OBJECT
 
 
-    def __init__(self, addressbook, name, uid, resourceID=None, options=None):  #@UnusedVariable
+    def __init__(self, addressbook, name, uid, resourceID=None, options=None):
 
         self._kind = None
         self._ownerAddressBookResourceID = None
@@ -1280,6 +1280,7 @@
         self._bindMessage = None
         self._bindName = None
         super(AddressBookObject, self).__init__(addressbook, name, uid, resourceID, options)
+        self._options = {} if options is None else options
 
 
     def __repr__(self):
@@ -1316,16 +1317,12 @@
     def remove(self):
 
         if self.owned():
-            # storebridge should already have done this
-            yield self.unshare()
+            yield self.unshare() # storebridge should already have done this
         else:
             # handled in storebridge as unshare, should not be here.  assert instead?
-            if self.isGroupForSharedAddressBook():
+            if self.isGroupForSharedAddressBook() or self.shareUID():
                 raise HTTPError(FORBIDDEN)
-            elif self.shareUID():
-                raise HTTPError(FORBIDDEN)
 
-
         if not self.owned() and not self.addressbook().fullyShared():
             readWriteObjectIDs = []
             readWriteGroupIDs = yield self.addressbook().readWriteGroupIDs()
@@ -1345,7 +1342,8 @@
 
             yield self._changeAddressBookRevision(self.ownerHome().addressbook())
 
-        else:  # owned or fully shared
+            # FIXME: drop though here and actually delete
+        else: # owned or fully shared
             # delete members table rows for this object,...
             aboMembers = schema.ABO_MEMBERS
             aboForeignMembers = schema.ABO_FOREIGN_MEMBERS
@@ -1416,7 +1414,7 @@
 
 
     @classproperty
-    def _allColumnsWithResourceID(cls):  #@NoSelf
+    def _allColumnsWithResourceID(cls): #@NoSelf
         obj = cls._objectSchema
         return Select(
             cls._allColumns, From=obj,
@@ -1501,7 +1499,7 @@
 
                 if groupBindRows:
                     groupBindRow = groupBindRows[0]
-                    bindMode, homeID, resourceID, bindName, bindStatus, bindRevision, bindMessage = groupBindRow[:AddressBookObject.bindColumnCount]  #@UnusedVariable
+                    bindMode, homeID, resourceID, bindName, bindStatus, bindRevision, bindMessage = groupBindRow[:AddressBookObject.bindColumnCount] #@UnusedVariable
                     self._bindMode = bindMode
                     self._bindStatus = bindStatus
                     self._bindMessage = bindMessage
@@ -1517,7 +1515,7 @@
 
 
     @classproperty
-    def _allColumns(cls):  #@NoSelf
+    def _allColumns(cls): #@NoSelf
         """
         Full set of columns in the object table that need to be loaded to
         initialize the object resource state.
@@ -1631,7 +1629,7 @@
         self.validAddressDataCheck(component, inserting)
 
 
-    def validAddressDataCheck(self, component, inserting):  #@UnusedVariable
+    def validAddressDataCheck(self, component, inserting): #@UnusedVariable
         """
         Check that the calendar data is valid iCalendar.
         @return:         tuple: (True/False if the calendar data is valid,
@@ -1706,7 +1704,8 @@
         self.fullValidation(component, inserting)
 
         # UID lock - this will remain active until the end of the current txn
-        yield self._lockUID(component, inserting)
+        if not inserting or self._options.get("coaddedUIDs") is None:
+            yield self._lockUID(component, inserting)
 
         yield self.updateDatabase(component, inserting=inserting)
         yield self._changeAddressBookRevision(self._addressbook, inserting)
@@ -1758,7 +1757,7 @@
 
 
     @classproperty
-    def _insertABObject(cls):  #@NoSelf
+    def _insertABObject(cls): #@NoSelf
         """
         DAL statement to create an addressbook object with all default values.
         """
@@ -1778,7 +1777,7 @@
 
 
     @inlineCallbacks
-    def updateDatabase(self, component, expand_until=None, reCreate=False,  #@UnusedVariable
+    def updateDatabase(self, component, expand_until=None, reCreate=False, #@UnusedVariable
                        inserting=False):
         """
         Update the database tables for the new data being written.
@@ -1795,12 +1794,17 @@
         if not self._ownerAddressBookResourceID:
             self._ownerAddressBookResourceID = self.ownerHome().addressbook()._resourceID
 
+        uid = component.resourceUID()
+        assert inserting or self._uid == uid  # can't change UID. Should be checked in upper layers
+        self._uid = uid
+
         if self._kind == _ABO_KIND_GROUP:
+            memberAddresses = set(component.resourceMemberAddresses())
 
             # get member ids
             memberUIDs = []
             foreignMemberAddrs = []
-            for memberAddr in set(component.resourceMemberAddresses()):
+            for memberAddr in memberAddresses:
                 if len(memberAddr) > len("urn:uuid:") and memberAddr.startswith("urn:uuid:"):
                     memberUIDs.append(memberAddr[len("urn:uuid:"):])
                 else:
@@ -1811,42 +1815,45 @@
             ) if memberUIDs else []
             memberIDs = [memberRow[0] for memberRow in memberRows]
             foundUIDs = [memberRow[1] for memberRow in memberRows]
-            foreignMemberAddrs.extend(["urn:uuid:" + missingUID for missingUID in set(memberUIDs) - set(foundUIDs)])
+            foundUIDs.append(self._uid) # circular self reference is OK
+            missingUIDs = set(memberUIDs) - set(foundUIDs)
 
-            if not self.owned():
-                if not self.addressbook().fullyShared():
-                    # in shared ab defined by groups, all members must be inside the shared groups
+            if not self.owned() and not self.addressbook().fullyShared():
+                # in partially shared addressbook, all members UIDs must be inside the shared groups
+                # except during bulk operations, when other UIDs added are OK
+                coaddedUIDs = set() if self._options.get("coaddedUIDs") is None else self._options["coaddedUIDs"]
+                if missingUIDs - coaddedUIDs:
+                    raise GroupWithUnsharedAddressNotAllowedError(missingUIDs)
 
-                    # FIXME: does this apply to whole-shared address books too?
-                    if foreignMemberAddrs:
-                        raise GroupWithUnsharedAddressNotAllowedError
+                # see if user has access all the members
+                acceptedGroupIDs = yield self.addressbook().acceptedGroupIDs()
+                allowedObjectIDs = yield self.addressbook().expandGroupIDs(self._txn, acceptedGroupIDs)
+                if set(memberIDs) - set(allowedObjectIDs):
+                    raise HTTPError(FORBIDDEN) # could give more info here, and use special exception
 
-                    acceptedGroupIDs = yield self.addressbook().acceptedGroupIDs()
-                    allowedObjectIDs = yield self.addressbook().expandGroupIDs(self._txn, acceptedGroupIDs)
-                    if set(memberIDs) - set(allowedObjectIDs):
-                        raise GroupWithUnsharedAddressNotAllowedError
+            # missing uids and other cuaddrs e.g. user at example.com, are stored in same schema table
+            foreignMemberAddrs.extend(["urn:uuid:" + missingUID for missingUID in missingUIDs])
 
             # don't store group members in object text
-
             orginialComponentText = str(component)
-            # sort addresses in component text
-            memberAddresses = component.resourceMemberAddresses()
             component.removeProperties("X-ADDRESSBOOKSERVER-MEMBER")
-            for memberAddress in sorted(list(set(memberAddresses))):
+            for memberAddress in sorted(list(memberAddresses)): # sort unique
                 component.addProperty(Property("X-ADDRESSBOOKSERVER-MEMBER", memberAddress))
 
-            # use sorted test to get size and md5
+            # use sorted for md5
             componentText = str(component)
             self._md5 = hashlib.md5(componentText).hexdigest()
-            self._size = len(componentText)
             self._componentChanged = orginialComponentText != componentText
 
             # remove members from component get new text
-            self._component = copy.deepcopy(component)
+            self._component = deepcopy(component)
             component.removeProperties("X-ADDRESSBOOKSERVER-MEMBER")
             componentText = str(component)
             self._objectText = componentText
 
+            #size for quota does not include group members
+            self._size = len(componentText)
+
         else:
             self._component = component
             componentText = str(component)
@@ -1854,10 +1861,6 @@
             self._size = len(componentText)
             self._objectText = componentText
 
-        uid = component.resourceUID()
-        assert inserting or self._uid == uid  # can't change UID. Should be checked in upper layers
-        self._uid = uid
-
         # Special - if migrating we need to preserve the original md5
         if self._txn._migrating and hasattr(component, "md5"):
             self._md5 = component.md5
@@ -1867,7 +1870,6 @@
         aboMembers = schema.ABO_MEMBERS
 
         if inserting:
-
             self._resourceID, self._created, self._modified = (
                 yield self._insertABObject.on(
                     self._txn,
@@ -1887,14 +1889,12 @@
                 Where=aboForeignMembers.MEMBER_ADDRESS == "urn:uuid:" + self._uid,
                 Return=aboForeignMembers.GROUP_ID
             ).on(self._txn)
-            groupIDs = [groupIDRow[0] for groupIDRow in groupIDRows]
+            groupIDs = set([groupIDRow[0] for groupIDRow in groupIDRows])
 
-            # FIXME: Is this correct? Write test case
-            if not self.owned():
-                if not self.addressbook().fullyShared() or self.addressbook().shareMode() != _BIND_MODE_WRITE:
-                    readWriteGroupIDs = yield self.addressbook().readWriteGroupIDs()
-                    assert readWriteGroupIDs, "no access"
-                    groupIDs.extend(readWriteGroupIDs)
+            if not self.owned() and not self.addressbook().fullyShared():
+                readWriteGroupIDs = yield self.addressbook().readWriteGroupIDs()
+                assert readWriteGroupIDs, "no access"
+                groupIDs |= set(readWriteGroupIDs)
 
             # add to member table rows
             for groupID in groupIDs:
@@ -1914,6 +1914,10 @@
 
         if self._kind == _ABO_KIND_GROUP:
 
+            # allow circular group
+            if inserting and "urn:uuid:" + self._uid in memberAddresses:
+                memberIDs.append(self._resourceID)
+
             # get current members
             currentMemberRows = yield Select([aboMembers.MEMBER_ID],
                  From=aboMembers,
@@ -2094,7 +2098,7 @@
 
     # same as CommonHomeChild._childrenAndMetadataForHomeID() w/o metadata join
     @classproperty
-    def _childrenAndMetadataForHomeID(cls):  #@NoSelf
+    def _childrenAndMetadataForHomeID(cls): #@NoSelf
         bind = cls._bindSchema
         child = cls._objectSchema
         columns = cls.bindColumns() + cls.additionalBindColumns() + cls.metadataColumns()
@@ -2111,7 +2115,7 @@
 
 
     @classproperty
-    def _addressbookIDForResourceID(cls):  #@NoSelf
+    def _addressbookIDForResourceID(cls): #@NoSelf
         obj = cls._objectSchema
         return Select([obj.PARENT_RESOURCE_ID],
                       From=obj,
@@ -2143,7 +2147,7 @@
         )
 
         result = []
-        for homeUID, homeRID, resourceID, resourceName, bindMode, bindStatus, bindMessage in acceptedRows:  #@UnusedVariable
+        for homeUID, homeRID, resourceID, resourceName, bindMode, bindStatus, bindMessage in acceptedRows: #@UnusedVariable
             invite = SharingInvitation(
                 resourceName,
                 self.addressbook()._home.name(),
@@ -2274,7 +2278,7 @@
                 self._txn, resourceID=self._resourceID, homeID=shareeHome._resourceID
             )
             groupBindRow = groupBindRows[0]
-            bindMode, homeID, resourceID, bindName, bindStatus, bindRevision, bindMessage = groupBindRow[:self.bindColumnCount]  #@UnusedVariable
+            bindMode, homeID, resourceID, bindName, bindStatus, bindRevision, bindMessage = groupBindRow[:self.bindColumnCount] #@UnusedVariable
             if bindStatus == _BIND_STATUS_ACCEPTED:
                 group = yield shareeHome.objectWithShareUID(bindName)
             else:
@@ -2414,7 +2418,7 @@
 
 
     @classproperty
-    def _acceptedBindForHomeIDAndAddressBookID(cls):  #@NoSelf
+    def _acceptedBindForHomeIDAndAddressBookID(cls): #@NoSelf
         bind = cls._bindSchema
         abo = cls._objectSchema
         return Select(
@@ -2428,7 +2432,7 @@
 
 
     @classproperty
-    def _unacceptedBindForHomeIDAndAddressBookID(cls):  #@NoSelf
+    def _unacceptedBindForHomeIDAndAddressBookID(cls): #@NoSelf
         bind = cls._bindSchema
         abo = cls._objectSchema
         return Select(
@@ -2442,7 +2446,7 @@
 
 
     @classproperty
-    def _bindForHomeIDAndAddressBookID(cls):  #@NoSelf
+    def _bindForHomeIDAndAddressBookID(cls): #@NoSelf
         bind = cls._bindSchema
         abo = cls._objectSchema
         return Select(
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20130809/b359ca14/attachment-0001.html>


More information about the calendarserver-changes mailing list