ÿØÿà JFIF    ÿÛ „ !.%+&8&+/1555$;@;4?.451 4,$,44444444444414444444444444444444444444444444444444ÿÀ  á á" ÿÄ     ÿÄ ?    !1AQaq"2‘¡±ÁðBRbrÑá#‚’¢²3S CñÿÄ   ÿÄ !    !1QAa‘2ÿÚ   ? 5˜Z¯V¦cø)›t/? z¨±>Õ5€¶‹Á¤·¼z¼Ü¬+ñ®v¤¨_ˆR­BFn©—˜ý®ç̝P8gýt·ÉSTŦˆìät?þé¼íìN/Þa)ì–í6ô… Ï¿øÃj´¿KÇü]ÿ ªô¹-eKànëÕHTx}ýSÜ›ÿ ”7Ø×&µ<¦  ¥ÑO¶[Ù¯ä¨ÞÃÿ PZ-¬;#õ|•oaÿ ©CìÞz3˜öː/¤­ñTûIØ}š^ mÓ%ªxˆ¥ÉŸu=Z+ISe¿45™¼u;ú&WØ÷€æßQ™®{|íx*TC“#ZŠìZ§²‹ 6pv…³¿¡äª*áZÐ%ÒOáˆo"x«OHk w±æ+¬V(kMúŸ5Vö«$ ÁrÏbàb57/luR ¸ÑÛj Òµì`Мq­û žICÀÊ•©4€Âcà¨Ï€O´<èÐ:›ù(Ë^L8þ‘ÍÌ#¸Ð_Ì©ÙK(Öz 4¬û+¸;ü’V’84‘¬ÃŽ:[â‡ÔÌáõp¢~§ªlæ£ö{®G>J¼"°‡7¯ÆÉèßû ‹É‹§ÁòÃýâßî ^ƾÙõ‹×óH#«LP½ïX=xÑÍ$|W?•~• îëÔ©ª‹ {ÝT…Kÿ ”hûâá)J*ö˜–ÔU;iÇ€/ ÆþjóZ\ýwØ=Ìm ºèËL9 ýèÆð/¨’¥öo=nË.%Îì ŽÕ¯È|{Oj²ƒE6e/ßdÄõ²Ìâ1O®ò×TsəԸhOMýíMˆ¿¼H˜l²,7Â¥#MF/Úf°Ö½± ¸–dr‹NýÊ íjqx{œÉ ä-È ¦ øÄër¨q°ð †nцýÑÄÆ’mä…n<0È™;ÁÝá¯ÁZƒ7FÀmì­ É&9ˆîéi¶ùN§Y• ÃZãAâ?•‡©‰ , ó¾IŸŠc1 4â&y­&pŠ­6;M À 0¹qç»p.á …ŸÅáK@%6·y6ƒ‰3?”úºŽ‰éX5ªPT §µ!=Mž«Ú½‹ÅgÂSâÉaþÓoö–¯ÁÔìR>5éÿ üs¶ÆUcÌ kÇR ]ÿ ù¬¼«VŽ;Â|‡~¢¦”ÏŰæ {L™Õ°Óv¹ò¸írޡעCÃ!íVÕ {¶»sŒNPg/ "uÕbkm²“$ďå¿é¹§°½æz¯6 †s¿!s–wÚÝ“™Œ °.ûj>·+™Òa…©Œ&rÝÎtÛë긪Ît’LAVp%c Úý[ÄzJ¾ÇàXXç@˜ó<êL]·T˜¾¥1Ó©V‡g´æ½¦Ý@¹óø!_@´ÞâSÁ —S3™•& ]@JHÚý©ZŽ €×æÔr»Áf!‡yÞ4Mv*èÓã_{‘åóUuљØ«Oïé*®EvÑ Œ÷‡U \"㪒ÍK+À 4“M¡ï:0¥5í!'<@î´”>Ç»&Z–ïCCV˜Ì5Šo&îhè.žû |ÓK©h$s6KìŒëã)¹hI¦GïOåóI;ììü#É$Š0…Ææ¥TØ.5­¾gn´ “ÂÖ\:hœ89G)J@„}œ:’Ò{/Š"¦_Æ×7Æ3VÇŠÊa]ÚŒÙ€Ä–=®uÁßâACZƒ§§£ Qnâ:«,×{tyø¬iÛcœÜÄ€H½ÄÍCk´÷šß .W'b¤Íåh]÷€=,Žv×cÚEÚHXJX¶îo¨FÒtèöŸ>ªª6[J®Fµ£sGÁeqõfe\íjÒÐïÄÐGˆe1Ø‹.Ø”‘Ëuø Y­ˆÜ ŽG|zùªüMpDnQWÄ”%JŠ™)â*p@Örš«ÕT2Ð%ˆG#ª„ ·¤!°ŸOTÂT¸aÚ%4&h™LµšØüÐ.F¿²ÐÞ_Ç‚¾ÅÃaÜ÷09Æ q€öy˜v‡85õN÷]¬äѼóS{°_MެúÔ#°Ç¸0åÞè2ëôPcvÆw9®ií1Ä8F™˜à‰´+‰Ik1òÝ7“Ñ×ÒsÝ\x‚h`ÞÑ`ó"|µEcý£n˜h`}GÞ !±ù²Ápü²ß6 0ïi󜵩SÈÇ7˜-ÕURO˜¦´f$ªž-Í6(œ}<„ éc øs]ŽŽ„*—¾ ìdŽ„)méª\¿êÎIg¾ØÞ~I#C/¼¼´EÁÈŽi8“©õådô·>euä ƒ'Ê×लR1ÉJE1ÐAát`t;ÇР%Ý<‡¥„ÍÆ`×Oyó)õiI€ñQaŸ4Ûù\áàaÃÔ¹HÃu¹*k€¦<„e S‡&õÏ B!ŽhüÞ`yj}mªf×\¿ Ç~æ­9‡û\՞Ǖg²1Žû5V7 !àöšm° c`ܬøÇìµÒ'P"?…´Ö,"§^•õލsÔ)6˜sæéÍR¼ ò|Sl”‹7 nPW Gòú÷½§O¯‡„l¡kSÞŒr½PÊ@æ¢pŽ-mÿ #Ÿ˜Àº¶Áä¦;ïÔæ$1££`“Õ>„—·ž)ßð³ñ#Ï Ô$¶œ‰ÊE‹À;÷º ¯«P:Ñ”8–IÊtpÞ3ª“>ê“þës4ò2OÏÕ­±zô†Õ§‰.÷ä¸;¿˜“'œ›žª}«Œ{ª±Ì 9ÔóÞÕ‡0 $íWV3Üì¬ —@kÝ4@¿r¼±½¬™›?øØæ´'Áé®CË3-g$˜ö‡×auÚi´Žp/êÛ æF›Ú2v‹ã¿¿,nB1̨ƃqÞa5͝@&Æû“él÷ \C²½UÍc ¯k×¢U ÖéQå™—-r wô ÞÏ<Ò=&=ÿ Ôê Òêˈt,i—;LîÜ á¸*ÚÃ1$êL•LÍ <É)ýÐà’ ;F™{ƒ™˜€&'}‚ãÄK`¡ÞT@I;®žZóè‚s’7®°›+§O­Åq©é»²9<Ô J ¼9O’HL»Ùïì¸rk¼Ž_ý‘TŸu[²ßÚŒ·ü÷B%¯E ŸÔX5êO´ Ç•€’I0 ÉJX` ñ¹õ%;µŸD‘«´€àwÒ™U ûئžÖö\×®×´8 ½‡ºÐÆÓ§?Àkmœ=;d5*@-ì0F Rªýš[Ü6âö̃ڸr*KA9· u*µæ£?U¸Âêí†8@¦X4 e-ò„0s{ HâUpU?¼mñRa°®a%Ð'tÉ×’\¾ÊÉ]t›h>·(Ë@R¼¡Ãt h}’O÷au<+nT…Ö…MӐ??Óe95 q>í/;&JSû °¯ÊéÞ øƒ*Ã2½Ài&:nôUl=¾¿5eˆ3”ñc|Ú2V”>„»&eE;«ÚäC p¢Û úy 9š[ŒÌx¼擼A&DåÒ¯ˆ¤ÀÌ;"˜ ÏQä¸åhÊ}Ûq«Û0WžÒ|»€ø®öCm5•\ÇÀ§Pe3£]0ÃàLDÉ‰1øªxjgwT‚÷¿LΨK‹›ùs—xˆÜ±µ kæ¸f‰‰ÜGk/LÛØ6d9ò¶ùA{ƒA3š/¬D¬khÓk‰`˜"㯒r¿±Óã jx‡°e}<Ñø\3y:'À•/h½Í€Ç4~g ?Û(¼]v‘ªlKÎâ~?O‚W%{Ì:“'©úNq¾›úo(X’¥¯ˆ nFê{Ç€ü?º'ë ø‹ì Þ09ŒÌç9Æ —ËC`j@ÓÄ(+a‹un¸#ÂꟋ{K`‘ÑÍÍ'à´»/Û,KW;Þ4²þð ï Nm|~fGÏ(…³Ã)«1ö­Õ ¥‡¨©ƒÃ™ü-s=à=U66Ï«Ýc蓦W¹íž®›nÔ%êÇìŒ<#Ü×84ån®Ð ÒåOC` ñânÑs‡¢ç 1õ%Îhì½Ã½® e:ݼUZo™`  ÅZŸŒÊ«ê1ÏÄo$q¹Þ€©ˆhÐÉä¯ñ[!…Ú˜àJ:x2$Íß&PåT£6ç— ‡Í*4Ýšçjÿ ‰É nófÐ ó(L5C•åÆ\rMÒ@ò }y-W}™üýVù—ú¢=Ù”c®‘< M ž ´Phr ¦©TD ‘ù.$´÷O‡‘V2Æò.=IUŒ=ž‡â¬i™aþÓåÙ?òUø'ØÖ•.~* šTŒ!•-×áºTâ®ä#õü'´ eýlYÅÓeÕKÂrT"CÚ@u!Óxƒ{š3€}1¿(r}%«nËamjÑ%ÑNEò v ˜à  σöK³,*º.àzù¨™Ó ÚçâU¦*¿ 9{%Ö¹ njûdaXöb) kÛÆ±ûÓ\°M7ˆÂ=û›ç¿Ã‚­V»Cg–8ÙêE- j)k$º`Ã-ùEýeBÆÇ]c¡°ñty&Òd0nõ'¡W+ƒ*|–øµFa\GQªEAÔp5\Ǽ·¼Ç8·õ -â§Ú[ ‡ uZeÖ 3}×d'+¹:ð+K†Û®s!Ï$úe€<Û”x)1»a­¡LC]¸µík…ÚàA»AYº{†ªS[¦5HÒ7ù --,ísòDØ€èk ÞÀîÜ ò@â( ËNˆë›4ô½•/¦o‡€Û7 ê•ÆêòðÜy'Án½µ á˜ݦ ndeo…[ì¶Ê,¥R³Ä=À±—–ß;£™´ñSâ*g§”ïaið‘Jå~™ÓÞ ß³Õ¢»8x埒²52>AÊb&-÷\7´éÄù€T˜,w;3{ï˜k…à¹ÄqÀ«œ{€\ ˆ¾[´¨јr &Úé„Ívˆ±8†¿]|¬ņ4I×pÞS1ÈÖz‰#Ìv‡G!YNògñ:màTz¢Ý1ô©^O=~ë|5Bã™ç•¼µõ•bÆ@úÕS¬ÈŒ#¬zünrŸ û” Z²•èðV"ÁHÚý©wÝ €7¼Ìu1hÑa3Éä û f$o¿É ™Ú›ÝçnpÒ3äÌ3†Í§,Äï]$‰/pê †«À¼¸e9­Æê_C]žƒ·ý·frÁN«, E=›Çq -‰öŒ:aÏ¿±í&£Í:-} 84‘ÿ eƒQÑeëSsuiA ³g㟥ú£?ÿ ʼn*”“÷aühe:ÊWa@ÒÞk±eØ] F Ô—r.åä˜ @ö¥ªZoÐýYL·¥S²G/‡ñ <~*ZÆ´è>JlòàÛÆ½ÿ 窘ìGN¢:I®KšJp/`íIÁÀõ#Ä-€ö­šµŒoF4|ÆQØÆ@Ì|£Ô…¢À{9˜è½Üó›€ôYÒÎYsið;ís¤€à²ˆ‚4qÉVŒI$ ‰"° æµ8cXGjœˏ¡Aâý•ËÜ¢ûï e·çLx']á"oÅÎê3¯Ç—¹”ó0nå‚âg{Œñ> S´˜îè°g238‚ãköÝfÚd´6Ò€;ò÷±¢™¼›º ¢Æ'¥Ðx'e¬ç ]bÈÆV¢ó‹kýBO ðÊâ$Ÿ!×T 3Mýמ žìٍàÌü‘8÷€àæØ8æ©6‰©L´«…oãpð„~Çk‰!ñ;‹”ÛžÍ àž±z Ÿôû øŸÝužÏ;ÿ #|u6™Þ¬ÚˆÐõA4¶â|ôl|Ê2ŽÇ¤ÝÅÇY.<#Aí.k§hóF‚”Y; M½Ö4hŸ4&›­¿tès´%FìL¥£Ãk‰ÇT¤haÁ¤ÚxfÉ`ÑìË›>i 3t‚:,–+^÷´–{Û–Nxi"x‘Ûg î¨>¥Õ܁ùZH,2Û“:8xÊ¢Çí9.É-Ìâã-=çjwµS˜dütžçwýGòú®®ûº_ˆýx$–¡ãøO EÚÛÏ÷R„×w+3£Á£öUMyR²¹âŒ°š›¸Ñãò9§Ó_Dl+Ùßc›úšGÅÌc†Ž!Ko=¶.‘Îÿ c²(2®V mª.ÿ ¹B›¹å ù„öŸSV>™ü¯$y:G¢Z×àøúdî¹û­·ýÇ´:•c LÍõi_‹ö+ÎæGÊè>OŠ•äž´§Þ{X}¨1ÚTc›»Qþ•êô°t¿OP?eæ~É{5]•ÙR£r5†nZ\ã@ &îJõ ¾àC°þV>fé¥/ü5ñÊIº_é5 ;e­h<@ Ä&æÃëE%;X,ÒãÆÞ`Oò¦kŸm#˜!ÀyÄ¢| óLšò¥Ä` ¶R=|ÈCâh5ò3DˆïF†ðÒ#ÅìÛœ?¸yhBãœí ZxßÎÄhºRK„`Þödvײ™ÀÈÑÒgŒuY w³%†ƒÓzõ ÖÏp‚dH®¦A´ù§»ÓÇMæ~)ˆð‡û:ù&Ä •vGD´À n ݇¼Ö8Fö óáà£~Ë¥x`oK|Ä?fxiØü%pìR>éò+Û±éÎ>núlFŤ'tq8LZÏvÃ?„¡ß±È⽆¯³íü@x|PöUäèØã¡ð‚ŒAìÏ"vÍwóŸÍ{ ý0.z È•Ö{,N¡£¡ŸKÕÙž>Ýœþ ÍÀ°<×EA!Å‚D™IúOÍ¡>ôG}Â` ÍßkÜL™Ž Þð™ {IøF²¹òQ3&!ÃÂÞz.d&Ï-sH¸,Ôõ˜ŽP€ 77ˆÝ¼ÊëÜw =cÕ Ú,ØÐ5ÎYÐ)ì´öœgŒ[¤ßv㙑8心>h]§µháYš£²ºÑ.{Ï7Sð•?´~×SÃKýJÛ˜ ™Íäiúu<µX¶1õ^kâçIÑ£sZ4h>j*ÔšD:4­¿_ ÷¸ Õxæÿ ¸?Mù _•­ÊÐ ä ÷ý ÑwL œ­ïnTkÛUÍN©ë:¦fV ¶ÜÔÜMªÅâA½–¿R×TXš-%iTÊT•‡Ù‚JôϐZxWÑè‰f‰òG º ×Õû2aZ7OU3[“×AT–ÞŒ…-‘¤”Ì ì&(ˆ¿­•ƒkï’:ðY¦W‘ Å)“†‘˜³Åtcø˜ñTÂwÚÇ4|üLÇªí–v- qˆèU qPE.†â‘˜µ Æ,ÐÅs]8¾„oúÑ i>ÜxxÈó)ƒ ´æÁâØ$À‰vžŸf$Ž |ãw;ÀÁIJ»b` {¦Ó¤Ú$©YÀ‘n@Óïž«9J¼êG m¤ ܯ¹ÌW4€ÐÒÅÛ‡#褕Ÿn-?í|с¥÷Ú¹¬'´ÞÜ9ÓK `hê£SÄSà?7—Wí_´…óB›»:=Ãïq`<8ñÓŒÑlú2d¬ê³£hÖ[l|$vÝro~'R®‰§°ñmY ͧäP |PUª¹·:3Œ[Û{Xÿ ºâ@‚W–Äé u‚ ¯´*=íή.pûÒdt @G‰¬ s¸ ëÉücr ÞæÑ¨Ê@>¤¢Ö±. Þ'¯°ÌME[YéïĵÂCå½ Ué©Áû'Ê9%eÔðNU”ë‘ÌsD3/®+UI˜9h.WC”빓$#:pz:YÓ ¿xž* ³$Í +$kñAŠ‹†¢ Uê>¸)_š¬÷©ßAÂÔb9ÇU ¯¾á•9¯ÏÏ÷O÷¼¼Fähal1‰3Ì[Ïr•´UCksNÐ] R‘¸¥H+§Šé†c©vÖÞ0iÓ76s†î!§=ß ¼~Ô'°Ãmäoäš³ªøi1úÉ)³yV8 CLÄØÁ‘WYïi€H6ÖÑiámø^ÈY´°Ñ7¥Û*—Ñ©L«Qƒï—Ùrÿ ›£Ð*š¸ˆL©ˆ$ˆ ÷¾D§9È®«qbqC)–ˆïv´çñsÑVT­Ø, <àïºÀO«Jý·õ àfPìð .wFšir´þ’2_Y *Æ€x\« ì€9š@ Ž|F⇥ˆkZ@hÖÄ0t¿-<“‹qµ¾*ZL¤Ú)&BJpÓF5=$„at*Zš$’ÑtdûÝRI1 2މ$€$I$#‰SÞ’Hë¬ï;Á$¡t$’`<(ñÇt)$‡Ð.Êf¢X’Kt=Éé$‚ˆªè¢oÝëòI%Rgcª÷ŠyI%¡‰ÿ !ñ)´õ $¤ Ô’IIGÿÙ (il $ dZddlZddlZddlZddlmZddlmZddlm Z ddlm Z ddlm Z e dZee d zZe d ZeezZee d z Zee d z Zee d ze d z ZeezZee dzZeezZee dz ZddhZeezZdZdZejdejejzZ Gdde!Z"Gdde"Z#Gdde"Z$Gdde"Z%Gdde"Z&Gdd e#Z'Gd!d"e"Z(Gd#d$e"Z)Gd%d&e"Z*Gd'd(e"Z+Gd)d*e+Z,Gd+d,e#Z-Gd-d.e"Z.Gd/d0e"Z/Gd1d2e"Z0Gd3d4e"Z1Gd5d6e"Z2Gd7d8e"Z3Gd9d:e"Z4Gd;de"Z6Gd?d@e"Z7GdAdBe"Z8GdCdDe"Z9GdEdFe"Z:GdGdHe"Z;GdIdJe"Z<GdKdLe"Z=GdMdNe%Z>GdOdPe"Z?GdQdRe"Z@GdSdTe"ZAGdUdVe"ZBGdWdXeBZCGdYdZe"ZDGd[d\e"ZEGd]d^e"ZFGd_d`e"ZGGdadbe"ZHGdcddeHZIGdedfeHZJGdgdhe"ZKGdidje"ZLGdkdle"ZMGdmdneMZNGdodpeNZOGdqdre"ZPGdsdteQZRGdudveRZSGdwdxeRZTGdydzeSZUGd{d|e jVZWeTd d}ZXeTd~dZYdeY_ZdeY_[eTddZ\ejd]d^ej_Z`ejd]ejad^ejbZcejdjdZeejd]ejad^ejbZfejd]ejad^ejbZgejd]ejad^ejbZhdZidZjdZkdZldZmdZndZodZpdZqdZrdZsdZtdZudZvdZwdZxdZydZzdZ{dZ|dZ}dZ~dZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdS)alHeader value parser implementing various email-related RFC parsing rules. The parsing methods defined in this module implement various email related parsing rules. Principal among them is RFC 5322, which is the followon to RFC 2822 and primarily a clarification of the former. It also implements RFC 2047 encoded word decoding. RFC 5322 goes to considerable trouble to maintain backward compatibility with RFC 822 in the parse phase, while cleaning up the structure on the generation phase. This parser supports correct RFC 5322 generation by tagging white space as folding white space only when folding is allowed in the non-obsolete rule sets. Actually, the parser is even more generous when accepting input than RFC 5322 mandates, following the spirit of Postel's Law, which RFC 5322 encourages. Where possible deviations from the standard are annotated on the 'defects' attribute of tokens that deviate. The general structure of the parser follows RFC 5322, and uses its terminology where there is a direct correspondence. Where the implementation requires a somewhat different structure than that used by the formal grammar, new terms that mimic the closest existing terms are used. Thus, it really helps to have a copy of RFC 5322 handy when studying this code. Input to the parser is a string that has already been unfolded according to RFC 5322 rules. According to the RFC this unfolding is the very first step, and this parser leaves the unfolding step to a higher level message parser, which will have already detected the line breaks that need unfolding while determining the beginning and end of each header. The output of the parser is a TokenList object, which is a list subclass. A TokenList is a recursive data structure. The terminal nodes of the structure are Terminal objects, which are subclasses of str. These do not correspond directly to terminal objects in the formal grammar, but are instead more practical higher level combinations of true terminals. All TokenList and Terminal objects have a 'value' attribute, which produces the semantically meaningful value of that part of the parse subtree. The value of all whitespace tokens (no matter how many sub-tokens they may contain) is a single space, as per the RFC rules. This includes 'CFWS', which is herein included in the general class of whitespace tokens. There is one exception to the rule that whitespace tokens are collapsed into single spaces in values: in the value of a 'bare-quoted-string' (a quoted-string with no leading or trailing whitespace), any whitespace that appeared between the quotation marks is preserved in the returned value. Note that in all Terminal strings quoted pairs are turned into their unquoted values. All TokenList and Terminal objects also have a string value, which attempts to be a "canonical" representation of the RFC-compliant form of the substring that produced the parsed subtree, including minimal use of quoted pair quoting. Whitespace runs are not collapsed. Comment tokens also have a 'content' attribute providing the string found between the parens (including any nested comments) with whitespace preserved. All TokenList and Terminal objects have a 'defects' attribute which is a possibly empty list all of the defects found while creating the token. Defects may appear on any token in the tree, and a composite list of all defects in the subtree is available through the 'all_defects' attribute of any node. (For Terminal notes x.defects == x.all_defects.) Each object in a parse tree is called a 'token', and each has a 'token_type' attribute that gives the name from the RFC 5322 grammar that it represents. Not all RFC 5322 nodes are produced, and there is one non-RFC 5322 node that may be produced: 'ptext'. A 'ptext' is a string of printable ascii characters. It is returned in place of lists of (ctext/quoted-pair) and (qtext/quoted-pair). XXX: provide complete list of token types. N) hexdigits) itemgetter)_encoded_words)errors)utilsz (z ()<>@,:;.\"[].z."(z/?=z*'%%  ct|ddddddS)z:Escape parenthesis and backslash for use within a comment.\\\r\()\)strreplacevalues 1/usr/lib/python3.11/email/_header_value_parser.pymake_parenthesis_pairsrbs= u::  dF + + e  WWS%001c|dt|ddddzdzS)N"rrz\"rrs r quote_stringrhs8 s5zz!!$//77UCC CC GGrz =\? # literal =? [^?]* # charset \? # literal ? [qQbB] # literal 'q' or 'b', case insensitive \? # literal ? .*? # encoded word \?= # literal ?= ceZdZdZdZdZfdZdZfdZe dZ e dZ dZ e d Z e d Zd Zdd ZddZddZxZS) TokenListNTcHtj|i|g|_dSN)super__init__defects)selfargskw __class__s rr#zTokenList.__init__s*$%"%%% rc@dd|DS)Nc34K|]}t|VdSr!r.0xs r z$TokenList.__str__..(,,!s1vv,,,,,,rjoinr%s r__str__zTokenList.__str__s#ww,,t,,,,,,rcd|jjtSNz{}({})formatr(__name__r"__repr__r%r(s rr;zTokenList.__repr__s3t~6"WW--//11 1rc@dd|DS)Nr*c32K|]}|j |jVdSr!rr-s rr0z"TokenList.value..s+8818qw888888rr2r4s rrzTokenList.values#ww88888888rc@td|D|jS)Nc3$K|] }|jV dSr!) all_defectsr-s rr0z(TokenList.all_defects..s$00aAM000000r)sumr$r4s rrAzTokenList.all_defectss#004000$,???rc6|dSNr)startswith_fwsr4s rrEzTokenList.startswith_fwssAw%%'''rc4td|DS)zATrue if all top level tokens of this part may be RFC2047 encoded.c3$K|] }|jV dSr!) as_ew_allowed)r.parts rr0z*TokenList.as_ew_allowed..s%77$4%777777r)allr4s rrHzTokenList.as_ew_alloweds!77$777777rcHg}|D]}||j|Sr!)extendcomments)r%rMtokens rrMzTokenList.commentss2 , ,E OOEN + + + +rc$t||S)Npolicy)_refold_parse_treer%rQs rfoldzTokenList.folds!$v6666rr*cLt||dS)Nindent)printppstrr%rWs rpprintzTokenList.pprints$ djjj''(((((rcTd||S)Nr rV)r3_pprZs rrYzTokenList.ppstrs"yy00111rc#nKd||jj|jV|D]K}t |ds|d|zV-||dzEd{VL|jrd|j}nd}d||VdS)Nz{}{}/{}(r]z* !! invalid element in token list: {!r}z z Defects: {}r*z{}){})r9r(r: token_typehasattrr]r$)r%rWrNextras rr]z TokenList._pps  N # O    4 4E5%(( 4!55;VE]]CDDDD!99VF]3333333333 < "))$,77EEEnnVU+++++++rr*)r: __module__ __qualname__r_syntactic_breakew_combine_allowedr#r5r;propertyrrArErHrMrTr[rYr] __classcell__r(s@rrr{s9JO---1111199X9@@X@(((88X8X 777))))2222,,,,,,,,rrc:eZdZedZedZdS)WhiteSpaceTokenListcdSN r4s rrzWhiteSpaceTokenList.valuesrcd|DS)Nc2g|]}|jdk |jS)comment)r_contentr-s r z0WhiteSpaceTokenList.comments..s&CCCa1<+B+B +B+B+Brror4s rrMzWhiteSpaceTokenList.commentssCC4CCCCrN)r:rcrdrgrrMrorrrkrksM XDDXDDDrrkceZdZdZdS)UnstructuredTokenList unstructuredNr:rcrdr_rorrrwrwsJJJrrwceZdZdZdS)PhrasephraseNryrorrr{r{JJJrr{ceZdZdZdS)WordwordNryrorrrrJJJrrceZdZdZdS)CFWSListcfwsNryrorrrrrrrceZdZdZdS)AtomatomNryrorrrrrrrceZdZdZdZdS)TokenrNFN)r:rcrdr_ encode_as_ewrorrrrsJLLLrrceZdZdZdZdZdZdS) EncodedWord encoded-wordN)r:rcrdr_ctecharsetlangrorrrrs"J CG DDDrrcTeZdZdZedZedZedZdS) QuotedString quoted-stringc8|D]}|jdkr |jcSdSNbare-quoted-stringr_rr%r/s rrtzQuotedString.contents9  A|333w4  rcg}|D]J}|jdkr#|t|0||jKd|S)Nrr*)r_appendrrr3)r%resr/s r quoted_valuezQuotedString.quoted_valuesf $ $A|333 3q66"""" 17####wws||rc8|D]}|jdkr |jcSdSrrr%rNs rstripped_valuezQuotedString.stripped_values= # #E#777{"""8 # #rN)r:rcrdr_rgrtrrrorrrrsh J X X##X###rrc.eZdZdZdZedZdS)BareQuotedStringrcZtdd|DS)Nr*c34K|]}t|VdSr!r,r-s rr0z+BareQuotedString.__str__..s(#9#9qCFF#9#9#9#9#9#9r)rr3r4s rr5zBareQuotedString.__str__s+BGG#9#9D#9#9#999:::rc@dd|DS)Nr*c34K|]}t|VdSr!r,r-s rr0z)BareQuotedString.value.. r1rr2r4s rrzBareQuotedString.value #ww,,t,,,,,,rN)r:rcrdr_r5rgrrorrrrsC%J;;;--X---rrcJeZdZdZdZdZedZedZdS)CommentrscldtdgfdDdgggS)Nr*rc:g|]}|Sro)quote)r.r/r%s rruz#Comment.__str__..s#999qTZZ]]999rr)r3rBr4s`rr5zComment.__str__sPwws E9999D999 E " ##$$ $rc|jdkrt|St|ddddddS)Nrsrrrrrr)r_rr)r%rs rrz Comment.quotesc  y ( (u:: 5zz!!$//77"%u...5g"%u/./. .rc@dd|DS)Nr*c34K|]}t|VdSr!r,r-s rr0z"Comment.content..#r1rr2r4s rrtzComment.content!rrc|jgSr!)rtr4s rrMzComment.comments%s  ~rN) r:rcrdr_r5rrgrtrMrorrrrsmJ$$$...--X-XrrcTeZdZdZedZedZedZdS) AddressListz address-listcd|DS)Nc(g|]}|jdk |S)addressr_r-s rruz)AddressList.addresses../$;;;a1<#:#:#:#:#:rror4s r addresseszAddressList.addresses-;;4;;;;rc6td|DgS)Nc3:K|]}|jdk |jVdSrNr_ mailboxesr-s rr0z(AddressList.mailboxes..3s<>>Q\9%<%<K%<%<%<%<>>rrBr4s rrzAddressList.mailboxes16>>!>>>?ACC Crc6td|DgS)Nc3:K|]}|jdk |jVdSrr_ all_mailboxesr-s rr0z,AddressList.all_mailboxes..8s<>>Q\9%<%<O%<%<%<%<>>rrr4s rrzAddressList.all_mailboxes6rrN)r:rcrdr_rgrrrrorrrr)spJ <<X<CCXCCCXCCCrrcTeZdZdZedZedZedZdS)AddressrcB|djdkr |djSdS)Nrgroupr_ display_namer4s rrzAddress.display_name@s) 7  ( (7' ' ) (rcv|djdkr |dgS|djdkrgS|djSNrmailboxinvalid-mailboxrr4s rrzAddress.mailboxesEsE 7  * *G9  !W #4 4 4IAw  rc|djdkr |dgS|djdkr |dgS|djSrrr4s rrzAddress.all_mailboxesMsL 7  * *G9  !W #4 4 4G9 Aw$$rN)r:rcrdr_rgrrrrorrrr<shJ ((X(!!X!%%X%%%rrc>eZdZdZedZedZdS) MailboxList mailbox-listcd|DS)Nc(g|]}|jdk |S)rrr-s rruz)MailboxList.mailboxes..[rrror4s rrzMailboxList.mailboxesYrrcd|DS)Nc$g|] }|jdv |S))rrrr-s rruz-MailboxList.all_mailboxes.._s/???a|======rror4s rrzMailboxList.all_mailboxes]s"??4??? ?rNr:rcrdr_rgrrrorrrrUsMJ <<X<??X???rrc>eZdZdZedZedZdS) GroupList group-listcF|r|djdkrgS|djSNrrrr4s rrzGroupList.mailboxesgs- tAw)^;;IAw  rcF|r|djdkrgS|djSrrr4s rrzGroupList.all_mailboxesms- tAw)^;;IAw$$rNrrorrrrcsMJ !!X! %%X%%%rrcTeZdZdZedZedZedZdS)GrouprcB|djdkrgS|djSNrrr4s rrzGroup.mailboxesxs& 7  - -IAw  rcB|djdkrgS|djSrrr4s rrzGroup.all_mailboxes~s& 7  - -IAw$$rc|djSrD)rr4s rrzGroup.display_namesAw##rN)r:rcrdr_rgrrrrorrrrtshJ !!X! %%X% $$X$$$rrceZdZdZedZedZedZedZedZ dS)NameAddr name-addrcFt|dkrdS|djSNr)lenrr4s rrzNameAddr.display_names# t99>>4Aw##rc|djSN local_partr4s rrzNameAddr.local_partsBx""rc|djSrdomainr4s rrzNameAddr.domainsBxrc|djSr)router4s rrzNameAddr.routesBx~rc|djSr addr_specr4s rrzNameAddr.addr_specsBx!!rN r:rcrdr_rgrrrrrrorrrrsJ $$X$ ##X#XX""X"""rrcjeZdZdZedZedZedZedZdS) AngleAddrz angle-addrc8|D]}|jdkr |jcSdSN addr-spec)r_rrs rrzAngleAddr.local_parts; $ $A|{**|###+ $ $rc8|D]}|jdkr |jcSdSrr_rrs rrzAngleAddr.domains8  A|{**x+  rc8|D]}|jdkr |jcSdS)N obs-route)r_domainsrs rrzAngleAddr.routes; ! !A|{**y   + ! !rc|D];}|jdkr.|jr |jcSt|j|jzcS)r_rrrrs rrzAngleAddr.addr_specs`  A|{**<D;&&&' 55 CCCC + 4rN) r:rcrdr_rgrrrrrorrrrsJ $$X$   X !!X! Xrrc(eZdZdZedZdS)ObsRoutercd|DS)Nc2g|]}|jdk |jSrrr-s rruz$ObsRoute.domains..s&CCCQ!,(*B*B*B*B*Brror4s rrzObsRoute.domainssCC$CCCCrN)r:rcrdr_rgrrorrrrs7J DDXDDDrrceZdZdZedZedZedZedZedZ dS)MailboxrcB|djdkr |djSdSNrrrr4s rrzMailbox.display_names) 7  , ,7' ' - ,rc|djSrDrr4s rrzMailbox.local_partAw!!rc|djSrDrr4s rrzMailbox.domainsAw~rcB|djdkr |djSdSr )r_rr4s rrz Mailbox.routes( 7  , ,7=  - ,rc|djSrDrr4s rrzMailbox.addr_specsAw  rNrrorrr r sJ ((X(""X"X!!X!!!X!!!rr c8eZdZdZedZexZxZxZZ dS)InvalidMailboxrcdSr!ror4s rrzInvalidMailbox.display_nametrNrrorrrrsB"J X/;:J::%)))rrc6eZdZdZdZefdZxZS)DomainrFctdtjSNr*r3r"rsplitr<s rrz Domain.domain'wwuww}**,,---r)r:rcrdr_rHrgrrhris@rrrsLJM ....X.....rrceZdZdZdS)DotAtomdot-atomNryrorrrrsJJJrrceZdZdZdZdS) DotAtomTextz dot-atom-textTNr:rcrdr_rHrorrr r s JMMMrr ceZdZdZdZdS) NoFoldLiteralzno-fold-literalFNr!rorrr#r#s"JMMMrr#cneZdZdZdZedZedZedZedZ dS)AddrSpecrFc|djSrDrr4s rrzAddrSpec.local_partr rcFt|dkrdS|djS)Nr)rrr4s rrzAddrSpec.domains" t99q==4Bxrct|dkr |djS|dj|djz|djzS)Nr(rrr)rrrstriplstripr4s rrzAddrSpec.valuesW t99q==7= Aw}##%%d1gm3DGM4H4H4J4JJJrct|j}t|t|tz krt |j}n|j}|j |dz|jzS|S)N@)setrr DOT_ATOM_ENDSrr)r%namesetlps rrzAddrSpec.addr_spec"sedo&& w<<#gm344 4 4do..BBB ; "8dk) ) rN) r:rcrdr_rHrgrrrrrorrr%r% sJM ""X"X KKXK Xrr%ceZdZdZdZdS) ObsLocalPartzobs-local-partFNr!rorrr3r3.s!JMMMrr3cLeZdZdZdZedZefdZxZS) DisplayNamez display-nameFct|}t|dkr|jS|djdkr|dn7|ddjdkr t|ddd|d<|djdkr|n7|ddjdkr t|ddd|d<|jS)Nrrrr)rrrr_pop)r%rs rrzDisplayName.display_name9soo s88q==9  q6  & & GGAJJJJ1vay#v--"3q6!"":..A r7  ' ' GGIIII2wr{%//#CGCRCL11Byrctd}|jrd}n|D]}|jdkrd}t|dkrt|rrdx}}|djdks|ddjdkrd}|djdks|ddjdkrd}|t|jz|zSt jS) NFTrrr*rrnr)r$r_rrrr"r)r%rr/prepostr(s rrzDisplayName.valueJs < !EE ! !>e>OC$Aw!6))T!WQZ-BF-J-JBx"F**d2hrl.Ev.M.M|D$5666t; ;77= r) r:rcrdr_rfrgrrrhris@rr5r54shJ X !!!!X!!!!!rr5cBeZdZdZdZedZedZdS) LocalPartz local-partFcX|djdkr |djS|djS)Nrr)r_rrr4s rrzLocalPart.valuecs- 7  0 07' '7= rc tg}t}d}|dtgzD]}|jdkr|r6|jdkr+|djdkrt|dd|d<t|t}|rG|jdkr<|djdkr+|t|ddn|||d}|}t|dd}|jS)NFrrdotrr)DOTr_r isinstancerr)r%rlast last_is_tltokis_tls rrzLocalPart.local_partjse 7cU?  C~'' /s~66H'611#D"I..BsI..E $/U22F%// 9SW--.... 3r7DJJAbD ""yrN)r:rcrdr_rHrgrrrorrr<r<^sRJM !!X! Xrr<cLeZdZdZdZefdZedZxZS) DomainLiteralzdomain-literalFctdtjSrrr<s rrzDomainLiteral.domainrrc8|D]}|jdkr |jcSdS)Nptextrrs ripzDomainLiteral.ips8  A|w&&w'  r) r:rcrdr_rHrgrrKrhris@rrGrGsg!JM ....X.XrrGceZdZdZdZdZdS) MIMEVersionz mime-versionN)r:rcrdr_majorminorrorrrMrMsJ E EEErrMcJeZdZdZdZdZdZedZedZ dS) Parameter parameterFus-asciic.|jr |djndSr) sectionednumberr4s rsection_numberzParameter.section_numbers"&6tAw~~Q6rc|D]N}|jdkr |jcS|jdkr-|D]*}|jdkr|D]}|jdkr |jcccS+OdS)Nrrrr*)r_rrs r param_valuezParameter.param_values < ''))D6!!!t 4L  !5u = > > > >!<<>>3 3 KD%5jmm444E(1+K!)G' &CJJNN8A;!##!HQK'..v/IH0J0JKKK!"1"IEKA).! *! *%!Q&&!>I ,,V-GI.K.KLLL  ,,V-GF.H.HIIIQ)>RR & = =e D DP$)LL:K$L$LEE +-?@PPP %*LL=N$O$OEEE P !077R!M001N1P1PQQQ.PPP!' 4 4UY 4 O O P ""5))))GGK((E+    g3 3 s$I&"G99'H#"H#&+JJc g}|jD]S\}}|r7|d|t|>||Td|}|rd|zndS)N{}={}z; rnr*)rrr9rr3)r%rrrs rr5zMimeParameters.__str__$s; $ $KD% $ gnnT<3F3FGGHHHH d####6""%-sV||2-rN)r:rcrdr_rergrr5rorrrlrlsJ"JO CCXCJ.....rrlc(eZdZdZedZdS)ParameterizedHeaderValueFcRt|D]}|jdkr |jcSiS)Nrm)reversedr_rrs rrzParameterizedHeaderValue.params5s>d^^ $ $E#444|###5 rN)r:rcrdrergrrorrrr/s4O XrrceZdZdZdZdZdZdS) ContentTypez content-typeFtextplainN)r:rcrdr_rHmaintypesubtyperorrrr=s"JMHGGGrrceZdZdZdZdZdS)ContentDispositionzcontent-dispositionFN)r:rcrdr_rHcontent_dispositionrorrrrDs &JMrrceZdZdZdZdZdS)ContentTransferEncodingzcontent-transfer-encodingF7bitN)r:rcrdr_rHrrorrrrJs,JM CCCrrceZdZdZdZdS) HeaderLabelz header-labelFNr!rorrrrPsJMMMrrceZdZdZdZdZdS)MsgIDzmsg-idFc0t||jzSr!)rlineseprSs rrTz MsgID.foldYs4yy6>))rN)r:rcrdr_rHrTrorrrrUs-JM*****rrceZdZdZdS) MessageIDz message-idNryrorrrr^sJJJrrceZdZdZdS)InvalidMessageIDzinvalid-message-idNryrorrrrbs%JJJrrceZdZdZdS)HeaderheaderNryrorrrrfr}rrc~eZdZdZdZdZfdZfdZdZe dZ d fd Z dZ e d Z d ZxZS) TerminalTcht||}||_g|_|Sr!)r"__new__r_r$)clsrr_r%r(s rrzTerminal.__new__ts-wwsE**$  rcd|jjtSr7r8r<s rr;zTerminal.__repr__zs,t~68H8H8J8JKKKrcNt|jjdz|jzdS)N/)rXr(r:r_r4s rr[zTerminal.pprint}s' dn%+do=>>>>>rc*t|jSr!)listr$r4s rrAzTerminal.all_defectssDL!!!rr*c d||jj|jt |jsdnd|jgS)Nz {}{}/{}({}){}r*z {})r9r(r:r_r"r;r$)r%rWr(s rr]z Terminal._pps_&&  N # O GG    l BBB T\(B(B  rcdSr!ror4s rpop_trailing_wszTerminal.pop_trailing_wsrrcgSr!ror4s rrMzTerminal.commentss rc.t||jfSr!)rr_r4s r__getnewargs__zTerminal.__getnewargs__s4yy$/**rrb)r:rcrdrHrfrerr;r[rgrAr]rrMrrhris@rrrnsMO LLLLL???""X"X+++++++rrc*eZdZedZdZdS)WhiteSpaceTerminalcdSrmror4s rrzWhiteSpaceTerminal.valuerprc$|o|dtvSrDWSPr4s rrEz!WhiteSpaceTerminal.startswith_fwss&Q3&rNr:rcrdrgrrErorrrrs< X'''''rrc*eZdZedZdZdS) ValueTerminalc|Sr!ror4s rrzValueTerminal.values rcdS)NFror4s rrEzValueTerminal.startswith_fwssurNrrorrrrs< Xrrc*eZdZedZdZdS)EWWhiteSpaceTerminalcdSrror4s rrzEWWhiteSpaceTerminal.valuesrrcdSrror4s rr5zEWWhiteSpaceTerminal.__str__srrN)r:rcrdrgrr5rorrrrs< XrrceZdZdZdS)_InvalidEwErrorz1Invalid encoded word found while parsing headers.N)r:rcrd__doc__rorrrrs;;;;rrr?,zlist-separatorFr-zroute-component-markerz([{}]+)r*z[^{}]+z[\x00-\x20\x7F]ct|}|r,|jtj|t j|r.|jtjddSdS)z@If input token contains ASCII non-printables, register a defect.z*Non-ASCII characters found in header tokenN)_non_printable_finderr$rrNonPrintableDefectrr|r})xtextnon_printabless r_validate_xtextrs+511NH V6~FFGGG U##; V: 8:: ; ; ; ; ;;;rclt|d^}}g}d}d}tt|D]D}||dkr |rd}d}nd}|rd}n |||vrn!|||E|dz}d|d||dg|z|fS)akScan printables/quoted-pairs until endchars and return unquoted ptext. This function turns a run of qcontent, ccontent-without-comments, or dtext-with-quoted-printables into a single string by unquoting any quoted printables. It returns the string, the remaining value, and a flag that is True iff there were any quoted printables decoded. rFrTr*N) _wsp_splitterrangerrr3)rendcharsfragment remaindervcharsescapehad_qpposs r_get_ptext_to_endcharsrs)22Hy F F FS]]## C=D    FF c]h & & E hsm$$$$Ag 776??BGGXcdd^$4y$@AA6 IIrc|}t|dt|t|z d}||fS)zFWS = 1*WSP This isn't the RFC definition. We're using fws to represent tokens where folding can be done, but when we are parsing the *un*folding has already been done so we don't need to watch out for CRLF. Nfws)r+rr)rnewvaluers rget_fwsr sF||~~H U# >@@ @ABBioodA..OC) eABBi% 0 7 7 > >@@ @ WWY  F F aq Yq Y #!<<a00yDj4 399;;! &4 ,.. / / / BF GGI  E@'*z$*t2C'D'D$gtWW  !@@@ / 6 6rv > >@@ @@BJBGJg  " 7c>>!$--KE4 IIe    )$22 eW-- %wwy!!  " ?q$$ &4 <>> ? ? ? u9s F--9G&ct}|r|dtvr(t|\}}||:d}|dr t |\}}d}t |dkr?|djdkr.|jtj dd}|r=t |dkr*|d jd krt|dd|d<||#t$rd}Yntj $rYnwxYwt|d^}}|r1t|r|d^}}t%|d }t'|||d |}||S) aOunstructured = (*([FWS] vchar) *WSP) / obs-unstruct obs-unstruct = *((*LF *CR *(obs-utext) *LF *CR)) / FWS) obs-utext = %d0 / obs-NO-WS-CTL / LF / CR obs-NO-WS-CTL is control characters except WSP/CR/LF. So, basically, we have printable runs, plus control characters or nulls in the obsolete syntax, separated by whitespace. Since RFC 2047 uses the obsolete syntax in its specification, but requires whitespace on either side of the encoded words, I can see no reason to need to separate the non-printable-non-whitespace from the printable runs if they occur, so we parse this into xtext tokens separated by WSP tokens. Because an 'unstructured' value must by definition constitute the entire value, this 'get' routine does not return a remaining value, only the parsed TokenList. rTrrrz&missing whitespace before encoded wordFrrrr*)rwrrrrrrr_r$rrurrrrrfc2047_matchersearch partitionrrr3)rrxrNvalid_ewhave_wsrDrrs rget_unstructuredrIs".)**L (# 8s??"5>>LE5    & & &    D ! !  /66 u|$$q((#B'2e;;$,33F4ND5F5FGGG"'5s<00144#B'2nDD+?(,e,5,5 R(##E***%# ! ! ! *    "(q11i  4..s33 4#ood33OC)c7++E""" ""Q (#R s!D D<+D<;D<cpt|d\}}}t|d}t|||fS)actext = This is not the RFC ctext, since we are handling nested comments in comment and unquoting quoted-pairs here. We allow anything except the '()' characters, but if we find any ASCII other than the RFC defined printable ASCII, a NonPrintableDefect is added to the token's defects list. Since quoted pairs are converted to their unquoted values, what is returned is a 'ptext' token. In this case it is a WhiteSpaceTerminal, so it's value is ' '. z()rJ)rrrrrJ_s r get_qp_ctextrs@-UD99OE5! ug . .EE %<rcpt|d\}}}t|d}t|||fS)aoqcontent = qtext / quoted-pair We allow anything except the DQUOTE character, but if we find any ASCII other than the RFC defined printable ASCII, a NonPrintableDefect is added to the token's defects list. Any quoted pairs are converted to their unquoted values, so what is returned is a 'ptext' token. In this case it is a ValueTerminal. rrJ)rrrrs r get_qcontentrs@-UC88OE5! % ) )EE %<rct|}|s'tjd||}|t |d}t |d}t|||fS)zatext = We allow any non-ATOM_ENDS in atext, but add an InvalidATextDefect to the token's defects list if we find non-atext characters. zexpected atext but found '{}'Natext)_non_atom_end_matcherrrr9rrrr)rmrs r get_atextrs e$$A ;% + 2 25 9 9;; ; GGIIE #e**++ E % ) )EE %<rc|ddkr'tjd|t}|dd}|r3|ddkr't |\}}|||r/|ddkr"|dt vrt|\}}n|dddkrd} t|\}}|j tj d d }n'#tj$rt |\}}YnwxYw|rNt|dkr;|d j d kr*|d j dkrt|d d |d <nt |\}}|||r |ddk"|s0|j tj d||fS||ddfS)zbare-quoted-string = DQUOTE *([FWS] qcontent) [FWS] DQUOTE A quoted-string without the leading or trailing white space. Its value is the text between the quote marks, with whitespace preserved and quoted pairs decoded. rrzexpected '"' but found '{}'rNrrFz!encoded word inside quoted stringTrrrrz"end of header inside quoted string)rrr9rrrrrrr$rurr_r)rbare_quoted_stringrNrs rget_bare_quoted_stringrsE Qx3% * 1 1% 8 8:: :)++ !""IE )qS#E** u!!%((( )E!HOO 8s??"5>>LE55 2A2Y$  H 3/66 u"*11&2L73939:::* 3 3 3+E22 uuu 3 7C 233a77&r*5>>*2.9^KK-A*2..7.7&r*(..LE5!!%(((+ )E!HOO, )"))&*D 0+2+2 3 3 3!5(( uQRRy ((sAD!D)(D)c |r3|ddkr'tjd|t}|dd}|r|ddkrv|dtvrt |\}}n1|ddkrt |\}}nt|\}}|||r |ddkv|s0|j tj d||fS||ddfS)zcomment = "(" *([FWS] ccontent) [FWS] ")" ccontent = ctext / quoted-pair / comment We handle nested comments here, and quoted-pair in our qp-ctext routine. rrzexpected '(' but found '{}'rNrzend of header inside comment) rrr9rrr get_commentrrr$ru)rrsrNs rrrs2  9qS% ) 0 0 7 799 9iiG !""IE E!HOO 8s??"5>>LE55 1X__&u--LE55'..LE5u E!HOO v9 * , , - - -~ E!""I rct}|ri|dtvrZ|dtvrt|\}}nt |\}}|||r|dtvZ||fS)z,CFWS = (1*([FWS] comment) [FWS]) / FWS r)r CFWS_LEADERrrrr)rrrNs rget_cfwsrs ::D E!H ++ 8s??"5>>LE55&u--LE5 E E!H ++ ;rcTt}|r6|dtvr't|\}}||t |\}}|||r6|dtvr't|\}}||||fS)zquoted-string = [CFWS] [CFWS] 'bare-quoted-string' is an intermediate class defined by this parser and not by the RFC grammar. It is the quoted string without any attached CFWS. r)rrrrr)r quoted_stringrNs rget_quoted_stringr  s!NNM $q[(( uU###)%00LE5 $q[(( uU### % rcdt}|r6|dtvr't|\}}|||r6|dtvr't jd||dr; t|\}}n9#t j$rt|\}}YnwxYwt|\}}|||r6|dtvr't|\}}||||fS)zPatom = [CFWS] 1*atext [CFWS] An atom could be an rfc2047 encoded word. rzexpected atom but found '{}'r) rrrr ATOM_ENDSrrr9rrr)rrrNs rget_atomr sI 66D q[(( u E :qY&&% * 1 1% 8 8:: : ( ,+E22LE55& , , ,%U++LE555 , !'' uKK q[(( u E ;sB((!C  C ct}|r|dtvr'tjd||ry|dtvrjt |\}}|||r0|ddkr$|t|dd}|r|dtvj|dtur*tjdd|z||fS)z( dot-text = 1*atext *("." 1*atext) rz8expected atom at a start of dot-atom-text but found '{}'r rNrz4expected atom at end of dot-atom-text but found '{}')r r rrr9rrr@)r dot_atom_textrNs rget_dot_atom_textr:s MMM :E!H ))%'++16%==:: : E!HI-- '' uU###  U1X__   % % %!""IE E!HI-- RC%'#VCI..00 0 % rct}|dtvr't|\}}|||dr; t |\}}n9#t j$rt|\}}YnwxYwt|\}}|||r6|dtvr't|\}}||||fS)z dot-atom = [CFWS] dot-atom-text [CFWS] Any place we can have a dot atom, we could instead have an rfc2047 encoded word. rr) rrrrrrrrr)rdot_atomrNs r get_dot_atomrMs yyH Qx; u 0 4+E22LE55& 4 4 4-U33LE555 4 )// u OOE q[(( u U?sA..!BBc`|dtvrt|\}}nd}|stjd|ddkrt |\}}nH|dt vr'tjd|t|\}}||g|dd<||fS)aword = atom / quoted-string Either atom or quoted-string may start with CFWS. We have to peel off this CFWS first to determine which type of word to parse. Afterward we splice the leading CFWS, if any, into the parsed sub-token. If neither an atom or a quoted-string is found before the next special, a HeaderParseError is raised. The token returned is either an Atom or a QuotedString, as appropriate. This means the 'word' level of the formal grammar is not represented in the parse tree; this is because having that extra layer when manipulating the parse tree is more confusing than it is helpful. rNz5Expected 'atom' or 'quoted-string' but found nothing.rz1Expected 'atom' or 'quoted-string' but found '{}')rrrrr SPECIALSr9r )rleaderrNs rget_wordrfs  Qx;   E% CEE E Qx}}(// uu qX  %'77=ve}}FF F  u Hbqb %<rct} t|\}}||nA#tj$r/|jtjdYnwxYw|r |dtvr|ddkrQ|t|jtj d|dd}n t|\}}nd#tj$rR|dtvr?t|\}}|jtj dnYnwxYw|||r|dtv||fS)a phrase = 1*word / obs-phrase obs-phrase = word *(word / "." / CFWS) This means a phrase can be a sequence of words, periods, and CFWS in any order as long as it starts with at least one word. If anything other than words is detected, an ObsoleteHeaderDefect is added to the token's defect list. We also accept a phrase that starts with CFWS followed by a dot; this is registered as an InvalidHeaderDefect, since it is not supported by even the obsolete grammar. zphrase does not start with wordrr zperiod in 'phrase'rNzcomment found without atom) r{rrrrr$ru PHRASE_ENDSr@ObsoleteHeaderDefectrr)rr|rNs r get_phrasersXXF0 u e  "000f8 -// 0 0 0 0 00 !E!HK// 8S== MM#    N ! !&"=$#&#& ' ' '!""IEE ' uu*   8{**#+E??LE5N))&*E4+6+6777777  MM% ! !E!HK//" 5=s"'8;A65A6)C< >@@ @ #E** uu  "    #E??LE55&   Qx4E!H $;$;KKEEE  Hbqb e '%(D..E!HK$?$? 23z??U3J K K  $(@ @ @   % %f&@N'P'P Q Q Q Q   % %f&A>'@'@ A A A& 1 >(((( >>>!!&"@;#=#= > > > > >> u sHA//C?BC9C C CCCF::6G32G3ct}d}|r|ddks|dtvr|ddkrU|r,|jt jd|t d}|dd}|ddkrb|t|dd |dd}|jt jd d}|r=|d jd kr,|jt jd  t|\}}d}n7#tj $r%|dtvrt|\}}YnwxYw|||r|ddk|dtv|djd ks"|djdkr=|djd kr,|jt jd|d jd ks"|d jdkr=|djd kr,|jt jd|jrd|_||fS)z' obs-local-part = word *("." word) Frrr zinvalid repeated '.'TrNmisplaced-specialz/'\' character outside of quoted-string/ccontentrr?zmissing '.' between wordsrz!Invalid leading '.' in local partrz"Invalid trailing '.' in local partr) r3rr$rrrur@rr_rrrr)rr!last_non_ws_was_dotrNs rrrs"^^N %U1Xt^^uQx{'B'B 8s??" -&--f.H*/,/,---  ! !# & & &"& !""IE  1Xt^^  ! !-a0C#E#E F F F!""IE  " ) )&*DB+D+D E E E"'    .nR0;uDD  " ) )&*D++-+- . . . +#E??LE5"'  & + + +Qx{**#E??LE555 + e$$$7 %U1Xt^^uQx{'B'B8 q$-- 1  (& 0 0 1  (% / /%%f&@ /'1'1 2 2 2r%.. 2  )6 1 1 2  )5 0 0%%f&@ 0'2'2 3 3 3=$<! 5  s?E1FFct|d\}}}t|d}|r,|jt jdt |||fS)a dtext = / obs-dtext obs-dtext = obs-NO-WS-CTL / quoted-pair We allow anything except the excluded characters, but if we find any ASCII other than the RFC defined printable ASCII, a NonPrintableDefect is added to the token's defects list. Quoted pairs are converted to their unquoted values, so what is returned is a ptext token, in this case a ValueTerminal. If there were quoted-printables, an ObsoleteHeaderDefect is added to the returned token's defect list. z[]rJz(quoted printable found in domain-literal)rrr$rrrr)rrJrs r get_dtextr'su2%>>E5& % ) )E 9 V8 688 9 9 9E %<rc|rdS|tjd|tdddS)NFz"end of input inside domain-literal]domain-literal-endT)rrrur)rdomain_literals r_check_for_early_dl_endr,s] u&4,..///--ABBCCC 4rcLt}|dtvr't|\}}|||st jd|ddkr't jd||dd}t||r||fS|tdd|dtvr't|\}}||t|\}}||t||r||fS|dtvr't|\}}||t||r||fS|ddkr't jd ||tdd |dd}|r6|dtvr't|\}}||||fS) zB domain-literal = [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS] rzexpected domain-literal[z6expected '[' at start of domain-literal but found '{}'rNzdomain-literal-startr)z4expected ']' at end of domain-literal but found '{}'r*) rGrrrrrr9r,rrrr')rr+rNs rget_domain_literalr/ s6#__N Qx; ue$$$ A%&?@@@ Qx3%'!!'00 0 !""IEun55%u$$--CDDEEE Qx3u~~ ue$$$U##LE5%   un55%u$$ Qx3u~~ ue$$$un55%u$$ Qx3%'!!'00 0--ABBCCC !""IE %q[(( ue$$$ 5  rct}d}|dtvrt|\}}|s'tjd||ddkr5t |\}}||g|dd<||||fS t|\}}n'#tj$rt|\}}YnwxYw|r |ddkrtjd||g|dd<|||r|ddkr|j tj d|dj d kr |d|dd<|rc|ddkrW|tt|d d\}}|||r |ddkW||fS) z] domain = dot-atom / domain-literal / obs-domain obs-domain = atom *("." atom)) Nrzexpected domain but found '{}'r.r-zInvalid Domainr z(domain is not a dot-atom (contains CFWS)rr)rrrrrr9r/rrr r$rr_r@)rrrrNs r get_domainr1Gs XXF F Qx;   <% , 3 3E : :<< < Qx3)%00 u  E"1"I eu}'#E** uu  "''' uuu' 8qS%&6777 Hbqb  MM% !qSf9 688 9 9 9 !9 : - -q F111I !aC MM#   #E!""I..LE5 MM%  !aC 5=sB00!CCct}t|\}}|||r |ddkr0|jt jd||fS|t ddt|dd\}}||||fS)z( addr-spec = local-part "@" domain rr-z#addr-spec local part with no domainaddress-at-symbolrN)r%r"rr$rrurr1)rrrNs r get_addr_specr4ms I!%((LE5 U  E!HOO  !; 1"3"3 4 4 4% ]3(;<<===eABBi((LE5 U e rct}|r|ddks|dtvr|dtvr(t|\}}||n0|ddkr$|t|dd}|r|ddku|dtv|r |ddkr't jd||tt|dd\}}|||r|ddkr|t|dd}|sn|dtvr't|\}}|||ddkrI|tt|dd\}}|||r |ddk|st jd|ddkr't jd ||tdd ||ddfS) z obs-route = obs-domain-list ":" obs-domain-list = *(CFWS / ",") "@" domain *("," [CFWS] ["@" domain]) Returns an obs-route token with the appropriate sub-tokens (that is, there is no obs-domain-list in the parse tree). rrrNr-z(expected obs-route domain but found '{}'z%end of header while parsing obs-route:z4expected ':' marking end of obs-route but found '{}'zend-of-obs-route-marker) rrrr ListSeparatorrrr9RouteComponentMarkerr1r)r obs_routerNs r get_obs_router:}s I U1Xs]]eAh+&=&= 8{ " "#E??LE5   U # # # # 1X__   ] + + +!""IE U1Xs]]eAh+&=&= FE!HOO% 6 = =e D DFF F )***eABBi((LE5 U  $E!HcMM'''abb    8{ " "#E??LE5   U # # # 8s??   1 2 2 2%eABBi00LE5   U # # #  $E!HcMM O%&MNNN Qx3%(''-ve}}66 6 ]3(ABBCCC eABBi rc&t}|dtvr't|\}}|||r |ddkr't jd||tdd|dd}|ddkr]|tdd|jt j d |dd}||fS t|\}}n#tj$r t|\}}|jt j d n:#tj$r(t jd |wxYw||t|\}}YnwxYw|||r|ddkr |dd}n,|jt j d |tdd|r6|dtvr't|\}}||||fS) z angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr obs-angle-addr = [CFWS] "<" obs-route addr-spec ">" [CFWS] rzangle-addr-endznull addr-spec in angle-addrz*obsolete route specification in angle-addrz.expected addr-spec or obs-route but found '{}'z"missing trailing '>' on angle-addr) rrrrrrr9rr$rur4r:r)r angle_addrrNs rget_angle_addrr?s J Qx; u%   @E!HOO% 0 7 7 > >@@ @mC);<<=== !""IE Qx3--=>>???!!&"< *#,#, - - -abb 5   ,$U++ uu  " , , , P(//LE5   % %f&A<'>'> ? ? ? ?& P P P)@GGNNPP P P %   $U++ uuu ,e 3qSabb !!&"< 0#2#2 3 3 3mC)9::;;; !q[(( u%   u s*D$$G4>E32G37F***GGct}t|\}}||dd|jdd|_||fS)z display-name = phrase Because this is simply a name-rule, we don't return a display-name token containing a phrase, but rather a display-name token with the content of the phrase. N)r5rrLr$)rrrNs rget_display_namerAsX==Le$$LE5aaa!!! =+L  rcht}d}|dtvr;t|\}}|s'tjd||ddkr|dt vr'tjd|t|\}}|s'tjd|||g|ddd<d}||t|\}}||g|dd<||||fS)z, name-addr = [display-name] angle-addr Nrz!expected name-addr but found '{}'r<) rrrrrr9rrArr?)r name_addrrrNs r get_name_addrrDsa I F Qx;   D)3::6BBDD D Qx3 8{ " ")3::5AACC C'.. u C)3::5AACC C  "8E!HRaRLF!%((LE5 Hbqb  U e rct} t|\}}nc#tj$rQ t |\}}n:#tj$r(tjd|wxYwYnwxYwt d|jDrd|_| |||fS)z& mailbox = name-addr / addr-spec zexpected mailbox but found '{}'c3JK|]}t|tjVdSr!)rArrur-s rr0zget_mailbox..sC 3 3 a3 4 4 3 3 3 3 3 3rr) r rDrrr4r9anyrAr_r)rrrNs r get_mailboxrHs  iiGA$U++ uu  "AAA A(//LE55& A A A)188??AA A A5A   3 3 % 1 3 3 333/. NN5 E>&#BAB7A==BBc*t}|r|d|vrv|dtvr4|t|dd|dd}n't |\}}|||r |d|vv||fS)z Read everything up to one of the chars in endchars. This is outside the formal grammar. The InvalidMailbox TokenList that is returned acts like a Mailbox, but the data attributes are None. rr$rN)rrrrr)rrinvalid_mailboxrNs rget_invalid_mailboxrLs%&&O *E!HH,, 8{ " "  " "=q1D$F$F G G G!""IEE%e,,LE5  " "5 ) ) ) *E!HH,, E !!rct}|rd|ddkrW t|\}}||n}#tj$rjd}|dt vrt |\}}|r |ddvrB|||jtjdnt|d\}}||g|dd<|||jtj dn|ddkr-|jtjdn^t|d\}}||g|dd<|||jtj dYnwxYw|rm|ddvrc|d}d |_ t|d\}}| ||jtj d|r0|ddkr$|t|d d}|r |ddkW||fS) aJ mailbox-list = (mailbox *("," mailbox)) / obs-mbox-list obs-mbox-list = *([CFWS] ",") mailbox *("," [mailbox / CFWS]) For this routine we go outside the formal grammar in order to improve error handling. We recognize the end of the mailbox list only at the end of the value or at a ';' (the group terminator). This is so that we can turn invalid mailboxes into InvalidMailbox tokens and continue parsing any remaining valid mailboxes. We also allow all mailbox entries to be null, and this condition is handled appropriately at a higher level. r;Nz,;zempty element in mailbox-listzinvalid mailbox in mailbox-listrrrr)rrHrrrrrr$rrLrur_rLr7)r mailbox_listrNrrs rget_mailbox_listrP(s==L (E!HOO 8&u--LE5    & & & && 8 8 8FQx;&& (  <aD 0 0 ''/// (//0K71919::::$7ud#C#CLE5)%+Hbqb  ''... (//0J91;1;<<<<qS$++F,G3-5-56666 35$?? u%!'E"1"I##E***$++F,F5-7-7888/ 82  4U1XT))#2&G!2G .ud;;LE5 NN5 ! ! !  ' '(B1)3)3 4 4 4  U1X__    . . .!""IEQ (E!HOOR  s'A E7GGct}|s0|jtjd||fSd}|r|dt vr~t |\}}|sE|jtjd||||fS|ddkr||||fSt|\}}t|j dkr\|||| ||jtj d||fS||g|dd<||||fS)zg group-list = mailbox-list / CFWS / obs-group-list obs-group-list = 1*([CFWS] ",") [CFWS] zend of header before group-listNrzend of header in group-listrNzgroup-list with empty entries) rr$rrrurrrPrrrLr)r group_listrrNs rget_group_listrSas J !!!&"< -#/#/ 0 0 05  F %q[((   %   % %f&@-'/'/ 0 0 0   f % % %u$ $ 8s??   f % % %u$ $#E**LE5 5 ""     f % % %%   !!&"= +#-#- . . .5   Hbqb e u rct}t|\}}|r |ddkr'tjd||||t dd|dd}|r;|ddkr/|t dd||ddfSt|\}}|||s-|jtj d n3|ddkr'tjd ||t dd|dd}|r6|dtvr't|\}}||||fS) z7 group = display-name ":" [group-list] ";" [CFWS] rr6z8expected ':' at end of group display name but found '{}'zgroup-display-name-terminatorrNrNzgroup-terminatorzend of header in groupz)expected ';' at end of group but found {}) rrArrr9rrrSr$rurr)rrrNs r get_grouprUs GGE#E**LE5 9E!HOO%'**0&--99 9 LL LLs$CDDEEE !""IE  qS ]3(:;;<<<eABBi!%((LE5 LL G V7 $&& ' ' ' ' qS% 7 > >u E EGG G LLs$677888 !""IE q[(( u U %<rc>t} t|\}}nc#tj$rQ t |\}}n:#tj$r(tjd|wxYwYnwxYw||||fS)a address = mailbox / group Note that counter-intuitively, an address can be either a single address or a list of addresses (a group). This is why the returned Address object has a 'mailboxes' attribute which treats a single address as a list of length one. When you need to differentiate between to two cases, extract the single element, which is either a mailbox or a group token. zexpected address but found '{}')rrUrrrHr9r)rrrNs r get_addressrWs"iiGA '' uu  "AAA A&u--LE55& A A A)188??AA A A5A  NN5 E>rIct}|rm t|\}}||n#tj$r}d}|dt vrt |\}}|r |ddkrC|||jtjdnt|d\}}||g|dd<|t|g|jtj dn|ddkr-|jtjdnlt|d\}}||g|dd<|t|g|jtj dYd}~nd}~wwxYw|ru|ddkri|dd}d|_ t|d\}}| ||jtj d|r$|t|d d}|m||fS) a address_list = (address *("," address)) / obs-addr-list obs-addr-list = *([CFWS] ",") address *("," [address / CFWS]) We depart from the formal grammar here by continuing to parse until the end of the input, assuming the input to be entirely composed of an address-list. This is always true in email parsing, and allows us to skip invalid addresses to parse additional valid ones. Nrrz"address-list entry with no contentzinvalid address in address-listzempty element in address-listrrr)rrWrrrrrr$rrLrrur_rLr7)r address_listrNerrrrs rget_address_listr[s==L ( 8&u--LE5    & & & && 8 8 8FQx;&& (  <aC ''/// (//0K<1>1>????$7uc#B#BLE5)%+Hbqb  ''(8(8999 (//0J91;1;<<<<qS$++F,G3-5-56666 35#>> u%!'E"1"I##GUG$4$4555$++F,F5-7-7888/ 82  4U1X__#2&q)G!2G .uc::LE5 NN5 ! ! !  ' '(B1)3)3 4 4 4      . . .!""IEQ (R  s'<G FGGcFt}|s'tjd||ddkr'tjd||t dd|dd}t |\}}|||r |ddkr'tjd ||t dd ||ddfS) z& no-fold-literal = "[" *dtext "]" z'expected no-fold-literal but found '{}'rr.z;expected '[' at the start of no-fold-literal but found '{}'zno-fold-literal-startrNr)z9expected ']' at the end of no-fold-literal but found '{}'zno-fold-literal-end)r#rrr9rrr')rno_fold_literalrNs rget_no_fold_literalr^s1$ooO E% 5 < " [CFWS] id-left = dot-atom-text / obs-id-left id-right = dot-atom-text / no-fold-literal / obs-id-right no-fold-literal = "[" *dtext "]" rr<zexpected msg-id but found '{}'z msg-id-startrNzobsolete id-left in msg-idz4expected dot-atom-text or obs-id-left but found '{}'r-zmsg-id with no id-rightr=z msg-id-endr3zobsolete id-right in msg-idzFexpected dot-atom-text, no-fold-literal or obs-id-right but found '{}'zmissing trailing '>' on msg-id)rrrrrrr9rrrr$rrur^r1)rmsg_idrNes r get_msg_idrbs  WWF q[(( u e D  E  7EE E HK+H>=K>K>J  K  7KK K KKKct} t|\}}|||r?|jt jd|ny#tj$rg}t|}t|}|jt jd|Yd}~nd}~wwxYw|S)z2message-id = "Message-ID:" msg-id CRLF zUnexpected {!r}zInvalid msg-id: {!r}N) rrbrr$rrur9rrr)r message_idrNexs rparse_message_idrfSs J 2!%(( u%     2   % %f&@!((//'1'1 2 2 2  "KKK ''%e,, !!  &'='D'DR'H'H I I K K K K K K K KK s'A99C/AC**C/ct}|s.|jtjd|S|dt vrUt |\}}|||s,|jtjdd}|rM|ddkrA|dt vr2||dz }|dd}|r|ddkr|dt v2|sc|jtjd ||t|d n7t||_ |t|d |r6|dt vr't |\}}|||r |ddkrZ|j ,|jtjd |r#|t|d |S|tdd |dd}|r6|dt vr't |\}}|||s5|j ,|jtjd |Sd}|r5|dt vr&||dz }|dd}|r|dt v&|sc|jtjd ||t|d n7t||_ |t|d |r6|dt vr't |\}}|||rO|jtjd|t|d |S)zE mime-version = [CFWS] 1*digit [CFWS] "." [CFWS] 1*digit [CFWS] z%Missing MIME version number (eg: 1.0)rz0Expected MIME version number but found only CFWSr*r rNz1Expected MIME major version number but found {!r}rdigitsz0Incomplete MIME version; found only major numberzversion-separatorz1Expected MIME minor version number but found {!r}z'Excess non-CFWS text after MIME version)rMr$rrHeaderMissingRequiredValuerrisdigitrur9rintrNrO)r mime_versionrNrhs rparse_mime_versionrmos ==L ##F$E 3%5%5 6 6 6 Qx; uE""" E  ' '(IB)D)D E E E F E!HOOa (C(C%(abb  E!HOOa (C(C >>  =##F$> ? F Fv N N%P%P Q Q QM&'::;;;; [[ M&(;;<<< #q[(( uE""" E!HOO   )  ' '(BB)D)D E E E  ?    eW = = > > > c+>??@@@ !""IE #q[(( uE"""    )  ' '(BB)D)D E E E F E!HK//%(abb  E!HK// >>  =##F$> ? F Fv N N%P%P Q Q QM&'::;;;; [[ M&(;;<<< #q[(( uE""" ;##F$> 5%7%7 8 8 8M%99::: rc2t}|r|ddkrx|dtvr4|t|dd|dd}n't |\}}|||r |ddkx||fS)z Read everything up to the next ';'. This is outside the formal grammar. The InvalidParameter TokenList that is returned acts like a Parameter, but the data attributes are None. rrNr$rN)r\rrrr)rinvalid_parameterrNs rget_invalid_parameterrps)** ,E!HOO 8{ " "  $ $]583F&H&H I I I!""IEE%e,,LE5  $ $U + + + ,E!HOO e ##rct|}|s'tjd||}|t |d}t |d}t|||fS)a8ttext = We allow any non-TOKEN_ENDS in ttext, but add defects to the token's defects list if we find non-ttext characters. We also register defects for *any* non-printables even though the RFC doesn't exclude all of them, because we follow the spirit of RFC 5322. zexpected ttext but found '{}'Nttext)_non_token_end_matcherrrr9rrrr)rrrrs r get_ttextrts u%%A ;% + 2 25 9 9;; ; GGIIE #e**++ E % ) )EE %<rct}|r6|dtvr't|\}}|||r6|dtvr't jd|t|\}}|||r6|dtvr't|\}}||||fS)ztoken = [CFWS] 1*ttext [CFWS] The RFC equivalent of ttext is any US-ASCII chars except space, ctls, or tspecials. We also exclude tabs even though the RFC doesn't. The RFC implies the CFWS but is not explicit about it in the BNF. rexpected token but found '{}') rrrr TOKEN_ENDSrrr9rt)rmtokenrNs r get_tokenrysWWF q[(( u e ;qZ''% + 2 25 9 9;; ;U##LE5 MM% q[(( u e 5=rct|}|s'tjd||}|t |d}t |d}t|||fS)aQattrtext = 1*(any non-ATTRIBUTE_ENDS character) We allow any non-ATTRIBUTE_ENDS in attrtext, but add defects to the token's defects list if we find non-attrtext characters. We also register defects for *any* non-printables even though the RFC doesn't exclude all of them, because we follow the spirit of RFC 5322. z expected attrtext but found {!r}Nrb)_non_attribute_end_matcherrrr9rrrrrrrbs r get_attrtextr}s #5))A >% . 5 5e < <>> >wwyyH #h--.. !EXz22HH U?rct}|r6|dtvr't|\}}|||r6|dtvr't jd|t|\}}|||r6|dtvr't|\}}||||fS)aH [CFWS] 1*attrtext [CFWS] This version of the BNF makes the CFWS explicit, and as usual we use a value terminal for the actual run of characters. The RFC equivalent of attrtext is the token characters, with the subtraction of '*', "'", and '%'. We include tab in the excluded set just as we do for token. rrv) r_rrrATTRIBUTE_ENDSrrr9r}rr`rNs r get_attributer s I  q[(( u ;q^++% + 2 25 9 9;; ;&&LE5 U  q[(( u e rct|}|s'tjd||}|t |d}t |d}t|||fS)zattrtext = 1*(any non-ATTRIBUTE_ENDS character plus '%') This is a special parsing routine so that we get a value that includes % escapes as a single string (which we decode as a single string later). z)expected extended attrtext but found {!r}Nextended-attrtext)#_non_extended_attribute_end_matcherrrr9rrrrr|s rget_extended_attrtextr s ,E22A G% 7 > >u E EGG GwwyyH #h--.. !EX':;;HH U?rct}|r6|dtvr't|\}}|||r6|dtvr't jd|t|\}}|||r6|dtvr't|\}}||||fS)z [CFWS] 1*extended_attrtext [CFWS] This is like the non-extended version except we allow % characters, so that we can pick up an encoded value as a single string. rrv) r_rrrEXTENDED_ATTRIBUTE_ENDSrrr9rrs rget_extended_attributer+ s I  q[(( u ;q444% + 2 25 9 9;; ;(//LE5 U  q[(( u e rct}|r |ddkr'tjd||t dd|dd}|r|ds'tjd|d}|rK|dr1||dz }|dd}|r|d1|dd kr2|d kr,|jtjd t||_ |t |d ||fS) a6 '*' digits The formal BNF is more complicated because leading 0s are not allowed. We check for that and add a defect. We also assume no CFWS is allowed between the '*' and the digits, though the RFC is not crystal clear on that. The caller should already have dealt with leading CFWS. r*zExpected section but found {}zsection-markerrNz$Expected section number but found {}r*0z'section number has an invalid leading 0rh) rfrrr9rrrjr$rurkrV)rrgrhs r get_sectionrA siiG 0E!HOO%&E&L&L(-'/'/00 0 NN=&677888 !""IE @a((**@%'117@@ @ F E!H$$&&%(abb  E!H$$&&ayCFcMMv99 ; ; < < <[[GN NN=22333 E>rct}|stjdd}|dtvrt |\}}|s'tjd||ddkrt |\}}nt|\}}||g|dd<||||fS)z quoted-string / attribute z&Expected value but found end of stringNrz Expected value but found only {}r) rirrrrr9r rr)rvrrNs r get_valuer_ s A P%&NOOO F Qx;   @%'006v@@ @ Qx3(// uu-e44 u Hbqb HHUOOO e8Orc t}t|\}}|||r |ddkrC|jt jd|||fS|ddkr t|\}}d|_||n#tj $rYnwxYw|st j d|ddkr4|tdd|dd }d|_ |dd krt j d |td d |dd }d }|r6|dtvr't|\}}||d }|}|j r|r|dd krt|\}}|j}d}|jdkr4|r|ddkrd}nBt#|\}} | r| ddkrd}n t%|\}} | sd}n#YnxYw|r_|jt jd|||D]} | jdkr g| d d <| }n|}n.d }|jt jd|r|ddkrd }nt)|\}}|j r |jdkrc|r |ddkr)||||r J||}||fS|jt jd|sI|jt jd|||||fSnC|>|D]} | jdkrn| jdk|| | j|_|ddkr't j d||tdd|dd }|rt|ddkrht#|\}}|||j|_|r |ddkr't j d||tdd|dd }|t1} |rr|dt2vrt5|\}}n9|dd krtd d}|dd }nt7|\}}| ||r| }nt)|\}}||||r J||}||fS)aY attribute [section] ["*"] [CFWS] "=" value The CFWS is implied by the RFC but not made explicit in the BNF. This simplified form of the BNF from the RFC is made to conform with the RFC BNF through some extra checks. We do it this way because it makes both error recovery and working with the resulting parse tree easier. rrNz)Parameter contains name ({}) but no valuerTzIncomplete parameterzextended-parameter-markerrN=zParameter not followed by '='parameter-separatorrF'z5Quoted string value for extended parameter is invalidrzZParameter marked as extended but appears to have a quoted string value that is non-encodedzcApparent initial-extended-value but attribute was not marked as extended or was not initial sectionz(Missing required charset/lang delimitersrrbz=Expected RFC2231 char/lang encoding delimiter, but found {!r}zRFC2231-delimiterz;Expected RFC2231 char/lang encoding delimiter, but found {}DQUOTE)rQrrr$rrur9rrUrrrZrrr rrWr}rr_rrrrrirrr) rrrNrrappendtoqstring inner_value semi_validrtrs r get_parameterru s KKE ''LE5 LL E!HOO V79%%+VE]]44 5 5 5e| Qx3 &u--LE5"EO LL    &    D  B)*@AA A 8s?? LLs,GHH I I I!""IE!EN Qx3%&EFFF LLs$9::;;; !""IE F q[(( u UIH ~$<%$ FU1A55 aC OOE " " "$ ''%'''!%<  V7 DEE F F F  V7 688 9 9 9  %<      <#666E7 LJ & & OOA   GEM 8s??)+FFLfUmmUU U c+>??@@@abb   KU1X__'..LE5 OOE " " "EJ KE!HOO-/<??@@@abb  GG Qx3&u~~ uuqS%c844abb +E22 u HHUOOO  '' u OOE% %<s.CCC,IIc"t}|r t|\}}||n#tj$r }d}|dt vrt |\}}|s|||cYd}~S|ddkrD||||jtjdnpt|\}}|r|g|dd<|||jtjd |Yd}~nd}~wwxYw|r|ddkru|d}d|_ t|\}}| ||jtjd ||r-|tdd |d d}||S) a! parameter *( ";" parameter ) That BNF is meant to indicate this routine should only be called after finding and handling the leading ';'. There is no corresponding rule in the formal RFC grammar, but it is more convenient for us for the set of parameters to be treated as its own TokenList. This is 'parse' routine because it consumes the remaining value, but it would never be called to parse a full header. Instead it is called to parse everything after the non-parameter value of a specific MIME header. NrrNzparameter entry with no contentzinvalid parameter {!r}rr]z)parameter with invalid trailing text {!r}rr)rlrrrrrrr$rurpr9r_rLr)rmime_parametersrNrZrrs rparse_mime_parametersr sg%&&O # =(//LE5  " "5 ) ) ) )& = = =FQx;&& (  '&&v...&&&&&&&Qx3%#**6222'..v/I507078888 5U;; u)!'E"1"I&&u---'..v/I,33E::0<0<===# =&  LU1X__$B'E2E 077LE5 LL     # * *6+E;BB5II,K,K L L L    " "=6K#L#L M M M!""IEG #H s"'<E ;EE CEEc|r|ddkrx|dtvr4|t|dd|dd}n't|\}}|||r |ddkx|sdS|tdd|t |dddS)zBDo our best to find the parameters in an invalid MIME header rrNr$rNr)rrrrr) tokenlistrrNs r_find_mime_parametersr7 s $E!HOO 8{ " "   ]585HII J J J!""IEE%e,,LE5   U # # # $E!HOO  ]3(=>>??? *595566666rct}d}|s.|jtjd|S t |\}}nf#tj$rT|jtjd|t|||cYSwxYw|||r |ddkr@|jtjd|rt|||S|j |_ |tdd|dd } t |\}}nf#tj$rT|jtjd |t|||cYSwxYw|||j |_|s|S|dd krU|jtjd ||` |`t|||S|td d |t!|dd |S)z maintype "/" subtype *( ";" parameter ) The maintype and substype are tokens. Theoretically they could be checked against the official IANA list + x-token, but we don't do that. Fz"Missing content type specificationz(Expected content maintype but found {!r}rrzInvalid content typezcontent-type-separatorrNz'Expected content subtype but found {!r}rNz 022 3 3 3  '' uu  " V7 6 = =e D DFF G G GeU+++   LL E!HOO V7 "$$ % % %  0 !% / / / [&&((..00EN LLs$<==>>> !""IE '' uu  " V7 5 < |dr6|ddtvr!|dd}|ddd|d<|S)Nr*rr)lineswsps r_steal_trailing_WSP_if_existsr sS C #r#uRy}33Bim"IcrcNb Jrc|jp tj}|jrdnd}dg}d}d}d}t dd}t |} | rj| d} | |ur|dz}"t| } |sB| jd krt |  }nt |  } | ||} n5#t$r(td | jDrd } nd} d }YnwxYw| jd krt!| ||||r|s| jsd}d}| jr| |dt)|j } |j| vr_t)| |t)|dz kr$t-|}|||dxx| z cc<t1| dst | | z} d}| jrt3| |||| j| }d}d}d}t)| |t)|dz kr|dxx| z cc<| jrWt)| dz|krAt-|}|s| r||| zd}wt1| dsrt | }| jdkr0t9dd gd|Dzt9dd gz}| js|dz }|||| z} | jr|s| d| d }t-|}|s| r||| zn|dxx| z cc<| j|j||jzS)zLReturn string of contents of parse_tree folded according to RFC rules. utf-8rSr*NrFwrap_as_ew_blockedrrJc3JK|]}t|tjVdSr!)rArr}r-s rr0z%_refold_parse_tree.. sC..a!>??......r unknown-8bitTrmrPrrrsrcbg|],}|jdkrtt|dn|-S)rJ)r_rr)r.ps rruz&_refold_parse_tree..7 sP((( //##9!#<#Q>Q=Q  u % % 66s=C/DDcx|B|r@tt|d|d|z}|dd||d<|dtvr]|d}|dd}t|d|kr"|t ||dxx|z cc<d}|dtvr|d}|dd}|t|dn|}|dkrdn|} t| dz} | dz|krt jd |r|t|dz } | | z } | dkr|d ;|d| } tj | | }t|| z }|dkr8| dd} tj | | }t|| z }|dk8|dxx|z cc<|t| d}|r*|d t|d}||dxx|z cc<|r|ndS) aFold string to_encode into lines as encoded word, combining if allowed. Return the new value for last_ew, or None if ew_combine_allowed is False. If there is already an encoded word in the last line of lines (indicated by a non-None value for last_ew) and ew_combine_allowed is true, decode the existing ew, combine it with to_encode, and re-encode. Otherwise, encode to_encode. In either case, split to_encode as necessary so that the encoded segments fit within maxlen. Nrrrr*rSrz3max_line_length is too small to fit an encoded wordrn)r) rrrrrrrrrr) to_encoderrrrfr leading_wsp trailing_wsp new_last_ew encode_as chrome_lenremaining_space text_spaceto_encode_word encoded_wordexcesss rrrO s1 U2Ywxx09< = =?? "Ihwh'b |s l abbM b NNf $ $ LL6u== > > > b [ L} } crcN $+O#eBi...K"j00gIY!#JQ6!!% ACC C ) 3uRy>>1$z1 ?? LL    ";J;/z.)DDD \""_4qjj,CRC0N:niHHHL&&8F qjj b \! c.11223  ) LL   eBi..K+ ), "IIIIII, 6;;$6rc |jD]O\}}|dds|dxxdz cc<|}d} ||d}n-#t$r d}t j|rd}d}nd}YnwxYw|r:tj |d | } d ||| } n#d |t|} t|dt| zd z|kr|ddz| z|d<+t| dz|kr| d| z[d} |dz} |rt|tt| zdzt| z} || dzkrd}|| z dz x}} |d|}tj |d | } t| |krn|d z}F| d || | | d } | d z } ||d}|r|dxxdz cc<|QdS)a>Fold TokenList 'part' into the 'lines' list as mime parameters. Using the decoded list of parameters and values, format them according to the RFC rules, including using RFC2231 encoding if the value cannot be expressed in 'encoding' and/or the parameter+value is too long to fit within 'maxlen'. rrNstrictFTrrprr*)saferz {}*={}''{}rrrnrrz''r(NNz {}*{}*={}{})rr*rcrr{rr|rvrwrr9rrrr)rIrrrqrrr error_handlerencoding_required encoded_valuerrg extra_chromer splitpointmaxcharspartials rrr s{:!:! e Ry!!**3//  "III III  " LL " " " %  ! " " " $ $U++ "( 1 !  "  ="L..B}/66M&&tWmDDDD>>$ U(;(;<>CII % )F 2 2b C$.E"I  YY]f $ $ LLt $ $ $ ~  !TSW%6%66:S=N=NNJa'' $*Z$7!$; ;J   , & 2 2"]!3!<!< }%%11a   LL..g|]<< = = =L qLG*++&E !b S - !I:!:!sA(('BB)rrerrvstringroperatorremailrrrrr.rrrr r/r TSPECIALSrw ASPECIALSrrrrrrcompileVERBOSE MULTILINErrrrkrwr{rrrrrrrrrrrrrrrrr rrrr r#r%r3r5r<rGrMrQr\r_rfrirlrrrrrrrrrrrrrrrrr@r7rHrer8r9r3rrrmatchrfindallrrsr{rrrrrrrrrrrrr r rrrrr"rr'r,r/r1r4r:r?rArDrHrLrPrSrUrWr[r^rbrfrmrprtryr}rrrrrrrrrrrrrRrrrorrrsCCJ ''''''  c%jjCCHHn 3  sN CCHH$ U# E "cc#hh . _ E " S(33s883 t    111 HHH"*Z",  @,@,@,@,@,@,@,@,FDDDDD)DDD     I   Y9"9I )#####9###6 - - - - -| - - -!4CCCCC)CCC&%%%%%i%%%2 ? ? ? ? ?) ? ? ?%%%%% %%%"$$$$$I$$$*"""""y"""6 DDDDDDyDDD!!!!!i!!!6;;;;;Y;;;.....Y...i) I yB9 '!'!'!'!'!&'!'!'!T!!!!! !!!H     I    ) 8%%%%%y%%% ##### ###i     I   S.S.S.S.S.YS.S.S.l     y   *1 i ) *****I***&&&&&y&&&Y(+(+(+(+(+s(+(+(+V''''''''H-<<<<#I$4$4 BIbggj!!""%$%$%%%*'RZ (8(8 BIbggn%%&&)()())).&0bj1A1A BIbgg-..//2121'2'227$;;;JJJ<   ///bAAAF"    ))))))V2      $6   &2   D$$$L%%%N-!-!-!^(%!%!%!N$$$L ' ' ' R,,,\   <*"""$666r###J<:444n&&&,BBBJ8BBBH$$$$&.&.$,<,LLL\222h777 777r<^y7y7y7v?7?7?7BI!I!I!I!I!r