ó
    �®žj,  ã                   óØ  • S r SSKrSSKrSSKJr  SSKJr  SSKJr  \R                  " \
5      rSrSrSrSrSrS	rSrSrSrS
r\\\\\-     4   r " S S\5      rS\S\S\\\4   4S jrS\S\4S jrS\S\S-  4S jr\4S\S\S\4S jjr S\S\4S jr!S\S\\   4S jr"\#" \RH                  \RJ                  \RL                  \RN                  15      r( S\RR                  S\*4S jr+g)uQ  Reader for Apple's IWA (iWork Archive) container format.

Pages, Numbers and Keynote from 2013 onwards store their documents as
``Index/*.iwa`` members inside the package. Apple has never published the
schemas, but the container itself is straightforward and stable:

1. An ``.iwa`` file is a sequence of chunks. Each chunk has a four-byte header â€”
   one compression tag (``0x00`` for Snappy) plus a three-byte little-endian
   payload length â€” followed by that many bytes of **raw** Snappy: no stream
   identifier, no CRC-32C, so a framed Snappy decoder cannot read it.
2. Concatenating the decompressed chunks yields a stream of archives. Each is a
   varint length, a ``TSP.ArchiveInfo`` message carrying an object identifier and
   one or more ``MessageInfo`` descriptors, then the payload bytes each
   descriptor claims.

That is enough to walk the document's object graph without any ``.proto``
definitions: the fields this backend needs are read positionally by
:func:`read_fields`. Only the message *type numbers* are format knowledge, and
those live in the Pages backend rather than here.
é    N)ÚIterator)Ú
NamedTuple)ÚDocumentLoadErroré   é   é   é   i   c                   ó8   • \ rS rSr% Sr\\S'   \\S'   \\S'   Srg)Ú	IWAObjecté7   zBOne archived object: its identifier, message type and raw payload.Ú
identifierÚmessage_typeÚpayload© N)	Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__ÚintÚ__annotations__ÚbytesÚ__static_attributes__r   ó    ÚV/home/mande/repo/quber/.venv/lib/python3.13/site-packages/docling/backend/iwork/iwa.pyr   r   7   s   ‡ ÙLàƒOØÓØ†Nr   r   ÚbufÚposÚreturnc                 ó°   • SnSn U[        U 5      :¼  a  [        S5      eUS:”  a  [        S5      eX   nUS-  nX$S-  U-  -  nUS-  (       d  X!4$ US-  nMR  )	zARead a base-128 varint, returning the value and the new position.r   zTruncated varint in IWA stream.é?   zOverlong varint in IWA stream.r   é   é€   é   )Úlenr   )r   r   ÚresultÚshiftÚbytes        r   Úread_varintr(   ?   sw   € à€FØ€EØ
Ø”#�c“(‹?Ü#Ð$EÓFÐFØ�2‹:Ü#Ð$DÓEÐEØ‰xˆØˆq‰ˆØ˜$‘; 5Ñ(Ñ(ˆØ�d�{Ø�;ÐØ�‰
ˆñ r   c                 óÞ  • 0 nSnU[        U 5      :  aÙ  [        X5      u  p2US-	  US-  pTU[        :X  a  [        X5      u  pbOyU[        :X  a4  [        X5      u  prX'-   [        U 5      :”  a  [	        S5      eXX'-    nX'-  nO;U[
        :X  a  XUS-    US-   p&O%U[        :X  a  XUS-    US-   p&O[	        SU S35      eUR                  U/ 5      R                  U5        U[        U 5      :  a  MÙ  U$ )	aW  Decode a protobuf message into ``{field_number: [values]}``.

Values are ``int`` for varint and fixed-width fields and ``bytes`` for
length-delimited ones, which the caller re-reads as a nested message, a
UTF-8 string or a packed value as the field requires. Groups (wire types 3
and 4) are obsolete and unused by iWork, so they are rejected.
r   é   r#   z%Truncated length-delimited IWA field.é   r   zUnsupported protobuf wire type z in IWA stream.)	r$   r(   Ú_WIRE_VARINTÚ_WIRE_LENGTH_DELIMITEDr   Ú_WIRE_64BITÚ_WIRE_32BITÚ
setdefaultÚappend)r   Úfieldsr   ÚkeyÚfield_noÚ	wire_typeÚvalueÚlengths           r   Úread_fieldsr8   P   s  € ð €FØ
€CØ
”�C“‹.Ü˜sÓ(‰ˆØ! Q™h¨¨d©
�)àœÓ$Ü$ SÓ.‰JˆE�3ØÔ0Ó0Ü% cÓ/‰KˆFØ‰|œc #›hÓ&Ü'Ð(OÓPÐPØ˜c™lÐ+ˆEØ‰M‰CØœ+Ó%Ø 3¨¡7Ð+¨S°1©W‘3Øœ+Ó%Ø 3¨¡7Ð+¨S°1©W‘3ä#Ø1°)°¸OÐLóð ð 	×Ñ˜( BÓ'×.Ñ.¨uÔ5ð) ”�C“�.ð* €Mr   c                 ór   • [        U 5      R                  SS/5      S   n[        U[        5      (       a  U$ S$ )zCRead a ``TSP.Reference``, whose only field is the target object id.r   Nr   )r8   ÚgetÚ
isinstancer   )r   Útargets     r   Úread_referencer=   r   s7   € ä˜Ó×!Ñ! ! d VÓ,¨QÑ/€FÜ ¬×,Ñ,ˆ6Ð6°$Ð6r   ÚblockÚlimitc                 ó<  • [        U S5      u  p#X!:”  a  [        SU SU S35      e[        5       n[        U 5      nX5:  Ga¨  X   nUS-  nUS-  nU[        :X  a†  US-	  nUS:¼  a6  US	-
  n	X9-   U:”  a  [        S
5      e[
        R                  XX9-    S5      nX9-  nUS-  nX8-   U:”  a  [        S5      eX@X3U-    -  nX8-  n[        U5      U:”  a  [        SU S35      eM¤  U[        :X  a.  SUS-	  S-  -   nX5:¼  a  [        S5      eUS-	  S-  X   -  n
US-  nOGU[        :X  a  SOSnUS-	  S-   nX;-   U:”  a  [        S5      e[
        R                  XX;-    S5      n
X;-  nU
S:X  d  U
[        U5      :”  a  [        S5      e[        U5      U
-
  nX¨:¼  a
  XDXÌU-    -  nO([        U5       H  nUR                  XLU-      5        M     [        U5      U:”  a  [        SU S35      eX5:  a  GM¨  [        U5      U:w  a  [        S[        U5       SU S35      e[        U5      $ )uY  Decompress one raw Snappy block, emitting at most ``limit`` bytes.

Implemented here rather than taken from a binding because iWork needs only
the decompressor, and that half of Snappy is small: a varint length preamble
followed by literal and copy elements. Keeping it in Python means the format
does not depend on a compiled wheel staying maintained for future Python
releases, and Pages documents are small enough that the speed difference is
immaterial.

Raw Snappy expands by up to 21.33x â€” a three-byte copy tag emits 64 bytes â€”
and the IWA chunk length field is three bytes wide, so a single chunk may
declare 16.7 MB and expand to roughly 358 MB. ``limit`` is therefore checked
twice: against the declared size before any work happens, and against the
output as it grows, because a hostile block can declare a small size and
then emit far more.
r   zSnappy block declares z bytes, over the z byte limit.r   r*   r   é<   é;   z Truncated Snappy literal length.ÚlittlezTruncated Snappy literal.z#Snappy block emitted more than the z bytes it declared.r   r#   zTruncated Snappy copy offset.r	   r+   z-Snappy copy offset outside the output window.zSnappy block decoded to z bytes, expected Ú.)r(   r   Ú	bytearrayr$   Ú_TAG_LITERALr   Ú
from_bytesÚ_TAG_COPY_1BÚ_TAG_COPY_2BÚranger1   r   )r>   r?   Úexpectedr   ÚoutÚsizeÚtagÚkindr7   ÚextraÚoffsetÚwidthÚstartÚindexs                 r   Údecompress_snappy_blockrU   x   sŒ  € ô"    qÓ)�M€HØÓÜØ$ X JÐ.?À¸wÀlÐSó
ð 	
ô ‹+€CÜˆu‹:€Dà
Œ*Ø‰jˆØˆq‰ˆØ�T‰zˆà”<ÓØ˜A‘XˆFØ˜‹|à ™�Ø‘; Ó%Ü+Ð,NÓOÐOÜŸ™¨°C±KÐ(@À(ÓK�Ø‘�Ø�a‰KˆFØ‰|˜dÓ"Ü'Ð(CÓDÐDØ˜ V™|Ð,Ñ,ˆCØ‰MˆCÜ�3‹x˜(Ó"Ü'Ø9¸(¸ÐCVÐWóð ñ à”<ÓØ˜3 !™8 tÑ+Ñ,ˆFØ‹{Ü'Ð(GÓHÐHØ˜a‘x A‘o¨©Ñ3ˆFØ�1‰H‰Cà¤Ó-‘A°1ˆEØ˜Q‘h !‘^ˆFØ‰{˜TÓ!Ü'Ð(GÓHÐHÜ—^‘^ E°±Ð$<¸hÓGˆFØ‰LˆCà�Q‹;˜&¤3 s£8Ó+Ü#Ð$SÓTÐTä�C“˜6Ñ!ˆØÓØ�u v™~Ð.Ñ.‰Cô ˜vž�Ø—
‘
˜3 u™}Ñ-Ö.ñ 'ô
 ˆs‹8�hÓÜ#Ø5°h°ZÐ?RÐSóð ðm Ž*ôt ˆ3ƒx�8ÓÜØ&¤s¨3£x jÐ0AÀ(ÀÈ1ÐMó
ð 	
ô �‹:Ðr   Údatac                 óÊ  • [        5       nSnU[        U 5      :  a¾  U[        -   [        U 5      :”  a  [        S5      eX   n[        R                  XS-   U[        -    S5      nU[        -  nU[        :w  a  [        SUS S35      eXX$-    n[        U5      U:w  a  [        S5      eX$-  nU[        U[        [        U5      -
  5      -  nU[        U 5      :  a  M¾  [        U5      $ )	z;Concatenate the decompressed chunks of one ``.iwa`` member.r   zTruncated IWA chunk header.r   rC   z(Unsupported IWA chunk compression tag 0xÚ02xrD   zTruncated IWA chunk payload.)
rE   r$   Ú_HEADER_LENr   r   rG   Ú_SNAPPY_TAGrU   Ú_MAX_STREAM_BYTESr   )rV   rL   r   rN   r7   r>   s         r   Ú
decompressr\   Ò   sì   € ä
‹+€CØ
€CØ
”�D“	‹/Ø”Ñœs 4›yÓ(Ü#Ð$AÓBÐBØ‰iˆÜ—‘ ¨1¡W¨s´[Ñ/@Ð AÀ8ÓLˆØŒ{ÑˆØ”+ÓÜ#Ø:¸3¸s¸)À1ÐEóð ð ˜3™<Ð(ˆÜˆu‹:˜ÓÜ#Ð$BÓCÐCØ‰ˆð 	Ô& uÔ.?Ä#ÀcÃ(Ñ.JÓKÑKˆð# ”�D“	�/ô$ �‹:Ðr   c           	   #   óì  #   • [        U 5      nSnU[        U5      :  GaS  [        X5      u  p2X#-   [        U5      :”  a  [        S5      e[	        XX#-    5      nX#-  nUR                  SS/5      S   n[        U[        5      (       d  [        S5      eUR                  S/ 5       H¸  n[        U[        5      (       d  M  [	        U5      nUR                  SS/5      S   nUR                  SS/5      S   n	[        U[        5      (       a  [        U	[        5      (       d  [        S5      eX)-   [        U5      :”  a  [        S5      e[        XXXX)-    5      v •  X)-  nMº     U[        U5      :  a  GMR  g	g	7f)
z@Yield every archived object in one decompressed ``.iwa`` stream.r   z(Truncated TSP.ArchiveInfo in IWA stream.r   z*Malformed object identifier in IWA stream.r   r*   z$Malformed MessageInfo in IWA stream.z'Truncated object payload in IWA stream.N)
r\   r$   r(   r   r8   r:   r;   r   r   r   )
rV   Ústreamr   Úinfo_lenÚinfor   Úmessage_infoÚmessager   Úpayload_lens
             r   Úiter_objectsrd   ë   sY  é € ä˜Ó€FØ
€CØ
”�F“Ô
Ü# FÓ0‰ˆØ‰>œC ›KÓ'Ü#Ð$NÓOÐOÜ˜6¨©Ð7Ó8ˆØ‰ˆà—X‘X˜a ! Ó% aÑ(ˆ
Ü˜*¤c×*Ñ*Ü#Ð$PÓQÐQà ŸH™H Q¨žOˆLÜ˜l¬E×2Ñ2ÙÜ! ,Ó/ˆGØ"Ÿ;™; q¨1¨#Ó.¨qÑ1ˆLØ!Ÿ+™+ a¨!¨Ó-¨aÑ0ˆKÜ˜l¬C×0Ñ0¼
À;ÔPS×8TÑ8TÜ'Ð(NÓOÐOØÑ ¤3 v£;Ó.Ü'Ð(QÓRÐRÜ˜J°fÀ3ÑCTÐ6UÓVÒVØÑŠCñ ,ð ”�F“×
Ð
ùs   ‚E-E4Å2E4r`   c                 óR   • U R                   S-  (       a  gU R                  [        ;  $ )a€  Report whether an archive member cannot be read because it is encrypted.

Standard ZIP encryption sets bit 0 of the general-purpose flags. Pages does
not use that: it leaves the flag clear and writes a compression method
outside the set ZIP defines, so both signals are needed.

Args:
    info: The archive member to inspect.

Returns:
    Whether the member appears to be encrypted.
r   T)Ú	flag_bitsÚcompress_typeÚREADABLE_COMPRESSION_METHODS)r`   s    r   Úis_encryptedri     s%   € ð ‡~�~˜×ØØ×ÑÔ%AÑAÐAr   ),r   ÚloggingÚzipfileÚcollections.abcr   Útypingr   Údocling.exceptionsr   Ú	getLoggerr   Ú_logrZ   rY   r,   r.   r-   r/   rF   rH   rI   r[   Údictr   Úlistr   ÚFieldMapr   Útupler(   r8   r=   rU   r\   rd   Ú	frozensetÚ
ZIP_STOREDÚZIP_DEFLATEDÚ	ZIP_BZIP2ÚZIP_LZMArh   ÚZipInfoÚboolri   r   r   r   Ú<module>r|      s{  ðñó* Û Ý $Ý å 0à×Ò˜Ó"€à€Ø€ð €Ø€ØÐ Ø€ð €Ø€Ø€ð &Ð à��T˜# ™+Ñ&Ð&Ñ'€ô�
ô ð�Uð  ð ¨¨s°C¨x©ô ð"�Uð ˜xô ðD7˜ð 7 #¨¡*ô 7ð 8Iñ W 5ð W°ð WÈUõ Wðt�Uð ˜uô ð2�uð  ¨)Ñ!4ô ñ:  )à×ÑØ×ÑØ×ÑØ×Ñð	ó Ð ððB�w—‘ð B¨4õ Br   