From c0f549625aaf6d61d7d4a328badfdc42b6c7f138 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 28 May 2013 11:42:53 +0530 Subject: [PATCH] Replace CRLF line endings --- format_docs/compression/zip.txt | 6434 ++++++++++++------------- imgsrc/catalog.svg | 314 +- imgsrc/sd.svg | 902 ++-- imgsrc/view.svg | 64 +- recipes/autosport.recipe | 60 +- recipes/buchreport.recipe | 90 +- recipes/diario_la_republica.recipe | 22 +- recipes/dnevnik_mk.recipe | 196 +- recipes/el_colombiano.recipe | 112 +- recipes/el_espectador.recipe | 108 +- recipes/el_mostrador.recipe | 80 +- recipes/el_tiempo.recipe | 104 +- recipes/estadao.recipe | 258 +- recipes/folhadesaopaulo.recipe | 330 +- recipes/gazeta_pl_szczecin.recipe | 70 +- recipes/gs24_pl.recipe | 86 +- recipes/hankyoreh.recipe | 94 +- recipes/hankyoreh21.recipe | 50 +- recipes/huffingtonpost_uk.recipe | 94 +- recipes/ilmanifesto.recipe | 220 +- recipes/jakarta_globe.recipe | 68 +- recipes/kompiutierra.recipe | 74 +- recipes/leipzer_volkszeitung.recipe | 68 +- recipes/lifehacker.recipe | 200 +- recipes/melbourne_herald_sun.recipe | 170 +- recipes/menorca.recipe | 276 +- recipes/mobile_bulgaria.recipe | 54 +- recipes/mojegotowanie.recipe | 2 +- recipes/novinite.recipe | 70 +- recipes/portafolio.recipe | 72 +- recipes/revista_semana.recipe | 22 +- recipes/rushisaband.recipe | 56 +- recipes/rybinski.recipe | 58 +- recipes/silicon_republic.recipe | 44 +- recipes/spin_magazine.recipe | 30 +- recipes/thai_post_daily.recipe | 36 +- recipes/the_clinic_online.recipe | 54 +- recipes/the_new_republic.recipe | 126 +- recipes/utrinski.recipe | 152 +- recipes/yazihane.recipe | 38 +- resources/calibre-portable.bat | 416 +- resources/content_server/date.js | 16 +- resources/viewer/jquery_scrollTo.js | 428 +- src/calibre/utils/cleantext.py | 134 +- src/cherrypy/LICENSE.txt | 50 +- src/html5lib/treewalkers/lxmletree.py | 350 +- src/unrar/acknow.txt | 162 +- 47 files changed, 6457 insertions(+), 6457 deletions(-) diff --git a/format_docs/compression/zip.txt b/format_docs/compression/zip.txt index e658f9582b..1565e775ba 100644 --- a/format_docs/compression/zip.txt +++ b/format_docs/compression/zip.txt @@ -1,3217 +1,3217 @@ -File: APPNOTE.TXT - .ZIP File Format Specification -Version: 6.3.2 -Revised: September 28, 2007 -Copyright (c) 1989 - 2007 PKWARE Inc., All Rights Reserved. - -The use of certain technological aspects disclosed in the current -APPNOTE is available pursuant to the below section entitled -"Incorporating PKWARE Proprietary Technology into Your Product". - -I. Purpose ----------- - -This specification is intended to define a cross-platform, -interoperable file storage and transfer format. Since its -first publication in 1989, PKWARE has remained committed to -ensuring the interoperability of the .ZIP file format through -publication and maintenance of this specification. We trust that -all .ZIP compatible vendors and application developers that have -adopted and benefited from this format will share and support -this commitment to interoperability. - -II. Contacting PKWARE ---------------------- - - PKWARE, Inc. - 648 N. Plankinton Avenue, Suite 220 - Milwaukee, WI 53203 - +1-414-289-9788 - +1-414-289-9789 FAX - zipformat@pkware.com - -III. Disclaimer ---------------- - -Although PKWARE will attempt to supply current and accurate -information relating to its file formats, algorithms, and the -subject programs, the possibility of error or omission cannot -be eliminated. PKWARE therefore expressly disclaims any warranty -that the information contained in the associated materials relating -to the subject programs and/or the format of the files created or -accessed by the subject programs and/or the algorithms used by -the subject programs, or any other matter, is current, correct or -accurate as delivered. Any risk of damage due to any possible -inaccurate information is assumed by the user of the information. -Furthermore, the information relating to the subject programs -and/or the file formats created or accessed by the subject -programs and/or the algorithms used by the subject programs is -subject to change without notice. - -If the version of this file is marked as a NOTIFICATION OF CHANGE, -the content defines an Early Feature Specification (EFS) change -to the .ZIP file format that may be subject to modification prior -to publication of the Final Feature Specification (FFS). This -document may also contain information on Planned Feature -Specifications (PFS) defining recognized future extensions. - -IV. Change Log --------------- - -Version Change Description Date -------- ------------------ ---------- -5.2 -Single Password Symmetric Encryption 06/02/2003 - storage - -6.1.0 -Smartcard compatibility 01/20/2004 - -Documentation on certificate storage - -6.2.0 -Introduction of Central Directory 04/26/2004 - Encryption for encrypting metadata - -Added OS/X to Version Made By values - -6.2.1 -Added Extra Field placeholder for 04/01/2005 - POSZIP using ID 0x4690 - - -Clarified size field on - "zip64 end of central directory record" - -6.2.2 -Documented Final Feature Specification 01/06/2006 - for Strong Encryption - - -Clarifications and typographical - corrections - -6.3.0 -Added tape positioning storage 09/29/2006 - parameters - - -Expanded list of supported hash algorithms - - -Expanded list of supported compression - algorithms - - -Expanded list of supported encryption - algorithms - - -Added option for Unicode filename - storage - - -Clarifications for consistent use - of Data Descriptor records - - -Added additional "Extra Field" - definitions - -6.3.1 -Corrected standard hash values for 04/11/2007 - SHA-256/384/512 - -6.3.2 -Added compression method 97 09/28/2007 - - -Documented InfoZIP "Extra Field" - values for UTF-8 file name and - file comment storage - -V. General Format of a .ZIP file --------------------------------- - - Files stored in arbitrary order. Large .ZIP files can span multiple - volumes or be split into user-defined segment sizes. All values - are stored in little-endian byte order unless otherwise specified. - - Overall .ZIP file format: - - [local file header 1] - [file data 1] - [data descriptor 1] - . - . - . - [local file header n] - [file data n] - [data descriptor n] - [archive decryption header] - [archive extra data record] - [central directory] - [zip64 end of central directory record] - [zip64 end of central directory locator] - [end of central directory record] - - - A. Local file header: - - local file header signature 4 bytes (0x04034b50) - version needed to extract 2 bytes - general purpose bit flag 2 bytes - compression method 2 bytes - last mod file time 2 bytes - last mod file date 2 bytes - crc-32 4 bytes - compressed size 4 bytes - uncompressed size 4 bytes - file name length 2 bytes - extra field length 2 bytes - - file name (variable size) - extra field (variable size) - - B. File data - - Immediately following the local header for a file - is the compressed or stored data for the file. - The series of [local file header][file data][data - descriptor] repeats for each file in the .ZIP archive. - - C. Data descriptor: - - crc-32 4 bytes - compressed size 4 bytes - uncompressed size 4 bytes - - This descriptor exists only if bit 3 of the general - purpose bit flag is set (see below). It is byte aligned - and immediately follows the last byte of compressed data. - This descriptor is used only when it was not possible to - seek in the output .ZIP file, e.g., when the output .ZIP file - was standard output or a non-seekable device. For ZIP64(tm) format - archives, the compressed and uncompressed sizes are 8 bytes each. - - When compressing files, compressed and uncompressed sizes - should be stored in ZIP64 format (as 8 byte values) when a - files size exceeds 0xFFFFFFFF. However ZIP64 format may be - used regardless of the size of a file. When extracting, if - the zip64 extended information extra field is present for - the file the compressed and uncompressed sizes will be 8 - byte values. - - Although not originally assigned a signature, the value - 0x08074b50 has commonly been adopted as a signature value - for the data descriptor record. Implementers should be - aware that ZIP files may be encountered with or without this - signature marking data descriptors and should account for - either case when reading ZIP files to ensure compatibility. - When writing ZIP files, it is recommended to include the - signature value marking the data descriptor record. When - the signature is used, the fields currently defined for - the data descriptor record will immediately follow the - signature. - - An extensible data descriptor will be released in a future - version of this APPNOTE. This new record is intended to - resolve conflicts with the use of this record going forward, - and to provide better support for streamed file processing. - - When the Central Directory Encryption method is used, the data - descriptor record is not required, but may be used. If present, - and bit 3 of the general purpose bit field is set to indicate - its presence, the values in fields of the data descriptor - record should be set to binary zeros. - - D. Archive decryption header: - - The Archive Decryption Header is introduced in version 6.2 - of the ZIP format specification. This record exists in support - of the Central Directory Encryption Feature implemented as part of - the Strong Encryption Specification as described in this document. - When the Central Directory Structure is encrypted, this decryption - header will precede the encrypted data segment. The encrypted - data segment will consist of the Archive extra data record (if - present) and the encrypted Central Directory Structure data. - The format of this data record is identical to the Decryption - header record preceding compressed file data. If the central - directory structure is encrypted, the location of the start of - this data record is determined using the Start of Central Directory - field in the Zip64 End of Central Directory record. Refer to the - section on the Strong Encryption Specification for information - on the fields used in the Archive Decryption Header record. - - - E. Archive extra data record: - - archive extra data signature 4 bytes (0x08064b50) - extra field length 4 bytes - extra field data (variable size) - - The Archive Extra Data Record is introduced in version 6.2 - of the ZIP format specification. This record exists in support - of the Central Directory Encryption Feature implemented as part of - the Strong Encryption Specification as described in this document. - When present, this record immediately precedes the central - directory data structure. The size of this data record will be - included in the Size of the Central Directory field in the - End of Central Directory record. If the central directory structure - is compressed, but not encrypted, the location of the start of - this data record is determined using the Start of Central Directory - field in the Zip64 End of Central Directory record. - - - F. Central directory structure: - - [file header 1] - . - . - . - [file header n] - [digital signature] - - File header: - - central file header signature 4 bytes (0x02014b50) - version made by 2 bytes - version needed to extract 2 bytes - general purpose bit flag 2 bytes - compression method 2 bytes - last mod file time 2 bytes - last mod file date 2 bytes - crc-32 4 bytes - compressed size 4 bytes - uncompressed size 4 bytes - file name length 2 bytes - extra field length 2 bytes - file comment length 2 bytes - disk number start 2 bytes - internal file attributes 2 bytes - external file attributes 4 bytes - relative offset of local header 4 bytes - - file name (variable size) - extra field (variable size) - file comment (variable size) - - Digital signature: - - header signature 4 bytes (0x05054b50) - size of data 2 bytes - signature data (variable size) - - With the introduction of the Central Directory Encryption - feature in version 6.2 of this specification, the Central - Directory Structure may be stored both compressed and encrypted. - Although not required, it is assumed when encrypting the - Central Directory Structure, that it will be compressed - for greater storage efficiency. Information on the - Central Directory Encryption feature can be found in the section - describing the Strong Encryption Specification. The Digital - Signature record will be neither compressed nor encrypted. - - G. Zip64 end of central directory record - - zip64 end of central dir - signature 4 bytes (0x06064b50) - size of zip64 end of central - directory record 8 bytes - version made by 2 bytes - version needed to extract 2 bytes - number of this disk 4 bytes - number of the disk with the - start of the central directory 4 bytes - total number of entries in the - central directory on this disk 8 bytes - total number of entries in the - central directory 8 bytes - size of the central directory 8 bytes - offset of start of central - directory with respect to - the starting disk number 8 bytes - zip64 extensible data sector (variable size) - - The value stored into the "size of zip64 end of central - directory record" should be the size of the remaining - record and should not include the leading 12 bytes. - - Size = SizeOfFixedFields + SizeOfVariableData - 12. - - The above record structure defines Version 1 of the - zip64 end of central directory record. Version 1 was - implemented in versions of this specification preceding - 6.2 in support of the ZIP64 large file feature. The - introduction of the Central Directory Encryption feature - implemented in version 6.2 as part of the Strong Encryption - Specification defines Version 2 of this record structure. - Refer to the section describing the Strong Encryption - Specification for details on the version 2 format for - this record. - - Special purpose data may reside in the zip64 extensible data - sector field following either a V1 or V2 version of this - record. To ensure identification of this special purpose data - it must include an identifying header block consisting of the - following: - - Header ID - 2 bytes - Data Size - 4 bytes - - The Header ID field indicates the type of data that is in the - data block that follows. - - Data Size identifies the number of bytes that follow for this - data block type. - - Multiple special purpose data blocks may be present, but each - must be preceded by a Header ID and Data Size field. Current - mappings of Header ID values supported in this field are as - defined in APPENDIX C. - - H. Zip64 end of central directory locator - - zip64 end of central dir locator - signature 4 bytes (0x07064b50) - number of the disk with the - start of the zip64 end of - central directory 4 bytes - relative offset of the zip64 - end of central directory record 8 bytes - total number of disks 4 bytes - - I. End of central directory record: - - end of central dir signature 4 bytes (0x06054b50) - number of this disk 2 bytes - number of the disk with the - start of the central directory 2 bytes - total number of entries in the - central directory on this disk 2 bytes - total number of entries in - the central directory 2 bytes - size of the central directory 4 bytes - offset of start of central - directory with respect to - the starting disk number 4 bytes - .ZIP file comment length 2 bytes - .ZIP file comment (variable size) - - J. Explanation of fields: - - version made by (2 bytes) - - The upper byte indicates the compatibility of the file - attribute information. If the external file attributes - are compatible with MS-DOS and can be read by PKZIP for - DOS version 2.04g then this value will be zero. If these - attributes are not compatible, then this value will - identify the host system on which the attributes are - compatible. Software can use this information to determine - the line record format for text files etc. The current - mappings are: - - 0 - MS-DOS and OS/2 (FAT / VFAT / FAT32 file systems) - 1 - Amiga 2 - OpenVMS - 3 - UNIX 4 - VM/CMS - 5 - Atari ST 6 - OS/2 H.P.F.S. - 7 - Macintosh 8 - Z-System - 9 - CP/M 10 - Windows NTFS - 11 - MVS (OS/390 - Z/OS) 12 - VSE - 13 - Acorn Risc 14 - VFAT - 15 - alternate MVS 16 - BeOS - 17 - Tandem 18 - OS/400 - 19 - OS/X (Darwin) 20 thru 255 - unused - - The lower byte indicates the ZIP specification version - (the version of this document) supported by the software - used to encode the file. The value/10 indicates the major - version number, and the value mod 10 is the minor version - number. - - version needed to extract (2 bytes) - - The minimum supported ZIP specification version needed to - extract the file, mapped as above. This value is based on - the specific format features a ZIP program must support to - be able to extract the file. If multiple features are - applied to a file, the minimum version should be set to the - feature having the highest value. New features or feature - changes affecting the published format specification will be - implemented using higher version numbers than the last - published value to avoid conflict. - - Current minimum feature versions are as defined below: - - 1.0 - Default value - 1.1 - File is a volume label - 2.0 - File is a folder (directory) - 2.0 - File is compressed using Deflate compression - 2.0 - File is encrypted using traditional PKWARE encryption - 2.1 - File is compressed using Deflate64(tm) - 2.5 - File is compressed using PKWARE DCL Implode - 2.7 - File is a patch data set - 4.5 - File uses ZIP64 format extensions - 4.6 - File is compressed using BZIP2 compression* - 5.0 - File is encrypted using DES - 5.0 - File is encrypted using 3DES - 5.0 - File is encrypted using original RC2 encryption - 5.0 - File is encrypted using RC4 encryption - 5.1 - File is encrypted using AES encryption - 5.1 - File is encrypted using corrected RC2 encryption** - 5.2 - File is encrypted using corrected RC2-64 encryption** - 6.1 - File is encrypted using non-OAEP key wrapping*** - 6.2 - Central directory encryption - 6.3 - File is compressed using LZMA - 6.3 - File is compressed using PPMd+ - 6.3 - File is encrypted using Blowfish - 6.3 - File is encrypted using Twofish - - - * Early 7.x (pre-7.2) versions of PKZIP incorrectly set the - version needed to extract for BZIP2 compression to be 50 - when it should have been 46. - - ** Refer to the section on Strong Encryption Specification - for additional information regarding RC2 corrections. - - *** Certificate encryption using non-OAEP key wrapping is the - intended mode of operation for all versions beginning with 6.1. - Support for OAEP key wrapping should only be used for - backward compatibility when sending ZIP files to be opened by - versions of PKZIP older than 6.1 (5.0 or 6.0). - - + Files compressed using PPMd should set the version - needed to extract field to 6.3, however, not all ZIP - programs enforce this and may be unable to decompress - data files compressed using PPMd if this value is set. - - When using ZIP64 extensions, the corresponding value in the - zip64 end of central directory record should also be set. - This field should be set appropriately to indicate whether - Version 1 or Version 2 format is in use. - - general purpose bit flag: (2 bytes) - - Bit 0: If set, indicates that the file is encrypted. - - (For Method 6 - Imploding) - Bit 1: If the compression method used was type 6, - Imploding, then this bit, if set, indicates - an 8K sliding dictionary was used. If clear, - then a 4K sliding dictionary was used. - Bit 2: If the compression method used was type 6, - Imploding, then this bit, if set, indicates - 3 Shannon-Fano trees were used to encode the - sliding dictionary output. If clear, then 2 - Shannon-Fano trees were used. - - (For Methods 8 and 9 - Deflating) - Bit 2 Bit 1 - 0 0 Normal (-en) compression option was used. - 0 1 Maximum (-exx/-ex) compression option was used. - 1 0 Fast (-ef) compression option was used. - 1 1 Super Fast (-es) compression option was used. - - (For Method 14 - LZMA) - Bit 1: If the compression method used was type 14, - LZMA, then this bit, if set, indicates - an end-of-stream (EOS) marker is used to - mark the end of the compressed data stream. - If clear, then an EOS marker is not present - and the compressed data size must be known - to extract. - - Note: Bits 1 and 2 are undefined if the compression - method is any other. - - Bit 3: If this bit is set, the fields crc-32, compressed - size and uncompressed size are set to zero in the - local header. The correct values are put in the - data descriptor immediately following the compressed - data. (Note: PKZIP version 2.04g for DOS only - recognizes this bit for method 8 compression, newer - versions of PKZIP recognize this bit for any - compression method.) - - Bit 4: Reserved for use with method 8, for enhanced - deflating. - - Bit 5: If this bit is set, this indicates that the file is - compressed patched data. (Note: Requires PKZIP - version 2.70 or greater) - - Bit 6: Strong encryption. If this bit is set, you should - set the version needed to extract value to at least - 50 and you must also set bit 0. If AES encryption - is used, the version needed to extract value must - be at least 51. - - Bit 7: Currently unused. - - Bit 8: Currently unused. - - Bit 9: Currently unused. - - Bit 10: Currently unused. - - Bit 11: Language encoding flag (EFS). If this bit is set, - the filename and comment fields for this file - must be encoded using UTF-8. (see APPENDIX D) - - Bit 12: Reserved by PKWARE for enhanced compression. - - Bit 13: Used when encrypting the Central Directory to indicate - selected data values in the Local Header are masked to - hide their actual values. See the section describing - the Strong Encryption Specification for details. - - Bit 14: Reserved by PKWARE. - - Bit 15: Reserved by PKWARE. - - compression method: (2 bytes) - - (see accompanying documentation for algorithm - descriptions) - - 0 - The file is stored (no compression) - 1 - The file is Shrunk - 2 - The file is Reduced with compression factor 1 - 3 - The file is Reduced with compression factor 2 - 4 - The file is Reduced with compression factor 3 - 5 - The file is Reduced with compression factor 4 - 6 - The file is Imploded - 7 - Reserved for Tokenizing compression algorithm - 8 - The file is Deflated - 9 - Enhanced Deflating using Deflate64(tm) - 10 - PKWARE Data Compression Library Imploding (old IBM TERSE) - 11 - Reserved by PKWARE - 12 - File is compressed using BZIP2 algorithm - 13 - Reserved by PKWARE - 14 - LZMA (EFS) - 15 - Reserved by PKWARE - 16 - Reserved by PKWARE - 17 - Reserved by PKWARE - 18 - File is compressed using IBM TERSE (new) - 19 - IBM LZ77 z Architecture (PFS) - 97 - WavPack compressed data - 98 - PPMd version I, Rev 1 - - date and time fields: (2 bytes each) - - The date and time are encoded in standard MS-DOS format. - If input came from standard input, the date and time are - those at which compression was started for this data. - If encrypting the central directory and general purpose bit - flag 13 is set indicating masking, the value stored in the - Local Header will be zero. - - CRC-32: (4 bytes) - - The CRC-32 algorithm was generously contributed by - David Schwaderer and can be found in his excellent - book "C Programmers Guide to NetBIOS" published by - Howard W. Sams & Co. Inc. The 'magic number' for - the CRC is 0xdebb20e3. The proper CRC pre and post - conditioning is used, meaning that the CRC register - is pre-conditioned with all ones (a starting value - of 0xffffffff) and the value is post-conditioned by - taking the one's complement of the CRC residual. - If bit 3 of the general purpose flag is set, this - field is set to zero in the local header and the correct - value is put in the data descriptor and in the central - directory. When encrypting the central directory, if the - local header is not in ZIP64 format and general purpose - bit flag 13 is set indicating masking, the value stored - in the Local Header will be zero. - - compressed size: (4 bytes) - uncompressed size: (4 bytes) - - The size of the file compressed and uncompressed, - respectively. When a decryption header is present it will - be placed in front of the file data and the value of the - compressed file size will include the bytes of the decryption - header. If bit 3 of the general purpose bit flag is set, - these fields are set to zero in the local header and the - correct values are put in the data descriptor and - in the central directory. If an archive is in ZIP64 format - and the value in this field is 0xFFFFFFFF, the size will be - in the corresponding 8 byte ZIP64 extended information - extra field. When encrypting the central directory, if the - local header is not in ZIP64 format and general purpose bit - flag 13 is set indicating masking, the value stored for the - uncompressed size in the Local Header will be zero. - - file name length: (2 bytes) - extra field length: (2 bytes) - file comment length: (2 bytes) - - The length of the file name, extra field, and comment - fields respectively. The combined length of any - directory record and these three fields should not - generally exceed 65,535 bytes. If input came from standard - input, the file name length is set to zero. - - disk number start: (2 bytes) - - The number of the disk on which this file begins. If an - archive is in ZIP64 format and the value in this field is - 0xFFFF, the size will be in the corresponding 4 byte zip64 - extended information extra field. - - internal file attributes: (2 bytes) - - Bits 1 and 2 are reserved for use by PKWARE. - - The lowest bit of this field indicates, if set, that - the file is apparently an ASCII or text file. If not - set, that the file apparently contains binary data. - The remaining bits are unused in version 1.0. - - The 0x0002 bit of this field indicates, if set, that a - 4 byte variable record length control field precedes each - logical record indicating the length of the record. The - record length control field is stored in little-endian byte - order. This flag is independent of text control characters, - and if used in conjunction with text data, includes any - control characters in the total length of the record. This - value is provided for mainframe data transfer support. - - external file attributes: (4 bytes) - - The mapping of the external attributes is - host-system dependent (see 'version made by'). For - MS-DOS, the low order byte is the MS-DOS directory - attribute byte. If input came from standard input, this - field is set to zero. - - relative offset of local header: (4 bytes) - - This is the offset from the start of the first disk on - which this file appears, to where the local header should - be found. If an archive is in ZIP64 format and the value - in this field is 0xFFFFFFFF, the size will be in the - corresponding 8 byte zip64 extended information extra field. - - file name: (Variable) - - The name of the file, with optional relative path. - The path stored should not contain a drive or - device letter, or a leading slash. All slashes - should be forward slashes '/' as opposed to - backwards slashes '\' for compatibility with Amiga - and UNIX file systems etc. If input came from standard - input, there is no file name field. If encrypting - the central directory and general purpose bit flag 13 is set - indicating masking, the file name stored in the Local Header - will not be the actual file name. A masking value consisting - of a unique hexadecimal value will be stored. This value will - be sequentially incremented for each file in the archive. See - the section on the Strong Encryption Specification for details - on retrieving the encrypted file name. - - extra field: (Variable) - - This is for expansion. If additional information - needs to be stored for special needs or for specific - platforms, it should be stored here. Earlier versions - of the software can then safely skip this file, and - find the next file or header. This field will be 0 - length in version 1.0. - - In order to allow different programs and different types - of information to be stored in the 'extra' field in .ZIP - files, the following structure should be used for all - programs storing data in this field: - - header1+data1 + header2+data2 . . . - - Each header should consist of: - - Header ID - 2 bytes - Data Size - 2 bytes - - Note: all fields stored in Intel low-byte/high-byte order. - - The Header ID field indicates the type of data that is in - the following data block. - - Header ID's of 0 thru 31 are reserved for use by PKWARE. - The remaining ID's can be used by third party vendors for - proprietary usage. - - The current Header ID mappings defined by PKWARE are: - - 0x0001 Zip64 extended information extra field - 0x0007 AV Info - 0x0008 Reserved for extended language encoding data (PFS) - (see APPENDIX D) - 0x0009 OS/2 - 0x000a NTFS - 0x000c OpenVMS - 0x000d UNIX - 0x000e Reserved for file stream and fork descriptors - 0x000f Patch Descriptor - 0x0014 PKCS#7 Store for X.509 Certificates - 0x0015 X.509 Certificate ID and Signature for - individual file - 0x0016 X.509 Certificate ID for Central Directory - 0x0017 Strong Encryption Header - 0x0018 Record Management Controls - 0x0019 PKCS#7 Encryption Recipient Certificate List - 0x0065 IBM S/390 (Z390), AS/400 (I400) attributes - - uncompressed - 0x0066 Reserved for IBM S/390 (Z390), AS/400 (I400) - attributes - compressed - 0x4690 POSZIP 4690 (reserved) - - Third party mappings commonly used are: - - - 0x07c8 Macintosh - 0x2605 ZipIt Macintosh - 0x2705 ZipIt Macintosh 1.3.5+ - 0x2805 ZipIt Macintosh 1.3.5+ - 0x334d Info-ZIP Macintosh - 0x4341 Acorn/SparkFS - 0x4453 Windows NT security descriptor (binary ACL) - 0x4704 VM/CMS - 0x470f MVS - 0x4b46 FWKCS MD5 (see below) - 0x4c41 OS/2 access control list (text ACL) - 0x4d49 Info-ZIP OpenVMS - 0x4f4c Xceed original location extra field - 0x5356 AOS/VS (ACL) - 0x5455 extended timestamp - 0x554e Xceed unicode extra field - 0x5855 Info-ZIP UNIX (original, also OS/2, NT, etc) - 0x6375 Info-ZIP Unicode Comment Extra Field - 0x6542 BeOS/BeBox - 0x7075 Info-ZIP Unicode Path Extra Field - 0x756e ASi UNIX - 0x7855 Info-ZIP UNIX (new) - 0xa220 Microsoft Open Packaging Growth Hint - 0xfd4a SMS/QDOS - - Detailed descriptions of Extra Fields defined by third - party mappings will be documented as information on - these data structures is made available to PKWARE. - PKWARE does not guarantee the accuracy of any published - third party data. - - The Data Size field indicates the size of the following - data block. Programs can use this value to skip to the - next header block, passing over any data blocks that are - not of interest. - - Note: As stated above, the size of the entire .ZIP file - header, including the file name, comment, and extra - field should not exceed 64K in size. - - In case two different programs should appropriate the same - Header ID value, it is strongly recommended that each - program place a unique signature of at least two bytes in - size (and preferably 4 bytes or bigger) at the start of - each data area. Every program should verify that its - unique signature is present, in addition to the Header ID - value being correct, before assuming that it is a block of - known type. - - -Zip64 Extended Information Extra Field (0x0001): - - The following is the layout of the zip64 extended - information "extra" block. If one of the size or - offset fields in the Local or Central directory - record is too small to hold the required data, - a Zip64 extended information record is created. - The order of the fields in the zip64 extended - information record is fixed, but the fields will - only appear if the corresponding Local or Central - directory record field is set to 0xFFFF or 0xFFFFFFFF. - - Note: all fields stored in Intel low-byte/high-byte order. - - Value Size Description - ----- ---- ----------- - (ZIP64) 0x0001 2 bytes Tag for this "extra" block type - Size 2 bytes Size of this "extra" block - Original - Size 8 bytes Original uncompressed file size - Compressed - Size 8 bytes Size of compressed data - Relative Header - Offset 8 bytes Offset of local header record - Disk Start - Number 4 bytes Number of the disk on which - this file starts - - This entry in the Local header must include BOTH original - and compressed file size fields. If encrypting the - central directory and bit 13 of the general purpose bit - flag is set indicating masking, the value stored in the - Local Header for the original file size will be zero. - - - -OS/2 Extra Field (0x0009): - - The following is the layout of the OS/2 attributes "extra" - block. (Last Revision 09/05/95) - - Note: all fields stored in Intel low-byte/high-byte order. - - Value Size Description - ----- ---- ----------- - (OS/2) 0x0009 2 bytes Tag for this "extra" block type - TSize 2 bytes Size for the following data block - BSize 4 bytes Uncompressed Block Size - CType 2 bytes Compression type - EACRC 4 bytes CRC value for uncompress block - (var) variable Compressed block - - The OS/2 extended attribute structure (FEA2LIST) is - compressed and then stored in it's entirety within this - structure. There will only ever be one "block" of data in - VarFields[]. - - -NTFS Extra Field (0x000a): - - The following is the layout of the NTFS attributes - "extra" block. (Note: At this time the Mtime, Atime - and Ctime values may be used on any WIN32 system.) - - Note: all fields stored in Intel low-byte/high-byte order. - - Value Size Description - ----- ---- ----------- - (NTFS) 0x000a 2 bytes Tag for this "extra" block type - TSize 2 bytes Size of the total "extra" block - Reserved 4 bytes Reserved for future use - Tag1 2 bytes NTFS attribute tag value #1 - Size1 2 bytes Size of attribute #1, in bytes - (var.) Size1 Attribute #1 data - . - . - . - TagN 2 bytes NTFS attribute tag value #N - SizeN 2 bytes Size of attribute #N, in bytes - (var.) SizeN Attribute #N data - - For NTFS, values for Tag1 through TagN are as follows: - (currently only one set of attributes is defined for NTFS) - - Tag Size Description - ----- ---- ----------- - 0x0001 2 bytes Tag for attribute #1 - Size1 2 bytes Size of attribute #1, in bytes - Mtime 8 bytes File last modification time - Atime 8 bytes File last access time - Ctime 8 bytes File creation time - - -OpenVMS Extra Field (0x000c): - - The following is the layout of the OpenVMS attributes - "extra" block. - - Note: all fields stored in Intel low-byte/high-byte order. - - Value Size Description - ----- ---- ----------- - (VMS) 0x000c 2 bytes Tag for this "extra" block type - TSize 2 bytes Size of the total "extra" block - CRC 4 bytes 32-bit CRC for remainder of the block - Tag1 2 bytes OpenVMS attribute tag value #1 - Size1 2 bytes Size of attribute #1, in bytes - (var.) Size1 Attribute #1 data - . - . - . - TagN 2 bytes OpenVMS attribute tag value #N - SizeN 2 bytes Size of attribute #N, in bytes - (var.) SizeN Attribute #N data - - Rules: - - 1. There will be one or more of attributes present, which - will each be preceded by the above TagX & SizeX values. - These values are identical to the ATR$C_XXXX and - ATR$S_XXXX constants which are defined in ATR.H under - OpenVMS C. Neither of these values will ever be zero. - - 2. No word alignment or padding is performed. - - 3. A well-behaved PKZIP/OpenVMS program should never produce - more than one sub-block with the same TagX value. Also, - there will never be more than one "extra" block of type - 0x000c in a particular directory record. - - -UNIX Extra Field (0x000d): - - The following is the layout of the UNIX "extra" block. - Note: all fields are stored in Intel low-byte/high-byte - order. - - Value Size Description - ----- ---- ----------- - (UNIX) 0x000d 2 bytes Tag for this "extra" block type - TSize 2 bytes Size for the following data block - Atime 4 bytes File last access time - Mtime 4 bytes File last modification time - Uid 2 bytes File user ID - Gid 2 bytes File group ID - (var) variable Variable length data field - - The variable length data field will contain file type - specific data. Currently the only values allowed are - the original "linked to" file names for hard or symbolic - links, and the major and minor device node numbers for - character and block device nodes. Since device nodes - cannot be either symbolic or hard links, only one set of - variable length data is stored. Link files will have the - name of the original file stored. This name is NOT NULL - terminated. Its size can be determined by checking TSize - - 12. Device entries will have eight bytes stored as two 4 - byte entries (in little endian format). The first entry - will be the major device number, and the second the minor - device number. - - -PATCH Descriptor Extra Field (0x000f): - - The following is the layout of the Patch Descriptor "extra" - block. - - Note: all fields stored in Intel low-byte/high-byte order. - - Value Size Description - ----- ---- ----------- - (Patch) 0x000f 2 bytes Tag for this "extra" block type - TSize 2 bytes Size of the total "extra" block - Version 2 bytes Version of the descriptor - Flags 4 bytes Actions and reactions (see below) - OldSize 4 bytes Size of the file about to be patched - OldCRC 4 bytes 32-bit CRC of the file to be patched - NewSize 4 bytes Size of the resulting file - NewCRC 4 bytes 32-bit CRC of the resulting file - - Actions and reactions - - Bits Description - ---- ---------------- - 0 Use for auto detection - 1 Treat as a self-patch - 2-3 RESERVED - 4-5 Action (see below) - 6-7 RESERVED - 8-9 Reaction (see below) to absent file - 10-11 Reaction (see below) to newer file - 12-13 Reaction (see below) to unknown file - 14-15 RESERVED - 16-31 RESERVED - - Actions - - Action Value - ------ ----- - none 0 - add 1 - delete 2 - patch 3 - - Reactions - - Reaction Value - -------- ----- - ask 0 - skip 1 - ignore 2 - fail 3 - - Patch support is provided by PKPatchMaker(tm) technology and is - covered under U.S. Patents and Patents Pending. The use or - implementation in a product of certain technological aspects set - forth in the current APPNOTE, including those with regard to - strong encryption, patching, or extended tape operations requires - a license from PKWARE. Please contact PKWARE with regard to - acquiring a license. - - -PKCS#7 Store for X.509 Certificates (0x0014): - - This field contains information about each of the certificates - files may be signed with. When the Central Directory Encryption - feature is enabled for a ZIP file, this record will appear in - the Archive Extra Data Record, otherwise it will appear in the - first central directory record and will be ignored in any - other record. - - Note: all fields stored in Intel low-byte/high-byte order. - - Value Size Description - ----- ---- ----------- - (Store) 0x0014 2 bytes Tag for this "extra" block type - TSize 2 bytes Size of the store data - TData TSize Data about the store - - - -X.509 Certificate ID and Signature for individual file (0x0015): - - This field contains the information about which certificate in - the PKCS#7 store was used to sign a particular file. It also - contains the signature data. This field can appear multiple - times, but can only appear once per certificate. - - Note: all fields stored in Intel low-byte/high-byte order. - - Value Size Description - ----- ---- ----------- - (CID) 0x0015 2 bytes Tag for this "extra" block type - TSize 2 bytes Size of data that follows - TData TSize Signature Data - - -X.509 Certificate ID and Signature for central directory (0x0016): - - This field contains the information about which certificate in - the PKCS#7 store was used to sign the central directory structure. - When the Central Directory Encryption feature is enabled for a - ZIP file, this record will appear in the Archive Extra Data Record, - otherwise it will appear in the first central directory record. - - Note: all fields stored in Intel low-byte/high-byte order. - - Value Size Description - ----- ---- ----------- - (CDID) 0x0016 2 bytes Tag for this "extra" block type - TSize 2 bytes Size of data that follows - TData TSize Data - - -Strong Encryption Header (0x0017): - - Value Size Description - ----- ---- ----------- - 0x0017 2 bytes Tag for this "extra" block type - TSize 2 bytes Size of data that follows - Format 2 bytes Format definition for this record - AlgID 2 bytes Encryption algorithm identifier - Bitlen 2 bytes Bit length of encryption key - Flags 2 bytes Processing flags - CertData TSize-8 Certificate decryption extra field data - (refer to the explanation for CertData - in the section describing the - Certificate Processing Method under - the Strong Encryption Specification) - - - -Record Management Controls (0x0018): - - Value Size Description - ----- ---- ----------- -(Rec-CTL) 0x0018 2 bytes Tag for this "extra" block type - CSize 2 bytes Size of total extra block data - Tag1 2 bytes Record control attribute 1 - Size1 2 bytes Size of attribute 1, in bytes - Data1 Size1 Attribute 1 data - . - . - . - TagN 2 bytes Record control attribute N - SizeN 2 bytes Size of attribute N, in bytes - DataN SizeN Attribute N data - - - -PKCS#7 Encryption Recipient Certificate List (0x0019): - - This field contains information about each of the certificates - used in encryption processing and it can be used to identify who is - allowed to decrypt encrypted files. This field should only appear - in the archive extra data record. This field is not required and - serves only to aide archive modifications by preserving public - encryption key data. Individual security requirements may dictate - that this data be omitted to deter information exposure. - - Note: all fields stored in Intel low-byte/high-byte order. - - Value Size Description - ----- ---- ----------- - (CStore) 0x0019 2 bytes Tag for this "extra" block type - TSize 2 bytes Size of the store data - TData TSize Data about the store - - TData: - - Value Size Description - ----- ---- ----------- - Version 2 bytes Format version number - must 0x0001 at this time - CStore (var) PKCS#7 data blob - - - -MVS Extra Field (0x0065): - - The following is the layout of the MVS "extra" block. - Note: Some fields are stored in Big Endian format. - All text is in EBCDIC format unless otherwise specified. - - Value Size Description - ----- ---- ----------- - (MVS) 0x0065 2 bytes Tag for this "extra" block type - TSize 2 bytes Size for the following data block - ID 4 bytes EBCDIC "Z390" 0xE9F3F9F0 or - "T4MV" for TargetFour - (var) TSize-4 Attribute data (see APPENDIX B) - - - -OS/400 Extra Field (0x0065): - - The following is the layout of the OS/400 "extra" block. - Note: Some fields are stored in Big Endian format. - All text is in EBCDIC format unless otherwise specified. - - Value Size Description - ----- ---- ----------- - (OS400) 0x0065 2 bytes Tag for this "extra" block type - TSize 2 bytes Size for the following data block - ID 4 bytes EBCDIC "I400" 0xC9F4F0F0 or - "T4MV" for TargetFour - (var) TSize-4 Attribute data (see APPENDIX A) - - - Third-party Mappings: - - -ZipIt Macintosh Extra Field (long) (0x2605): - - The following is the layout of the ZipIt extra block - for Macintosh. The local-header and central-header versions - are identical. This block must be present if the file is - stored MacBinary-encoded and it should not be used if the file - is not stored MacBinary-encoded. - - Value Size Description - ----- ---- ----------- - (Mac2) 0x2605 Short tag for this extra block type - TSize Short total data size for this block - "ZPIT" beLong extra-field signature - FnLen Byte length of FileName - FileName variable full Macintosh filename - FileType Byte[4] four-byte Mac file type string - Creator Byte[4] four-byte Mac creator string - - - -ZipIt Macintosh Extra Field (short, for files) (0x2705): - - The following is the layout of a shortened variant of the - ZipIt extra block for Macintosh (without "full name" entry). - This variant is used by ZipIt 1.3.5 and newer for entries of - files (not directories) that do not have a MacBinary encoded - file. The local-header and central-header versions are identical. - - Value Size Description - ----- ---- ----------- - (Mac2b) 0x2705 Short tag for this extra block type - TSize Short total data size for this block (12) - "ZPIT" beLong extra-field signature - FileType Byte[4] four-byte Mac file type string - Creator Byte[4] four-byte Mac creator string - fdFlags beShort attributes from FInfo.frFlags, - may be omitted - 0x0000 beShort reserved, may be omitted - - - -ZipIt Macintosh Extra Field (short, for directories) (0x2805): - - The following is the layout of a shortened variant of the - ZipIt extra block for Macintosh used only for directory - entries. This variant is used by ZipIt 1.3.5 and newer to - save some optional Mac-specific information about directories. - The local-header and central-header versions are identical. - - Value Size Description - ----- ---- ----------- - (Mac2c) 0x2805 Short tag for this extra block type - TSize Short total data size for this block (12) - "ZPIT" beLong extra-field signature - frFlags beShort attributes from DInfo.frFlags, may - be omitted - View beShort ZipIt view flag, may be omitted - - - The View field specifies ZipIt-internal settings as follows: - - Bits of the Flags: - bit 0 if set, the folder is shown expanded (open) - when the archive contents are viewed in ZipIt. - bits 1-15 reserved, zero; - - - -FWKCS MD5 Extra Field (0x4b46): - - The FWKCS Contents_Signature System, used in - automatically identifying files independent of file name, - optionally adds and uses an extra field to support the - rapid creation of an enhanced contents_signature: - - Header ID = 0x4b46 - Data Size = 0x0013 - Preface = 'M','D','5' - followed by 16 bytes containing the uncompressed file's - 128_bit MD5 hash(1), low byte first. - - When FWKCS revises a .ZIP file central directory to add - this extra field for a file, it also replaces the - central directory entry for that file's uncompressed - file length with a measured value. - - FWKCS provides an option to strip this extra field, if - present, from a .ZIP file central directory. In adding - this extra field, FWKCS preserves .ZIP file Authenticity - Verification; if stripping this extra field, FWKCS - preserves all versions of AV through PKZIP version 2.04g. - - FWKCS, and FWKCS Contents_Signature System, are - trademarks of Frederick W. Kantor. - - (1) R. Rivest, RFC1321.TXT, MIT Laboratory for Computer - Science and RSA Data Security, Inc., April 1992. - ll.76-77: "The MD5 algorithm is being placed in the - public domain for review and possible adoption as a - standard." - - - -Info-ZIP Unicode Comment Extra Field (0x6375): - - Stores the UTF-8 version of the file comment as stored in the - central directory header. (Last Revision 20070912) - - Value Size Description - ----- ---- ----------- - (UCom) 0x6375 Short tag for this extra block type ("uc") - TSize Short total data size for this block - Version 1 byte version of this extra field, currently 1 - ComCRC32 4 bytes Comment Field CRC32 Checksum - UnicodeCom Variable UTF-8 version of the entry comment - - Currently Version is set to the number 1. If there is a need - to change this field, the version will be incremented. Changes - may not be backward compatible so this extra field should not be - used if the version is not recognized. - - The ComCRC32 is the standard zip CRC32 checksum of the File Comment - field in the central directory header. This is used to verify that - the comment field has not changed since the Unicode Comment extra field - was created. This can happen if a utility changes the File Comment - field but does not update the UTF-8 Comment extra field. If the CRC - check fails, this Unicode Comment extra field should be ignored and - the File Comment field in the header should be used instead. - - The UnicodeCom field is the UTF-8 version of the File Comment field - in the header. As UnicodeCom is defined to be UTF-8, no UTF-8 byte - order mark (BOM) is used. The length of this field is determined by - subtracting the size of the previous fields from TSize. If both the - File Name and Comment fields are UTF-8, the new General Purpose Bit - Flag, bit 11 (Language encoding flag (EFS)), can be used to indicate - both the header File Name and Comment fields are UTF-8 and, in this - case, the Unicode Path and Unicode Comment extra fields are not - needed and should not be created. Note that, for backward - compatibility, bit 11 should only be used if the native character set - of the paths and comments being zipped up are already in UTF-8. It is - expected that the same file comment storage method, either general - purpose bit 11 or extra fields, be used in both the Local and Central - Directory Header for a file. - - - -Info-ZIP Unicode Path Extra Field (0x7075): - - Stores the UTF-8 version of the file name field as stored in the - local header and central directory header. (Last Revision 20070912) - - Value Size Description - ----- ---- ----------- - (UPath) 0x7075 Short tag for this extra block type ("up") - TSize Short total data size for this block - Version 1 byte version of this extra field, currently 1 - NameCRC32 4 bytes File Name Field CRC32 Checksum - UnicodeName Variable UTF-8 version of the entry File Name - - Currently Version is set to the number 1. If there is a need - to change this field, the version will be incremented. Changes - may not be backward compatible so this extra field should not be - used if the version is not recognized. - - The NameCRC32 is the standard zip CRC32 checksum of the File Name - field in the header. This is used to verify that the header - File Name field has not changed since the Unicode Path extra field - was created. This can happen if a utility renames the File Name but - does not update the UTF-8 path extra field. If the CRC check fails, - this UTF-8 Path Extra Field should be ignored and the File Name field - in the header should be used instead. - - The UnicodeName is the UTF-8 version of the contents of the File Name - field in the header. As UnicodeName is defined to be UTF-8, no UTF-8 - byte order mark (BOM) is used. The length of this field is determined - by subtracting the size of the previous fields from TSize. If both - the File Name and Comment fields are UTF-8, the new General Purpose - Bit Flag, bit 11 (Language encoding flag (EFS)), can be used to - indicate that both the header File Name and Comment fields are UTF-8 - and, in this case, the Unicode Path and Unicode Comment extra fields - are not needed and should not be created. Note that, for backward - compatibility, bit 11 should only be used if the native character set - of the paths and comments being zipped up are already in UTF-8. It is - expected that the same file name storage method, either general - purpose bit 11 or extra fields, be used in both the Local and Central - Directory Header for a file. - - - -Microsoft Open Packaging Growth Hint (0xa220): - - Value Size Description - ----- ---- ----------- - 0xa220 Short tag for this extra block type - TSize Short size of Sig + PadVal + Padding - Sig Short verification signature (A028) - PadVal Short Initial padding value - Padding variable filled with NULL characters - - - file comment: (Variable) - - The comment for this file. - - number of this disk: (2 bytes) - - The number of this disk, which contains central - directory end record. If an archive is in ZIP64 format - and the value in this field is 0xFFFF, the size will - be in the corresponding 4 byte zip64 end of central - directory field. - - - number of the disk with the start of the central - directory: (2 bytes) - - The number of the disk on which the central - directory starts. If an archive is in ZIP64 format - and the value in this field is 0xFFFF, the size will - be in the corresponding 4 byte zip64 end of central - directory field. - - total number of entries in the central dir on - this disk: (2 bytes) - - The number of central directory entries on this disk. - If an archive is in ZIP64 format and the value in - this field is 0xFFFF, the size will be in the - corresponding 8 byte zip64 end of central - directory field. - - total number of entries in the central dir: (2 bytes) - - The total number of files in the .ZIP file. If an - archive is in ZIP64 format and the value in this field - is 0xFFFF, the size will be in the corresponding 8 byte - zip64 end of central directory field. - - size of the central directory: (4 bytes) - - The size (in bytes) of the entire central directory. - If an archive is in ZIP64 format and the value in - this field is 0xFFFFFFFF, the size will be in the - corresponding 8 byte zip64 end of central - directory field. - - offset of start of central directory with respect to - the starting disk number: (4 bytes) - - Offset of the start of the central directory on the - disk on which the central directory starts. If an - archive is in ZIP64 format and the value in this - field is 0xFFFFFFFF, the size will be in the - corresponding 8 byte zip64 end of central - directory field. - - .ZIP file comment length: (2 bytes) - - The length of the comment for this .ZIP file. - - .ZIP file comment: (Variable) - - The comment for this .ZIP file. ZIP file comment data - is stored unsecured. No encryption or data authentication - is applied to this area at this time. Confidential information - should not be stored in this section. - - zip64 extensible data sector (variable size) - - (currently reserved for use by PKWARE) - - - K. Splitting and Spanning ZIP files - - Spanning is the process of segmenting a ZIP file across - multiple removable media. This support has typically only - been provided for DOS formatted floppy diskettes. - - File splitting is a newer derivative of spanning. - Splitting follows the same segmentation process as - spanning, however, it does not require writing each - segment to a unique removable medium and instead supports - placing all pieces onto local or non-removable locations - such as file systems, local drives, folders, etc... - - A key difference between spanned and split ZIP files is - that all pieces of a spanned ZIP file have the same name. - Since each piece is written to a separate volume, no name - collisions occur and each segment can reuse the original - .ZIP file name given to the archive. - - Sequence ordering for DOS spanned archives uses the DOS - volume label to determine segment numbers. Volume labels - for each segment are written using the form PKBACK#xxx, - where xxx is the segment number written as a decimal - value from 001 - nnn. - - Split ZIP files are typically written to the same location - and are subject to name collisions if the spanned name - format is used since each segment will reside on the same - drive. To avoid name collisions, split archives are named - as follows. - - Segment 1 = filename.z01 - Segment n-1 = filename.z(n-1) - Segment n = filename.zip - - The .ZIP extension is used on the last segment to support - quickly reading the central directory. The segment number - n should be a decimal value. - - Spanned ZIP files may be PKSFX Self-extracting ZIP files. - PKSFX files may also be split, however, in this case - the first segment must be named filename.exe. The first - segment of a split PKSFX archive must be large enough to - include the entire executable program. - - Capacities for split archives are as follows. - - Maximum number of segments = 4,294,967,295 - 1 - Maximum .ZIP segment size = 4,294,967,295 bytes - Minimum segment size = 64K - Maximum PKSFX segment size = 2,147,483,647 bytes - - Segment sizes may be different however by convention, all - segment sizes should be the same with the exception of the - last, which may be smaller. Local and central directory - header records must never be split across a segment boundary. - When writing a header record, if the number of bytes remaining - within a segment is less than the size of the header record, - end the current segment and write the header at the start - of the next segment. The central directory may span segment - boundaries, but no single record in the central directory - should be split across segments. - - Spanned/Split archives created using PKZIP for Windows - (V2.50 or greater), PKZIP Command Line (V2.50 or greater), - or PKZIP Explorer will include a special spanning - signature as the first 4 bytes of the first segment of - the archive. This signature (0x08074b50) will be - followed immediately by the local header signature for - the first file in the archive. - - A special spanning marker may also appear in spanned/split - archives if the spanning or splitting process starts but - only requires one segment. In this case the 0x08074b50 - signature will be replaced with the temporary spanning - marker signature of 0x30304b50. Split archives can - only be uncompressed by other versions of PKZIP that - know how to create a split archive. - - The signature value 0x08074b50 is also used by some - ZIP implementations as a marker for the Data Descriptor - record. Conflict in this alternate assignment can be - avoided by ensuring the position of the signature - within the ZIP file to determine the use for which it - is intended. - - L. General notes: - - 1) All fields unless otherwise noted are unsigned and stored - in Intel low-byte:high-byte, low-word:high-word order. - - 2) String fields are not null terminated, since the - length is given explicitly. - - 3) The entries in the central directory may not necessarily - be in the same order that files appear in the .ZIP file. - - 4) If one of the fields in the end of central directory - record is too small to hold required data, the field - should be set to -1 (0xFFFF or 0xFFFFFFFF) and the - ZIP64 format record should be created. - - 5) The end of central directory record and the - Zip64 end of central directory locator record must - reside on the same disk when splitting or spanning - an archive. - -VI. Explanation of compression methods --------------------------------------- - -UnShrinking - Method 1 ----------------------- - -Shrinking is a Dynamic Ziv-Lempel-Welch compression algorithm -with partial clearing. The initial code size is 9 bits, and -the maximum code size is 13 bits. Shrinking differs from -conventional Dynamic Ziv-Lempel-Welch implementations in several -respects: - -1) The code size is controlled by the compressor, and is not - automatically increased when codes larger than the current - code size are created (but not necessarily used). When - the decompressor encounters the code sequence 256 - (decimal) followed by 1, it should increase the code size - read from the input stream to the next bit size. No - blocking of the codes is performed, so the next code at - the increased size should be read from the input stream - immediately after where the previous code at the smaller - bit size was read. Again, the decompressor should not - increase the code size used until the sequence 256,1 is - encountered. - -2) When the table becomes full, total clearing is not - performed. Rather, when the compressor emits the code - sequence 256,2 (decimal), the decompressor should clear - all leaf nodes from the Ziv-Lempel tree, and continue to - use the current code size. The nodes that are cleared - from the Ziv-Lempel tree are then re-used, with the lowest - code value re-used first, and the highest code value - re-used last. The compressor can emit the sequence 256,2 - at any time. - -Expanding - Methods 2-5 ------------------------ - -The Reducing algorithm is actually a combination of two -distinct algorithms. The first algorithm compresses repeated -byte sequences, and the second algorithm takes the compressed -stream from the first algorithm and applies a probabilistic -compression method. - -The probabilistic compression stores an array of 'follower -sets' S(j), for j=0 to 255, corresponding to each possible -ASCII character. Each set contains between 0 and 32 -characters, to be denoted as S(j)[0],...,S(j)[m], where m<32. -The sets are stored at the beginning of the data area for a -Reduced file, in reverse order, with S(255) first, and S(0) -last. - -The sets are encoded as { N(j), S(j)[0],...,S(j)[N(j)-1] }, -where N(j) is the size of set S(j). N(j) can be 0, in which -case the follower set for S(j) is empty. Each N(j) value is -encoded in 6 bits, followed by N(j) eight bit character values -corresponding to S(j)[0] to S(j)[N(j)-1] respectively. If -N(j) is 0, then no values for S(j) are stored, and the value -for N(j-1) immediately follows. - -Immediately after the follower sets, is the compressed data -stream. The compressed data stream can be interpreted for the -probabilistic decompression as follows: - -let Last-Character <- 0. -loop until done - if the follower set S(Last-Character) is empty then - read 8 bits from the input stream, and copy this - value to the output stream. - otherwise if the follower set S(Last-Character) is non-empty then - read 1 bit from the input stream. - if this bit is not zero then - read 8 bits from the input stream, and copy this - value to the output stream. - otherwise if this bit is zero then - read B(N(Last-Character)) bits from the input - stream, and assign this value to I. - Copy the value of S(Last-Character)[I] to the - output stream. - - assign the last value placed on the output stream to - Last-Character. -end loop - -B(N(j)) is defined as the minimal number of bits required to -encode the value N(j)-1. - -The decompressed stream from above can then be expanded to -re-create the original file as follows: - -let State <- 0. - -loop until done - read 8 bits from the input stream into C. - case State of - 0: if C is not equal to DLE (144 decimal) then - copy C to the output stream. - otherwise if C is equal to DLE then - let State <- 1. - - 1: if C is non-zero then - let V <- C. - let Len <- L(V) - let State <- F(Len). - otherwise if C is zero then - copy the value 144 (decimal) to the output stream. - let State <- 0 - - 2: let Len <- Len + C - let State <- 3. - - 3: move backwards D(V,C) bytes in the output stream - (if this position is before the start of the output - stream, then assume that all the data before the - start of the output stream is filled with zeros). - copy Len+3 bytes from this position to the output stream. - let State <- 0. - end case -end loop - -The functions F,L, and D are dependent on the 'compression -factor', 1 through 4, and are defined as follows: - -For compression factor 1: - L(X) equals the lower 7 bits of X. - F(X) equals 2 if X equals 127 otherwise F(X) equals 3. - D(X,Y) equals the (upper 1 bit of X) * 256 + Y + 1. -For compression factor 2: - L(X) equals the lower 6 bits of X. - F(X) equals 2 if X equals 63 otherwise F(X) equals 3. - D(X,Y) equals the (upper 2 bits of X) * 256 + Y + 1. -For compression factor 3: - L(X) equals the lower 5 bits of X. - F(X) equals 2 if X equals 31 otherwise F(X) equals 3. - D(X,Y) equals the (upper 3 bits of X) * 256 + Y + 1. -For compression factor 4: - L(X) equals the lower 4 bits of X. - F(X) equals 2 if X equals 15 otherwise F(X) equals 3. - D(X,Y) equals the (upper 4 bits of X) * 256 + Y + 1. - -Imploding - Method 6 --------------------- - -The Imploding algorithm is actually a combination of two distinct -algorithms. The first algorithm compresses repeated byte -sequences using a sliding dictionary. The second algorithm is -used to compress the encoding of the sliding dictionary output, -using multiple Shannon-Fano trees. - -The Imploding algorithm can use a 4K or 8K sliding dictionary -size. The dictionary size used can be determined by bit 1 in the -general purpose flag word; a 0 bit indicates a 4K dictionary -while a 1 bit indicates an 8K dictionary. - -The Shannon-Fano trees are stored at the start of the compressed -file. The number of trees stored is defined by bit 2 in the -general purpose flag word; a 0 bit indicates two trees stored, a -1 bit indicates three trees are stored. If 3 trees are stored, -the first Shannon-Fano tree represents the encoding of the -Literal characters, the second tree represents the encoding of -the Length information, the third represents the encoding of the -Distance information. When 2 Shannon-Fano trees are stored, the -Length tree is stored first, followed by the Distance tree. - -The Literal Shannon-Fano tree, if present is used to represent -the entire ASCII character set, and contains 256 values. This -tree is used to compress any data not compressed by the sliding -dictionary algorithm. When this tree is present, the Minimum -Match Length for the sliding dictionary is 3. If this tree is -not present, the Minimum Match Length is 2. - -The Length Shannon-Fano tree is used to compress the Length part -of the (length,distance) pairs from the sliding dictionary -output. The Length tree contains 64 values, ranging from the -Minimum Match Length, to 63 plus the Minimum Match Length. - -The Distance Shannon-Fano tree is used to compress the Distance -part of the (length,distance) pairs from the sliding dictionary -output. The Distance tree contains 64 values, ranging from 0 to -63, representing the upper 6 bits of the distance value. The -distance values themselves will be between 0 and the sliding -dictionary size, either 4K or 8K. - -The Shannon-Fano trees themselves are stored in a compressed -format. The first byte of the tree data represents the number of -bytes of data representing the (compressed) Shannon-Fano tree -minus 1. The remaining bytes represent the Shannon-Fano tree -data encoded as: - - High 4 bits: Number of values at this bit length + 1. (1 - 16) - Low 4 bits: Bit Length needed to represent value + 1. (1 - 16) - -The Shannon-Fano codes can be constructed from the bit lengths -using the following algorithm: - -1) Sort the Bit Lengths in ascending order, while retaining the - order of the original lengths stored in the file. - -2) Generate the Shannon-Fano trees: - - Code <- 0 - CodeIncrement <- 0 - LastBitLength <- 0 - i <- number of Shannon-Fano codes - 1 (either 255 or 63) - - loop while i >= 0 - Code = Code + CodeIncrement - if BitLength(i) <> LastBitLength then - LastBitLength=BitLength(i) - CodeIncrement = 1 shifted left (16 - LastBitLength) - ShannonCode(i) = Code - i <- i - 1 - end loop - -3) Reverse the order of all the bits in the above ShannonCode() - vector, so that the most significant bit becomes the least - significant bit. For example, the value 0x1234 (hex) would - become 0x2C48 (hex). - -4) Restore the order of Shannon-Fano codes as originally stored - within the file. - -Example: - - This example will show the encoding of a Shannon-Fano tree - of size 8. Notice that the actual Shannon-Fano trees used - for Imploding are either 64 or 256 entries in size. - -Example: 0x02, 0x42, 0x01, 0x13 - - The first byte indicates 3 values in this table. Decoding the - bytes: - 0x42 = 5 codes of 3 bits long - 0x01 = 1 code of 2 bits long - 0x13 = 2 codes of 4 bits long - - This would generate the original bit length array of: - (3, 3, 3, 3, 3, 2, 4, 4) - - There are 8 codes in this table for the values 0 thru 7. Using - the algorithm to obtain the Shannon-Fano codes produces: - - Reversed Order Original -Val Sorted Constructed Code Value Restored Length ---- ------ ----------------- -------- -------- ------ -0: 2 1100000000000000 11 101 3 -1: 3 1010000000000000 101 001 3 -2: 3 1000000000000000 001 110 3 -3: 3 0110000000000000 110 010 3 -4: 3 0100000000000000 010 100 3 -5: 3 0010000000000000 100 11 2 -6: 4 0001000000000000 1000 1000 4 -7: 4 0000000000000000 0000 0000 4 - -The values in the Val, Order Restored and Original Length columns -now represent the Shannon-Fano encoding tree that can be used for -decoding the Shannon-Fano encoded data. How to parse the -variable length Shannon-Fano values from the data stream is beyond -the scope of this document. (See the references listed at the end of -this document for more information.) However, traditional decoding -schemes used for Huffman variable length decoding, such as the -Greenlaw algorithm, can be successfully applied. - -The compressed data stream begins immediately after the -compressed Shannon-Fano data. The compressed data stream can be -interpreted as follows: - -loop until done - read 1 bit from input stream. - - if this bit is non-zero then (encoded data is literal data) - if Literal Shannon-Fano tree is present - read and decode character using Literal Shannon-Fano tree. - otherwise - read 8 bits from input stream. - copy character to the output stream. - otherwise (encoded data is sliding dictionary match) - if 8K dictionary size - read 7 bits for offset Distance (lower 7 bits of offset). - otherwise - read 6 bits for offset Distance (lower 6 bits of offset). - - using the Distance Shannon-Fano tree, read and decode the - upper 6 bits of the Distance value. - - using the Length Shannon-Fano tree, read and decode - the Length value. - - Length <- Length + Minimum Match Length - - if Length = 63 + Minimum Match Length - read 8 bits from the input stream, - add this value to Length. - - move backwards Distance+1 bytes in the output stream, and - copy Length characters from this position to the output - stream. (if this position is before the start of the output - stream, then assume that all the data before the start of - the output stream is filled with zeros). -end loop - -Tokenizing - Method 7 ---------------------- - -This method is not used by PKZIP. - -Deflating - Method 8 --------------------- - -The Deflate algorithm is similar to the Implode algorithm using -a sliding dictionary of up to 32K with secondary compression -from Huffman/Shannon-Fano codes. - -The compressed data is stored in blocks with a header describing -the block and the Huffman codes used in the data block. The header -format is as follows: - - Bit 0: Last Block bit This bit is set to 1 if this is the last - compressed block in the data. - Bits 1-2: Block type - 00 (0) - Block is stored - All stored data is byte aligned. - Skip bits until next byte, then next word = block - length, followed by the ones compliment of the block - length word. Remaining data in block is the stored - data. - - 01 (1) - Use fixed Huffman codes for literal and distance codes. - Lit Code Bits Dist Code Bits - --------- ---- --------- ---- - 0 - 143 8 0 - 31 5 - 144 - 255 9 - 256 - 279 7 - 280 - 287 8 - - Literal codes 286-287 and distance codes 30-31 are - never used but participate in the huffman construction. - - 10 (2) - Dynamic Huffman codes. (See expanding Huffman codes) - - 11 (3) - Reserved - Flag a "Error in compressed data" if seen. - -Expanding Huffman Codes ------------------------ -If the data block is stored with dynamic Huffman codes, the Huffman -codes are sent in the following compressed format: - - 5 Bits: # of Literal codes sent - 256 (256 - 286) - All other codes are never sent. - 5 Bits: # of Dist codes - 1 (1 - 32) - 4 Bits: # of Bit Length codes - 3 (3 - 19) - -The Huffman codes are sent as bit lengths and the codes are built as -described in the implode algorithm. The bit lengths themselves are -compressed with Huffman codes. There are 19 bit length codes: - - 0 - 15: Represent bit lengths of 0 - 15 - 16: Copy the previous bit length 3 - 6 times. - The next 2 bits indicate repeat length (0 = 3, ... ,3 = 6) - Example: Codes 8, 16 (+2 bits 11), 16 (+2 bits 10) will - expand to 12 bit lengths of 8 (1 + 6 + 5) - 17: Repeat a bit length of 0 for 3 - 10 times. (3 bits of length) - 18: Repeat a bit length of 0 for 11 - 138 times (7 bits of length) - -The lengths of the bit length codes are sent packed 3 bits per value -(0 - 7) in the following order: - - 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 - -The Huffman codes should be built as described in the Implode algorithm -except codes are assigned starting at the shortest bit length, i.e. the -shortest code should be all 0's rather than all 1's. Also, codes with -a bit length of zero do not participate in the tree construction. The -codes are then used to decode the bit lengths for the literal and -distance tables. - -The bit lengths for the literal tables are sent first with the number -of entries sent described by the 5 bits sent earlier. There are up -to 286 literal characters; the first 256 represent the respective 8 -bit character, code 256 represents the End-Of-Block code, the remaining -29 codes represent copy lengths of 3 thru 258. There are up to 30 -distance codes representing distances from 1 thru 32k as described -below. - - Length Codes - ------------ - Extra Extra Extra Extra - Code Bits Length Code Bits Lengths Code Bits Lengths Code Bits Length(s) - ---- ---- ------ ---- ---- ------- ---- ---- ------- ---- ---- --------- - 257 0 3 265 1 11,12 273 3 35-42 281 5 131-162 - 258 0 4 266 1 13,14 274 3 43-50 282 5 163-194 - 259 0 5 267 1 15,16 275 3 51-58 283 5 195-226 - 260 0 6 268 1 17,18 276 3 59-66 284 5 227-257 - 261 0 7 269 2 19-22 277 4 67-82 285 0 258 - 262 0 8 270 2 23-26 278 4 83-98 - 263 0 9 271 2 27-30 279 4 99-114 - 264 0 10 272 2 31-34 280 4 115-130 - - Distance Codes - -------------- - Extra Extra Extra Extra - Code Bits Dist Code Bits Dist Code Bits Distance Code Bits Distance - ---- ---- ---- ---- ---- ------ ---- ---- -------- ---- ---- -------- - 0 0 1 8 3 17-24 16 7 257-384 24 11 4097-6144 - 1 0 2 9 3 25-32 17 7 385-512 25 11 6145-8192 - 2 0 3 10 4 33-48 18 8 513-768 26 12 8193-12288 - 3 0 4 11 4 49-64 19 8 769-1024 27 12 12289-16384 - 4 1 5,6 12 5 65-96 20 9 1025-1536 28 13 16385-24576 - 5 1 7,8 13 5 97-128 21 9 1537-2048 29 13 24577-32768 - 6 2 9-12 14 6 129-192 22 10 2049-3072 - 7 2 13-16 15 6 193-256 23 10 3073-4096 - -The compressed data stream begins immediately after the -compressed header data. The compressed data stream can be -interpreted as follows: - -do - read header from input stream. - - if stored block - skip bits until byte aligned - read count and 1's compliment of count - copy count bytes data block - otherwise - loop until end of block code sent - decode literal character from input stream - if literal < 256 - copy character to the output stream - otherwise - if literal = end of block - break from loop - otherwise - decode distance from input stream - - move backwards distance bytes in the output stream, and - copy length characters from this position to the output - stream. - end loop -while not last block - -if data descriptor exists - skip bits until byte aligned - read crc and sizes -endif - -Enhanced Deflating - Method 9 ------------------------------ - -The Enhanced Deflating algorithm is similar to Deflate but -uses a sliding dictionary of up to 64K. Deflate64(tm) is supported -by the Deflate extractor. - -BZIP2 - Method 12 ------------------ - -BZIP2 is an open-source data compression algorithm developed by -Julian Seward. Information and source code for this algorithm -can be found on the internet. - -LZMA - Method 14 (EFS) ----------------------- - -LZMA is a block-oriented, general purpose data compression algorithm -developed and maintained by Igor Pavlov. It is a derivative of LZ77 -that utilizes Markov chains and a range coder. Information and -source code for this algorithm can be found on the internet. Consult -with the author of this algorithm for information on terms or -restrictions on use. - -Support for LZMA within the ZIP format is defined as follows: - -The Compression method field within the ZIP Local and Central -Header records will be set to the value 14 to indicate data was -compressed using LZMA. - -The Version needed to extract field within the ZIP Local and -Central Header records will be set to 6.3 to indicate the -minimum ZIP format version supporting this feature. - -File data compressed using the LZMA algorithm must be placed -immediately following the Local Header for the file. If a -standard ZIP encryption header is required, it will follow -the Local Header and will precede the LZMA compressed file -data segment. The location of LZMA compressed data segment -within the ZIP format will be as shown: - - [local header file 1] - [encryption header file 1] - [LZMA compressed data segment for file 1] - [data descriptor 1] - [local header file 2] - -The encryption header and data descriptor records may -be conditionally present. The LZMA Compressed Data Segment -will consist of an LZMA Properties Header followed by the -LZMA Compressed Data as shown: - - [LZMA properties header for file 1] - [LZMA compressed data for file 1] - -The LZMA Compressed Data will be stored as provided by the -LZMA compression library. Compressed size, uncompressed -size and other file characteristics about the file being -compressed must be stored in standard ZIP storage format. - -The LZMA Properties Header will store specific data required to -decompress the LZMA compressed Data. This data is set by the -LZMA compression engine using the function WriteCoderProperties() -as documented within the LZMA SDK. - -Storage fields for the property information within the LZMA -Properties Header are as follows: - - LZMA Version Information 2 bytes - LZMA Properties Size 2 bytes - LZMA Properties Data variable, defined by "LZMA Properties Size" - -LZMA Version Information - this field identifies which version of - the LZMA SDK was used to compress a file. The first byte will - store the major version number of the LZMA SDK and the second - byte will store the minor number. - -LZMA Properties Size - this field defines the size of the remaining - property data. Typically this size should be determined by the - version of the SDK. This size field is included as a convenience - and to help avoid any ambiguity should it arise in the future due - to changes in this compression algorithm. - -LZMA Property Data - this variable sized field records the required - values for the decompressor as defined by the LZMA SDK. The - data stored in this field should be obtained using the - WriteCoderProperties() in the version of the SDK defined by - the "LZMA Version Information" field. - -The layout of the "LZMA Properties Data" field is a function of the -LZMA compression algorithm. It is possible that this layout may be -changed by the author over time. The data layout in version 4.32 -of the LZMA SDK defines a 5 byte array that uses 4 bytes to store -the dictionary size in little-endian order. This is preceded by a -single packed byte as the first element of the array that contains -the following fields: - - PosStateBits - LiteralPosStateBits - LiteralContextBits - -Refer to the LZMA documentation for a more detailed explanation of -these fields. - -Data compressed with method 14, LZMA, may include an end-of-stream -(EOS) marker ending the compressed data stream. This marker is not -required, but its use is highly recommended to facilitate processing -and implementers should include the EOS marker whenever possible. -When the EOS marker is used, general purpose bit 1 must be set. If -general purpose bit 1 is not set, the EOS marker is not present. - -WavPack - Method 97 -------------------- - -Information describing the use of compression method 97 is -provided by WinZIP International, LLC. This method relies on the -open source WavPack audio compression utility developed by David Bryant. -Information on WavPack is available at www.wavpack.com. Please consult -with the author of this algorithm for information on terms and -restrictions on use. - -WavPack data for a file begins immediately after the end of the -local header data. This data is the output from WavPack compression -routines. Within the ZIP file, the use of WavPack compression is -indicated by setting the compression method field to a value of 97 -in both the local header and the central directory header. The Version -needed to extract and version made by fields use the same values as are -used for data compressed using the Deflate algorithm. - -An implementation note for storing digital sample data when using -WavPack compression within ZIP files is that all of the bytes of -the sample data should be compressed. This includes any unused -bits up to the byte boundary. An example is a 2 byte sample that -uses only 12 bits for the sample data with 4 unused bits. If only -12 bits are passed as the sample size to the WavPack routines, the 4 -unused bits will be set to 0 on extraction regardless of their original -state. To avoid this, the full 16 bits of the sample data size -should be provided. - -PPMd - Method 98 ----------------- - -PPMd is a data compression algorithm developed by Dmitry Shkarin -which includes a carryless rangecoder developed by Dmitry Subbotin. -This algorithm is based on predictive phrase matching on multiple -order contexts. Information and source code for this algorithm -can be found on the internet. Consult with the author of this -algorithm for information on terms or restrictions on use. - -Support for PPMd within the ZIP format currently is provided only -for version I, revision 1 of the algorithm. Storage requirements -for using this algorithm are as follows: - -Parameters needed to control the algorithm are stored in the two -bytes immediately preceding the compressed data. These bytes are -used to store the following fields: - -Model order - sets the maximum model order, default is 8, possible - values are from 2 to 16 inclusive - -Sub-allocator size - sets the size of sub-allocator in MB, default is 50, - possible values are from 1MB to 256MB inclusive - -Model restoration method - sets the method used to restart context - model at memory insufficiency, values are: - - 0 - restarts model from scratch - default - 1 - cut off model - decreases performance by as much as 2x - 2 - freeze context tree - not recommended - -An example for packing these fields into the 2 byte storage field is -illustrated below. These values are stored in Intel low-byte/high-byte -order. - -wPPMd = (Model order - 1) + - ((Sub-allocator size - 1) << 4) + - (Model restoration method << 12) - - -VII. Traditional PKWARE Encryption ----------------------------------- - -The following information discusses the decryption steps -required to support traditional PKWARE encryption. This -form of encryption is considered weak by today's standards -and its use is recommended only for situations with -low security needs or for compatibility with older .ZIP -applications. - -Decryption ----------- - -PKWARE is grateful to Mr. Roger Schlafly for his expert contribution -towards the development of PKWARE's traditional encryption. - -PKZIP encrypts the compressed data stream. Encrypted files must -be decrypted before they can be extracted. - -Each encrypted file has an extra 12 bytes stored at the start of -the data area defining the encryption header for that file. The -encryption header is originally set to random values, and then -itself encrypted, using three, 32-bit keys. The key values are -initialized using the supplied encryption password. After each byte -is encrypted, the keys are then updated using pseudo-random number -generation techniques in combination with the same CRC-32 algorithm -used in PKZIP and described elsewhere in this document. - -The following is the basic steps required to decrypt a file: - -1) Initialize the three 32-bit keys with the password. -2) Read and decrypt the 12-byte encryption header, further - initializing the encryption keys. -3) Read and decrypt the compressed data stream using the - encryption keys. - -Step 1 - Initializing the encryption keys ------------------------------------------ - -Key(0) <- 305419896 -Key(1) <- 591751049 -Key(2) <- 878082192 - -loop for i <- 0 to length(password)-1 - update_keys(password(i)) -end loop - -Where update_keys() is defined as: - -update_keys(char): - Key(0) <- crc32(key(0),char) - Key(1) <- Key(1) + (Key(0) & 000000ffH) - Key(1) <- Key(1) * 134775813 + 1 - Key(2) <- crc32(key(2),key(1) >> 24) -end update_keys - -Where crc32(old_crc,char) is a routine that given a CRC value and a -character, returns an updated CRC value after applying the CRC-32 -algorithm described elsewhere in this document. - -Step 2 - Decrypting the encryption header ------------------------------------------ - -The purpose of this step is to further initialize the encryption -keys, based on random data, to render a plaintext attack on the -data ineffective. - -Read the 12-byte encryption header into Buffer, in locations -Buffer(0) thru Buffer(11). - -loop for i <- 0 to 11 - C <- buffer(i) ^ decrypt_byte() - update_keys(C) - buffer(i) <- C -end loop - -Where decrypt_byte() is defined as: - -unsigned char decrypt_byte() - local unsigned short temp - temp <- Key(2) | 2 - decrypt_byte <- (temp * (temp ^ 1)) >> 8 -end decrypt_byte - -After the header is decrypted, the last 1 or 2 bytes in Buffer -should be the high-order word/byte of the CRC for the file being -decrypted, stored in Intel low-byte/high-byte order. Versions of -PKZIP prior to 2.0 used a 2 byte CRC check; a 1 byte CRC check is -used on versions after 2.0. This can be used to test if the password -supplied is correct or not. - -Step 3 - Decrypting the compressed data stream ----------------------------------------------- - -The compressed data stream can be decrypted as follows: - -loop until done - read a character into C - Temp <- C ^ decrypt_byte() - update_keys(temp) - output Temp -end loop - - -VIII. Strong Encryption Specification -------------------------------------- - -The Strong Encryption technology defined in this specification is -covered under a pending patent application. The use or implementation -in a product of certain technological aspects set forth in the current -APPNOTE, including those with regard to strong encryption, patching, -or extended tape operations requires a license from PKWARE. Portions -of this Strong Encryption technology are available for use at no charge. -Contact PKWARE for licensing terms and conditions. Refer to section II -of this APPNOTE (Contacting PKWARE) for information on how to -contact PKWARE. - -Version 5.x of this specification introduced support for strong -encryption algorithms. These algorithms can be used with either -a password or an X.509v3 digital certificate to encrypt each file. -This format specification supports either password or certificate -based encryption to meet the security needs of today, to enable -interoperability between users within both PKI and non-PKI -environments, and to ensure interoperability between different -computing platforms that are running a ZIP program. - -Password based encryption is the most common form of encryption -people are familiar with. However, inherent weaknesses with -passwords (e.g. susceptibility to dictionary/brute force attack) -as well as password management and support issues make certificate -based encryption a more secure and scalable option. Industry -efforts and support are defining and moving towards more advanced -security solutions built around X.509v3 digital certificates and -Public Key Infrastructures(PKI) because of the greater scalability, -administrative options, and more robust security over traditional -password based encryption. - -Most standard encryption algorithms are supported with this -specification. Reference implementations for many of these -algorithms are available from either commercial or open source -distributors. Readily available cryptographic toolkits make -implementation of the encryption features straight-forward. -This document is not intended to provide a treatise on data -encryption principles or theory. Its purpose is to document the -data structures required for implementing interoperable data -encryption within the .ZIP format. It is strongly recommended that -you have a good understanding of data encryption before reading -further. - -The algorithms introduced in Version 5.0 of this specification -include: - - RC2 40 bit, 64 bit, and 128 bit - RC4 40 bit, 64 bit, and 128 bit - DES - 3DES 112 bit and 168 bit - -Version 5.1 adds support for the following: - - AES 128 bit, 192 bit, and 256 bit - - -Version 6.1 introduces encryption data changes to support -interoperability with Smartcard and USB Token certificate storage -methods which do not support the OAEP strengthening standard. - -Version 6.2 introduces support for encrypting metadata by compressing -and encrypting the central directory data structure to reduce information -leakage. Information leakage can occur in legacy ZIP applications -through exposure of information about a file even though that file is -stored encrypted. The information exposed consists of file -characteristics stored within the records and fields defined by this -specification. This includes data such as a files name, its original -size, timestamp and CRC32 value. - -Version 6.3 introduces support for encrypting data using the Blowfish -and Twofish algorithms. These are symmetric block ciphers developed -by Bruce Schneier. Blowfish supports using a variable length key from -32 to 448 bits. Block size is 64 bits. Implementations should use 16 -rounds and the only mode supported within ZIP files is CBC. Twofish -supports key sizes 128, 192 and 256 bits. Block size is 128 bits. -Implementations should use 16 rounds and the only mode supported within -ZIP files is CBC. Information and source code for both Blowfish and -Twofish algorithms can be found on the internet. Consult with the author -of these algorithms for information on terms or restrictions on use. - -Central Directory Encryption provides greater protection against -information leakage by encrypting the Central Directory structure and -by masking key values that are replicated in the unencrypted Local -Header. ZIP compatible programs that cannot interpret an encrypted -Central Directory structure cannot rely on the data in the corresponding -Local Header for decompression information. - -Extra Field records that may contain information about a file that should -not be exposed should not be stored in the Local Header and should only -be written to the Central Directory where they can be encrypted. This -design currently does not support streaming. Information in the End of -Central Directory record, the Zip64 End of Central Directory Locator, -and the Zip64 End of Central Directory records are not encrypted. Access -to view data on files within a ZIP file with an encrypted Central Directory -requires the appropriate password or private key for decryption prior to -viewing any files, or any information about the files, in the archive. - -Older ZIP compatible programs not familiar with the Central Directory -Encryption feature will no longer be able to recognize the Central -Directory and may assume the ZIP file is corrupt. Programs that -attempt streaming access using Local Headers will see invalid -information for each file. Central Directory Encryption need not be -used for every ZIP file. Its use is recommended for greater security. -ZIP files not using Central Directory Encryption should operate as -in the past. - -This strong encryption feature specification is intended to provide for -scalable, cross-platform encryption needs ranging from simple password -encryption to authenticated public/private key encryption. - -Encryption provides data confidentiality and privacy. It is -recommended that you combine X.509 digital signing with encryption -to add authentication and non-repudiation. - - -Single Password Symmetric Encryption Method: -------------------------------------------- - -The Single Password Symmetric Encryption Method using strong -encryption algorithms operates similarly to the traditional -PKWARE encryption defined in this format. Additional data -structures are added to support the processing needs of the -strong algorithms. - -The Strong Encryption data structures are: - -1. General Purpose Bits - Bits 0 and 6 of the General Purpose bit -flag in both local and central header records. Both bits set -indicates strong encryption. Bit 13, when set indicates the Central -Directory is encrypted and that selected fields in the Local Header -are masked to hide their actual value. - - -2. Extra Field 0x0017 in central header only. - - Fields to consider in this record are: - - Format - the data format identifier for this record. The only - value allowed at this time is the integer value 2. - - AlgId - integer identifier of the encryption algorithm from the - following range - - 0x6601 - DES - 0x6602 - RC2 (version needed to extract < 5.2) - 0x6603 - 3DES 168 - 0x6609 - 3DES 112 - 0x660E - AES 128 - 0x660F - AES 192 - 0x6610 - AES 256 - 0x6702 - RC2 (version needed to extract >= 5.2) - 0x6720 - Blowfish - 0x6721 - Twofish - 0x6801 - RC4 - 0xFFFF - Unknown algorithm - - Bitlen - Explicit bit length of key - - 32 - 448 bits - - Flags - Processing flags needed for decryption - - 0x0001 - Password is required to decrypt - 0x0002 - Certificates only - 0x0003 - Password or certificate required to decrypt - - Values > 0x0003 reserved for certificate processing - - -3. Decryption header record preceding compressed file data. - - -Decryption Header: - - Value Size Description - ----- ---- ----------- - IVSize 2 bytes Size of initialization vector (IV) - IVData IVSize Initialization vector for this file - Size 4 bytes Size of remaining decryption header data - Format 2 bytes Format definition for this record - AlgID 2 bytes Encryption algorithm identifier - Bitlen 2 bytes Bit length of encryption key - Flags 2 bytes Processing flags - ErdSize 2 bytes Size of Encrypted Random Data - ErdData ErdSize Encrypted Random Data - Reserved1 4 bytes Reserved certificate processing data - Reserved2 (var) Reserved for certificate processing data - VSize 2 bytes Size of password validation data - VData VSize-4 Password validation data - VCRC32 4 bytes Standard ZIP CRC32 of password validation data - - IVData - The size of the IV should match the algorithm block size. - The IVData can be completely random data. If the size of - the randomly generated data does not match the block size - it should be complemented with zero's or truncated as - necessary. If IVSize is 0,then IV = CRC32 + Uncompressed - File Size (as a 64 bit little-endian, unsigned integer value). - - Format - the data format identifier for this record. The only - value allowed at this time is the integer value 3. - - AlgId - integer identifier of the encryption algorithm from the - following range - - 0x6601 - DES - 0x6602 - RC2 (version needed to extract < 5.2) - 0x6603 - 3DES 168 - 0x6609 - 3DES 112 - 0x660E - AES 128 - 0x660F - AES 192 - 0x6610 - AES 256 - 0x6702 - RC2 (version needed to extract >= 5.2) - 0x6720 - Blowfish - 0x6721 - Twofish - 0x6801 - RC4 - 0xFFFF - Unknown algorithm - - Bitlen - Explicit bit length of key - - 32 - 448 bits - - Flags - Processing flags needed for decryption - - 0x0001 - Password is required to decrypt - 0x0002 - Certificates only - 0x0003 - Password or certificate required to decrypt - - Values > 0x0003 reserved for certificate processing - - ErdData - Encrypted random data is used to store random data that - is used to generate a file session key for encrypting - each file. SHA1 is used to calculate hash data used to - derive keys. File session keys are derived from a master - session key generated from the user-supplied password. - If the Flags field in the decryption header contains - the value 0x4000, then the ErdData field must be - decrypted using 3DES. If the value 0x4000 is not set, - then the ErdData field must be decrypted using AlgId. - - - Reserved1 - Reserved for certificate processing, if value is - zero, then Reserved2 data is absent. See the explanation - under the Certificate Processing Method for details on - this data structure. - - Reserved2 - If present, the size of the Reserved2 data structure - is located by skipping the first 4 bytes of this field - and using the next 2 bytes as the remaining size. See - the explanation under the Certificate Processing Method - for details on this data structure. - - VSize - This size value will always include the 4 bytes of the - VCRC32 data and will be greater than 4 bytes. - - VData - Random data for password validation. This data is VSize - in length and VSize must be a multiple of the encryption - block size. VCRC32 is a checksum value of VData. - VData and VCRC32 are stored encrypted and start the - stream of encrypted data for a file. - - -4. Useful Tips - -Strong Encryption is always applied to a file after compression. The -block oriented algorithms all operate in Cypher Block Chaining (CBC) -mode. The block size used for AES encryption is 16. All other block -algorithms use a block size of 8. Two ID's are defined for RC2 to -account for a discrepancy found in the implementation of the RC2 -algorithm in the cryptographic library on Windows XP SP1 and all -earlier versions of Windows. It is recommended that zero length files -not be encrypted, however programs should be prepared to extract them -if they are found within a ZIP file. - -A pseudo-code representation of the encryption process is as follows: - -Password = GetUserPassword() -MasterSessionKey = DeriveKey(SHA1(Password)) -RD = CryptographicStrengthRandomData() -For Each File - IV = CryptographicStrengthRandomData() - VData = CryptographicStrengthRandomData() - VCRC32 = CRC32(VData) - FileSessionKey = DeriveKey(SHA1(IV + RD) - ErdData = Encrypt(RD,MasterSessionKey,IV) - Encrypt(VData + VCRC32 + FileData, FileSessionKey,IV) -Done - -The function names and parameter requirements will depend on -the choice of the cryptographic toolkit selected. Almost any -toolkit supporting the reference implementations for each -algorithm can be used. The RSA BSAFE(r), OpenSSL, and Microsoft -CryptoAPI libraries are all known to work well. - - -Single Password - Central Directory Encryption: ------------------------------------------------ - -Central Directory Encryption is achieved within the .ZIP format by -encrypting the Central Directory structure. This encapsulates the metadata -most often used for processing .ZIP files. Additional metadata is stored for -redundancy in the Local Header for each file. The process of concealing -metadata by encrypting the Central Directory does not protect the data within -the Local Header. To avoid information leakage from the exposed metadata -in the Local Header, the fields containing information about a file are masked. - -Local Header: - -Masking replaces the true content of the fields for a file in the Local -Header with false information. When masked, the Local Header is not -suitable for streaming access and the options for data recovery of damaged -archives is reduced. Extra Data fields that may contain confidential -data should not be stored within the Local Header. The value set into -the Version needed to extract field should be the correct value needed to -extract the file without regard to Central Directory Encryption. The fields -within the Local Header targeted for masking when the Central Directory is -encrypted are: - - Field Name Mask Value - ------------------ --------------------------- - compression method 0 - last mod file time 0 - last mod file date 0 - crc-32 0 - compressed size 0 - uncompressed size 0 - file name (variable size) Base 16 value from the - range 1 - 0xFFFFFFFFFFFFFFFF - represented as a string whose - size will be set into the - file name length field - -The Base 16 value assigned as a masked file name is simply a sequentially -incremented value for each file starting with 1 for the first file. -Modifications to a ZIP file may cause different values to be stored for -each file. For compatibility, the file name field in the Local Header -should never be left blank. As of Version 6.2 of this specification, -the Compression Method and Compressed Size fields are not yet masked. -Fields having a value of 0xFFFF or 0xFFFFFFFF for the ZIP64 format -should not be masked. - -Encrypting the Central Directory: - -Encryption of the Central Directory does not include encryption of the -Central Directory Signature data, the Zip64 End of Central Directory -record, the Zip64 End of Central Directory Locator, or the End -of Central Directory record. The ZIP file comment data is never -encrypted. - -Before encrypting the Central Directory, it may optionally be compressed. -Compression is not required, but for storage efficiency it is assumed -this structure will be compressed before encrypting. Similarly, this -specification supports compressing the Central Directory without -requiring that it also be encrypted. Early implementations of this -feature will assume the encryption method applied to files matches the -encryption applied to the Central Directory. - -Encryption of the Central Directory is done in a manner similar to -that of file encryption. The encrypted data is preceded by a -decryption header. The decryption header is known as the Archive -Decryption Header. The fields of this record are identical to -the decryption header preceding each encrypted file. The location -of the Archive Decryption Header is determined by the value in the -Start of the Central Directory field in the Zip64 End of Central -Directory record. When the Central Directory is encrypted, the -Zip64 End of Central Directory record will always be present. - -The layout of the Zip64 End of Central Directory record for all -versions starting with 6.2 of this specification will follow the -Version 2 format. The Version 2 format is as follows: - -The leading fixed size fields within the Version 1 format for this -record remain unchanged. The record signature for both Version 1 -and Version 2 will be 0x06064b50. Immediately following the last -byte of the field known as the Offset of Start of Central -Directory With Respect to the Starting Disk Number will begin the -new fields defining Version 2 of this record. - -New fields for Version 2: - -Note: all fields stored in Intel low-byte/high-byte order. - - Value Size Description - ----- ---- ----------- - Compression Method 2 bytes Method used to compress the - Central Directory - Compressed Size 8 bytes Size of the compressed data - Original Size 8 bytes Original uncompressed size - AlgId 2 bytes Encryption algorithm ID - BitLen 2 bytes Encryption key length - Flags 2 bytes Encryption flags - HashID 2 bytes Hash algorithm identifier - Hash Length 2 bytes Length of hash data - Hash Data (variable) Hash data - -The Compression Method accepts the same range of values as the -corresponding field in the Central Header. - -The Compressed Size and Original Size values will not include the -data of the Central Directory Signature which is compressed or -encrypted. - -The AlgId, BitLen, and Flags fields accept the same range of values -the corresponding fields within the 0x0017 record. - -Hash ID identifies the algorithm used to hash the Central Directory -data. This data does not have to be hashed, in which case the -values for both the HashID and Hash Length will be 0. Possible -values for HashID are: - - Value Algorithm - ------ --------- - 0x0000 none - 0x0001 CRC32 - 0x8003 MD5 - 0x8004 SHA1 - 0x8007 RIPEMD160 - 0x800C SHA256 - 0x800D SHA384 - 0x800E SHA512 - -When the Central Directory data is signed, the same hash algorithm -used to hash the Central Directory for signing should be used. -This is recommended for processing efficiency, however, it is -permissible for any of the above algorithms to be used independent -of the signing process. - -The Hash Data will contain the hash data for the Central Directory. -The length of this data will vary depending on the algorithm used. - -The Version Needed to Extract should be set to 62. - -The value for the Total Number of Entries on the Current Disk will -be 0. These records will no longer support random access when -encrypting the Central Directory. - -When the Central Directory is compressed and/or encrypted, the -End of Central Directory record will store the value 0xFFFFFFFF -as the value for the Total Number of Entries in the Central -Directory. The value stored in the Total Number of Entries in -the Central Directory on this Disk field will be 0. The actual -values will be stored in the equivalent fields of the Zip64 -End of Central Directory record. - -Decrypting and decompressing the Central Directory is accomplished -in the same manner as decrypting and decompressing a file. - -Certificate Processing Method: ------------------------------ - -The Certificate Processing Method of for ZIP file encryption -defines the following additional data fields: - -1. Certificate Flag Values - -Additional processing flags that can be present in the Flags field of both -the 0x0017 field of the central directory Extra Field and the Decryption -header record preceding compressed file data are: - - 0x0007 - reserved for future use - 0x000F - reserved for future use - 0x0100 - Indicates non-OAEP key wrapping was used. If this - this field is set, the version needed to extract must - be at least 61. This means OAEP key wrapping is not - used when generating a Master Session Key using - ErdData. - 0x4000 - ErdData must be decrypted using 3DES-168, otherwise use the - same algorithm used for encrypting the file contents. - 0x8000 - reserved for future use - - -2. CertData - Extra Field 0x0017 record certificate data structure - -The data structure used to store certificate data within the section -of the Extra Field defined by the CertData field of the 0x0017 -record are as shown: - - Value Size Description - ----- ---- ----------- - RCount 4 bytes Number of recipients. - HashAlg 2 bytes Hash algorithm identifier - HSize 2 bytes Hash size - SRList (var) Simple list of recipients hashed public keys - - - RCount This defines the number intended recipients whose - public keys were used for encryption. This identifies - the number of elements in the SRList. - - HashAlg This defines the hash algorithm used to calculate - the public key hash of each public key used - for encryption. This field currently supports - only the following value for SHA-1 - - 0x8004 - SHA1 - - HSize This defines the size of a hashed public key. - - SRList This is a variable length list of the hashed - public keys for each intended recipient. Each - element in this list is HSize. The total size of - SRList is determined using RCount * HSize. - - -3. Reserved1 - Certificate Decryption Header Reserved1 Data: - - Value Size Description - ----- ---- ----------- - RCount 4 bytes Number of recipients. - - RCount This defines the number intended recipients whose - public keys were used for encryption. This defines - the number of elements in the REList field defined below. - - -4. Reserved2 - Certificate Decryption Header Reserved2 Data Structures: - - - Value Size Description - ----- ---- ----------- - HashAlg 2 bytes Hash algorithm identifier - HSize 2 bytes Hash size - REList (var) List of recipient data elements - - - HashAlg This defines the hash algorithm used to calculate - the public key hash of each public key used - for encryption. This field currently supports - only the following value for SHA-1 - - 0x8004 - SHA1 - - HSize This defines the size of a hashed public key - defined in REHData. - - REList This is a variable length of list of recipient data. - Each element in this list consists of a Recipient - Element data structure as follows: - - - Recipient Element (REList) Data Structure: - - Value Size Description - ----- ---- ----------- - RESize 2 bytes Size of REHData + REKData - REHData HSize Hash of recipients public key - REKData (var) Simple key blob - - - RESize This defines the size of an individual REList - element. This value is the combined size of the - REHData field + REKData field. REHData is defined by - HSize. REKData is variable and can be calculated - for each REList element using RESize and HSize. - - REHData Hashed public key for this recipient. - - REKData Simple Key Blob. The format of this data structure - is identical to that defined in the Microsoft - CryptoAPI and generated using the CryptExportKey() - function. The version of the Simple Key Blob - supported at this time is 0x02 as defined by - Microsoft. - -Certificate Processing - Central Directory Encryption: ------------------------------------------------------- - -Central Directory Encryption using Digital Certificates will -operate in a manner similar to that of Single Password Central -Directory Encryption. This record will only be present when there -is data to place into it. Currently, data is placed into this -record when digital certificates are used for either encrypting -or signing the files within a ZIP file. When only password -encryption is used with no certificate encryption or digital -signing, this record is not currently needed. When present, this -record will appear before the start of the actual Central Directory -data structure and will be located immediately after the Archive -Decryption Header if the Central Directory is encrypted. - -The Archive Extra Data record will be used to store the following -information. Additional data may be added in future versions. - -Extra Data Fields: - -0x0014 - PKCS#7 Store for X.509 Certificates -0x0016 - X.509 Certificate ID and Signature for central directory -0x0019 - PKCS#7 Encryption Recipient Certificate List - -The 0x0014 and 0x0016 Extra Data records that otherwise would be -located in the first record of the Central Directory for digital -certificate processing. When encrypting or compressing the Central -Directory, the 0x0014 and 0x0016 records must be located in the -Archive Extra Data record and they should not remain in the first -Central Directory record. The Archive Extra Data record will also -be used to store the 0x0019 data. - -When present, the size of the Archive Extra Data record will be -included in the size of the Central Directory. The data of the -Archive Extra Data record will also be compressed and encrypted -along with the Central Directory data structure. - -Certificate Processing Differences: - -The Certificate Processing Method of encryption differs from the -Single Password Symmetric Encryption Method as follows. Instead -of using a user-defined password to generate a master session key, -cryptographically random data is used. The key material is then -wrapped using standard key-wrapping techniques. This key material -is wrapped using the public key of each recipient that will need -to decrypt the file using their corresponding private key. - -This specification currently assumes digital certificates will follow -the X.509 V3 format for 1024 bit and higher RSA format digital -certificates. Implementation of this Certificate Processing Method -requires supporting logic for key access and management. This logic -is outside the scope of this specification. - -OAEP Processing with Certificate-based Encryption: - -OAEP stands for Optimal Asymmetric Encryption Padding. It is a -strengthening technique used for small encoded items such as decryption -keys. This is commonly applied in cryptographic key-wrapping techniques -and is supported by PKCS #1. Versions 5.0 and 6.0 of this specification -were designed to support OAEP key-wrapping for certificate-based -decryption keys for additional security. - -Support for private keys stored on Smartcards or Tokens introduced -a conflict with this OAEP logic. Most card and token products do -not support the additional strengthening applied to OAEP key-wrapped -data. In order to resolve this conflict, versions 6.1 and above of this -specification will no longer support OAEP when encrypting using -digital certificates. - -Versions of PKZIP available during initial development of the -certificate processing method set a value of 61 into the -version needed to extract field for a file. This indicates that -non-OAEP key wrapping is used. This affects certificate encryption -only, and password encryption functions should not be affected by -this value. This means values of 61 may be found on files encrypted -with certificates only, or on files encrypted with both password -encryption and certificate encryption. Files encrypted with both -methods can safely be decrypted using the password methods documented. - -IX. Change Process ------------------- - -In order for the .ZIP file format to remain a viable definition, this -specification should be considered as open for periodic review and -revision. Although this format was originally designed with a -certain level of extensibility, not all changes in technology -(present or future) were or will be necessarily considered in its -design. If your application requires new definitions to the -extensible sections in this format, or if you would like to -submit new data structures, please forward your request to -zipformat@pkware.com. All submissions will be reviewed by the -ZIP File Specification Committee for possible inclusion into -future versions of this specification. Periodic revisions -to this specification will be published to ensure interoperability. -We encourage comments and feedback that may help improve clarity -or content. - -X. Incorporating PKWARE Proprietary Technology into Your Product ----------------------------------------------------------------- - -PKWARE is committed to the interoperability and advancement of the -.ZIP format. PKWARE offers a free license for certain technological -aspects described above under certain restrictions and conditions. -However, the use or implementation in a product of certain technological -aspects set forth in the current APPNOTE, including those with regard to -strong encryption, patching, or extended tape operations requires a -license from PKWARE. Please contact PKWARE with regard to acquiring -a license. - -XI. Acknowledgements ---------------------- - -In addition to the above mentioned contributors to PKZIP and PKUNZIP, -I would like to extend special thanks to Robert Mahoney for suggesting -the extension .ZIP for this software. - -XII. References ---------------- - - Fiala, Edward R., and Greene, Daniel H., "Data compression with - finite windows", Communications of the ACM, Volume 32, Number 4, - April 1989, pages 490-505. - - Held, Gilbert, "Data Compression, Techniques and Applications, - Hardware and Software Considerations", John Wiley & Sons, 1987. - - Huffman, D.A., "A method for the construction of minimum-redundancy - codes", Proceedings of the IRE, Volume 40, Number 9, September 1952, - pages 1098-1101. - - Nelson, Mark, "LZW Data Compression", Dr. Dobbs Journal, Volume 14, - Number 10, October 1989, pages 29-37. - - Nelson, Mark, "The Data Compression Book", M&T Books, 1991. - - Storer, James A., "Data Compression, Methods and Theory", - Computer Science Press, 1988 - - Welch, Terry, "A Technique for High-Performance Data Compression", - IEEE Computer, Volume 17, Number 6, June 1984, pages 8-19. - - Ziv, J. and Lempel, A., "A universal algorithm for sequential data - compression", Communications of the ACM, Volume 30, Number 6, - June 1987, pages 520-540. - - Ziv, J. and Lempel, A., "Compression of individual sequences via - variable-rate coding", IEEE Transactions on Information Theory, - Volume 24, Number 5, September 1978, pages 530-536. - - -APPENDIX A - AS/400 Extra Field (0x0065) Attribute Definitions --------------------------------------------------------------- - -Field Definition Structure: - - a. field length including length 2 bytes - b. field code 2 bytes - c. data x bytes - -Field Code Description - 4001 Source type i.e. CLP etc - 4002 The text description of the library - 4003 The text description of the file - 4004 The text description of the member - 4005 x'F0' or 0 is PF-DTA, x'F1' or 1 is PF_SRC - 4007 Database Type Code 1 byte - 4008 Database file and fields definition - 4009 GZIP file type 2 bytes - 400B IFS code page 2 bytes - 400C IFS Creation Time 4 bytes - 400D IFS Access Time 4 bytes - 400E IFS Modification time 4 bytes - 005C Length of the records in the file 2 bytes - 0068 GZIP two words 8 bytes - -APPENDIX B - z/OS Extra Field (0x0065) Attribute Definitions ------------------------------------------------------------- - -Field Definition Structure: - - a. field length including length 2 bytes - b. field code 2 bytes - c. data x bytes - -Field Code Description - 0001 File Type 2 bytes - 0002 NonVSAM Record Format 1 byte - 0003 Reserved - 0004 NonVSAM Block Size 2 bytes Big Endian - 0005 Primary Space Allocation 3 bytes Big Endian - 0006 Secondary Space Allocation 3 bytes Big Endian - 0007 Space Allocation Type1 byte flag - 0008 Modification Date Retired with PKZIP 5.0 + - 0009 Expiration Date Retired with PKZIP 5.0 + - 000A PDS Directory Block Allocation 3 bytes Big Endian binary value - 000B NonVSAM Volume List variable - 000C UNIT Reference Retired with PKZIP 5.0 + - 000D DF/SMS Management Class 8 bytes EBCDIC Text Value - 000E DF/SMS Storage Class 8 bytes EBCDIC Text Value - 000F DF/SMS Data Class 8 bytes EBCDIC Text Value - 0010 PDS/PDSE Member Info. 30 bytes - 0011 VSAM sub-filetype 2 bytes - 0012 VSAM LRECL 13 bytes EBCDIC "(num_avg num_max)" - 0013 VSAM Cluster Name Retired with PKZIP 5.0 + - 0014 VSAM KSDS Key Information 13 bytes EBCDIC "(num_length num_position)" - 0015 VSAM Average LRECL 5 bytes EBCDIC num_value padded with blanks - 0016 VSAM Maximum LRECL 5 bytes EBCDIC num_value padded with blanks - 0017 VSAM KSDS Key Length 5 bytes EBCDIC num_value padded with blanks - 0018 VSAM KSDS Key Position 5 bytes EBCDIC num_value padded with blanks - 0019 VSAM Data Name 1-44 bytes EBCDIC text string - 001A VSAM KSDS Index Name 1-44 bytes EBCDIC text string - 001B VSAM Catalog Name 1-44 bytes EBCDIC text string - 001C VSAM Data Space Type 9 bytes EBCDIC text string - 001D VSAM Data Space Primary 9 bytes EBCDIC num_value left-justified - 001E VSAM Data Space Secondary 9 bytes EBCDIC num_value left-justified - 001F VSAM Data Volume List variable EBCDIC text list of 6-character Volume IDs - 0020 VSAM Data Buffer Space 8 bytes EBCDIC num_value left-justified - 0021 VSAM Data CISIZE 5 bytes EBCDIC num_value left-justified - 0022 VSAM Erase Flag 1 byte flag - 0023 VSAM Free CI % 3 bytes EBCDIC num_value left-justified - 0024 VSAM Free CA % 3 bytes EBCDIC num_value left-justified - 0025 VSAM Index Volume List variable EBCDIC text list of 6-character Volume IDs - 0026 VSAM Ordered Flag 1 byte flag - 0027 VSAM REUSE Flag 1 byte flag - 0028 VSAM SPANNED Flag 1 byte flag - 0029 VSAM Recovery Flag 1 byte flag - 002A VSAM WRITECHK Flag 1 byte flag - 002B VSAM Cluster/Data SHROPTS 3 bytes EBCDIC "n,y" - 002C VSAM Index SHROPTS 3 bytes EBCDIC "n,y" - 002D VSAM Index Space Type 9 bytes EBCDIC text string - 002E VSAM Index Space Primary 9 bytes EBCDIC num_value left-justified - 002F VSAM Index Space Secondary 9 bytes EBCDIC num_value left-justified - 0030 VSAM Index CISIZE 5 bytes EBCDIC num_value left-justified - 0031 VSAM Index IMBED 1 byte flag - 0032 VSAM Index Ordered Flag 1 byte flag - 0033 VSAM REPLICATE Flag 1 byte flag - 0034 VSAM Index REUSE Flag 1 byte flag - 0035 VSAM Index WRITECHK Flag 1 byte flag Retired with PKZIP 5.0 + - 0036 VSAM Owner 8 bytes EBCDIC text string - 0037 VSAM Index Owner 8 bytes EBCDIC text string - 0038 Reserved - 0039 Reserved - 003A Reserved - 003B Reserved - 003C Reserved - 003D Reserved - 003E Reserved - 003F Reserved - 0040 Reserved - 0041 Reserved - 0042 Reserved - 0043 Reserved - 0044 Reserved - 0045 Reserved - 0046 Reserved - 0047 Reserved - 0048 Reserved - 0049 Reserved - 004A Reserved - 004B Reserved - 004C Reserved - 004D Reserved - 004E Reserved - 004F Reserved - 0050 Reserved - 0051 Reserved - 0052 Reserved - 0053 Reserved - 0054 Reserved - 0055 Reserved - 0056 Reserved - 0057 Reserved - 0058 PDS/PDSE Member TTR Info. 6 bytes Big Endian - 0059 PDS 1st LMOD Text TTR 3 bytes Big Endian - 005A PDS LMOD EP Rec # 4 bytes Big Endian - 005B Reserved - 005C Max Length of records 2 bytes Big Endian - 005D PDSE Flag 1 byte flag - 005E Reserved - 005F Reserved - 0060 Reserved - 0061 Reserved - 0062 Reserved - 0063 Reserved - 0064 Reserved - 0065 Last Date Referenced 4 bytes Packed Hex "yyyymmdd" - 0066 Date Created 4 bytes Packed Hex "yyyymmdd" - 0068 GZIP two words 8 bytes - 0071 Extended NOTE Location 12 bytes Big Endian - 0072 Archive device UNIT 6 bytes EBCDIC - 0073 Archive 1st Volume 6 bytes EBCDIC - 0074 Archive 1st VOL File Seq# 2 bytes Binary - -APPENDIX C - Zip64 Extensible Data Sector Mappings (EFS) --------------------------------------------------------- - - -Z390 Extra Field: - - The following is the general layout of the attributes for the - ZIP 64 "extra" block for extended tape operations. Portions of - this extended tape processing technology is covered under a - pending patent application. The use or implementation in a - product of certain technological aspects set forth in the - current APPNOTE, including those with regard to strong encryption, - patching or extended tape operations, requires a license from - PKWARE. Please contact PKWARE with regard to acquiring a license. - - - Note: some fields stored in Big Endian format. All text is - in EBCDIC format unless otherwise specified. - - Value Size Description - ----- ---- ----------- - (Z390) 0x0065 2 bytes Tag for this "extra" block type - Size 4 bytes Size for the following data block - Tag 4 bytes EBCDIC "Z390" - Length71 2 bytes Big Endian - Subcode71 2 bytes Enote type code - FMEPos 1 byte - Length72 2 bytes Big Endian - Subcode72 2 bytes Unit type code - Unit 1 byte Unit - Length73 2 bytes Big Endian - Subcode73 2 bytes Volume1 type code - FirstVol 1 byte Volume - Length74 2 bytes Big Endian - Subcode74 2 bytes FirstVol file sequence - FileSeq 2 bytes Sequence - -APPENDIX D - Language Encoding (EFS) ------------------------------------- - -The ZIP format has historically supported only the original IBM PC character -encoding set, commonly referred to as IBM Code Page 437. This limits storing -file name characters to only those within the original MS-DOS range of values -and does not properly support file names in other character encodings, or -languages. To address this limitation, this specification will support the -following change. - -If general purpose bit 11 is unset, the file name and comment should conform -to the original ZIP character encoding. If general purpose bit 11 is set, the -filename and comment must support The Unicode Standard, Version 4.1.0 or -greater using the character encoding form defined by the UTF-8 storage -specification. The Unicode Standard is published by the The Unicode -Consortium (www.unicode.org). UTF-8 encoded data stored within ZIP files -is expected to not include a byte order mark (BOM). - -Applications may choose to supplement this file name storage through the use -of the 0x0008 Extra Field. Storage for this optional field is currently -undefined, however it will be used to allow storing extended information -on source or target encoding that may further assist applications with file -name, or file content encoding tasks. Please contact PKWARE with any -requirements on how this field should be used. - -The 0x0008 Extra Field storage may be used with either setting for general -purpose bit 11. Examples of the intended usage for this field is to store -whether "modified-UTF-8" (JAVA) is used, or UTF-8-MAC. Similarly, other -commonly used character encoding (code page) designations can be indicated -through this field. Formalized values for use of the 0x0008 record remain -undefined at this time. The definition for the layout of the 0x0008 field -will be published when available. Use of the 0x0008 Extra Field provides -for storing data within a ZIP file in an encoding other than IBM Code -Page 437 or UTF-8. - -General purpose bit 11 will not imply any encoding of file content or -password. Values defining character encoding for file content or -password must be stored within the 0x0008 Extended Language Encoding -Extra Field. - -Ed Gordon of the Info-ZIP group has defined a pair of "extra field" records -that can be used to store UTF-8 file name and file comment fields. These -records can be used for cases when the general purpose bit 11 method -for storing UTF-8 data in the standard file name and comment fields is -not desirable. A common case for this alternate method is if backward -compatibility with older programs is required. - -Definitions for the record structure of these fields are included above -in the section on 3rd party mappings for "extra field" records. These -records are identified by Header ID's 0x6375 (Info-ZIP Unicode Comment -Extra Field) and 0x7075 (Info-ZIP Unicode Path Extra Field). - -The choice of which storage method to use when writing a ZIP file is left -to the implementation. Developers should expect that a ZIP file may -contain either method and should provide support for reading data in -either format. Use of general purpose bit 11 reduces storage requirements -for file name data by not requiring additional "extra field" data for -each file, but can result in older ZIP programs not being able to extract -files. Use of the 0x6375 and 0x7075 records will result in a ZIP file -that should always be readable by older ZIP programs, but requires more -storage per file to write file name and/or file comment fields. - - - - +File: APPNOTE.TXT - .ZIP File Format Specification +Version: 6.3.2 +Revised: September 28, 2007 +Copyright (c) 1989 - 2007 PKWARE Inc., All Rights Reserved. + +The use of certain technological aspects disclosed in the current +APPNOTE is available pursuant to the below section entitled +"Incorporating PKWARE Proprietary Technology into Your Product". + +I. Purpose +---------- + +This specification is intended to define a cross-platform, +interoperable file storage and transfer format. Since its +first publication in 1989, PKWARE has remained committed to +ensuring the interoperability of the .ZIP file format through +publication and maintenance of this specification. We trust that +all .ZIP compatible vendors and application developers that have +adopted and benefited from this format will share and support +this commitment to interoperability. + +II. Contacting PKWARE +--------------------- + + PKWARE, Inc. + 648 N. Plankinton Avenue, Suite 220 + Milwaukee, WI 53203 + +1-414-289-9788 + +1-414-289-9789 FAX + zipformat@pkware.com + +III. Disclaimer +--------------- + +Although PKWARE will attempt to supply current and accurate +information relating to its file formats, algorithms, and the +subject programs, the possibility of error or omission cannot +be eliminated. PKWARE therefore expressly disclaims any warranty +that the information contained in the associated materials relating +to the subject programs and/or the format of the files created or +accessed by the subject programs and/or the algorithms used by +the subject programs, or any other matter, is current, correct or +accurate as delivered. Any risk of damage due to any possible +inaccurate information is assumed by the user of the information. +Furthermore, the information relating to the subject programs +and/or the file formats created or accessed by the subject +programs and/or the algorithms used by the subject programs is +subject to change without notice. + +If the version of this file is marked as a NOTIFICATION OF CHANGE, +the content defines an Early Feature Specification (EFS) change +to the .ZIP file format that may be subject to modification prior +to publication of the Final Feature Specification (FFS). This +document may also contain information on Planned Feature +Specifications (PFS) defining recognized future extensions. + +IV. Change Log +-------------- + +Version Change Description Date +------- ------------------ ---------- +5.2 -Single Password Symmetric Encryption 06/02/2003 + storage + +6.1.0 -Smartcard compatibility 01/20/2004 + -Documentation on certificate storage + +6.2.0 -Introduction of Central Directory 04/26/2004 + Encryption for encrypting metadata + -Added OS/X to Version Made By values + +6.2.1 -Added Extra Field placeholder for 04/01/2005 + POSZIP using ID 0x4690 + + -Clarified size field on + "zip64 end of central directory record" + +6.2.2 -Documented Final Feature Specification 01/06/2006 + for Strong Encryption + + -Clarifications and typographical + corrections + +6.3.0 -Added tape positioning storage 09/29/2006 + parameters + + -Expanded list of supported hash algorithms + + -Expanded list of supported compression + algorithms + + -Expanded list of supported encryption + algorithms + + -Added option for Unicode filename + storage + + -Clarifications for consistent use + of Data Descriptor records + + -Added additional "Extra Field" + definitions + +6.3.1 -Corrected standard hash values for 04/11/2007 + SHA-256/384/512 + +6.3.2 -Added compression method 97 09/28/2007 + + -Documented InfoZIP "Extra Field" + values for UTF-8 file name and + file comment storage + +V. General Format of a .ZIP file +-------------------------------- + + Files stored in arbitrary order. Large .ZIP files can span multiple + volumes or be split into user-defined segment sizes. All values + are stored in little-endian byte order unless otherwise specified. + + Overall .ZIP file format: + + [local file header 1] + [file data 1] + [data descriptor 1] + . + . + . + [local file header n] + [file data n] + [data descriptor n] + [archive decryption header] + [archive extra data record] + [central directory] + [zip64 end of central directory record] + [zip64 end of central directory locator] + [end of central directory record] + + + A. Local file header: + + local file header signature 4 bytes (0x04034b50) + version needed to extract 2 bytes + general purpose bit flag 2 bytes + compression method 2 bytes + last mod file time 2 bytes + last mod file date 2 bytes + crc-32 4 bytes + compressed size 4 bytes + uncompressed size 4 bytes + file name length 2 bytes + extra field length 2 bytes + + file name (variable size) + extra field (variable size) + + B. File data + + Immediately following the local header for a file + is the compressed or stored data for the file. + The series of [local file header][file data][data + descriptor] repeats for each file in the .ZIP archive. + + C. Data descriptor: + + crc-32 4 bytes + compressed size 4 bytes + uncompressed size 4 bytes + + This descriptor exists only if bit 3 of the general + purpose bit flag is set (see below). It is byte aligned + and immediately follows the last byte of compressed data. + This descriptor is used only when it was not possible to + seek in the output .ZIP file, e.g., when the output .ZIP file + was standard output or a non-seekable device. For ZIP64(tm) format + archives, the compressed and uncompressed sizes are 8 bytes each. + + When compressing files, compressed and uncompressed sizes + should be stored in ZIP64 format (as 8 byte values) when a + files size exceeds 0xFFFFFFFF. However ZIP64 format may be + used regardless of the size of a file. When extracting, if + the zip64 extended information extra field is present for + the file the compressed and uncompressed sizes will be 8 + byte values. + + Although not originally assigned a signature, the value + 0x08074b50 has commonly been adopted as a signature value + for the data descriptor record. Implementers should be + aware that ZIP files may be encountered with or without this + signature marking data descriptors and should account for + either case when reading ZIP files to ensure compatibility. + When writing ZIP files, it is recommended to include the + signature value marking the data descriptor record. When + the signature is used, the fields currently defined for + the data descriptor record will immediately follow the + signature. + + An extensible data descriptor will be released in a future + version of this APPNOTE. This new record is intended to + resolve conflicts with the use of this record going forward, + and to provide better support for streamed file processing. + + When the Central Directory Encryption method is used, the data + descriptor record is not required, but may be used. If present, + and bit 3 of the general purpose bit field is set to indicate + its presence, the values in fields of the data descriptor + record should be set to binary zeros. + + D. Archive decryption header: + + The Archive Decryption Header is introduced in version 6.2 + of the ZIP format specification. This record exists in support + of the Central Directory Encryption Feature implemented as part of + the Strong Encryption Specification as described in this document. + When the Central Directory Structure is encrypted, this decryption + header will precede the encrypted data segment. The encrypted + data segment will consist of the Archive extra data record (if + present) and the encrypted Central Directory Structure data. + The format of this data record is identical to the Decryption + header record preceding compressed file data. If the central + directory structure is encrypted, the location of the start of + this data record is determined using the Start of Central Directory + field in the Zip64 End of Central Directory record. Refer to the + section on the Strong Encryption Specification for information + on the fields used in the Archive Decryption Header record. + + + E. Archive extra data record: + + archive extra data signature 4 bytes (0x08064b50) + extra field length 4 bytes + extra field data (variable size) + + The Archive Extra Data Record is introduced in version 6.2 + of the ZIP format specification. This record exists in support + of the Central Directory Encryption Feature implemented as part of + the Strong Encryption Specification as described in this document. + When present, this record immediately precedes the central + directory data structure. The size of this data record will be + included in the Size of the Central Directory field in the + End of Central Directory record. If the central directory structure + is compressed, but not encrypted, the location of the start of + this data record is determined using the Start of Central Directory + field in the Zip64 End of Central Directory record. + + + F. Central directory structure: + + [file header 1] + . + . + . + [file header n] + [digital signature] + + File header: + + central file header signature 4 bytes (0x02014b50) + version made by 2 bytes + version needed to extract 2 bytes + general purpose bit flag 2 bytes + compression method 2 bytes + last mod file time 2 bytes + last mod file date 2 bytes + crc-32 4 bytes + compressed size 4 bytes + uncompressed size 4 bytes + file name length 2 bytes + extra field length 2 bytes + file comment length 2 bytes + disk number start 2 bytes + internal file attributes 2 bytes + external file attributes 4 bytes + relative offset of local header 4 bytes + + file name (variable size) + extra field (variable size) + file comment (variable size) + + Digital signature: + + header signature 4 bytes (0x05054b50) + size of data 2 bytes + signature data (variable size) + + With the introduction of the Central Directory Encryption + feature in version 6.2 of this specification, the Central + Directory Structure may be stored both compressed and encrypted. + Although not required, it is assumed when encrypting the + Central Directory Structure, that it will be compressed + for greater storage efficiency. Information on the + Central Directory Encryption feature can be found in the section + describing the Strong Encryption Specification. The Digital + Signature record will be neither compressed nor encrypted. + + G. Zip64 end of central directory record + + zip64 end of central dir + signature 4 bytes (0x06064b50) + size of zip64 end of central + directory record 8 bytes + version made by 2 bytes + version needed to extract 2 bytes + number of this disk 4 bytes + number of the disk with the + start of the central directory 4 bytes + total number of entries in the + central directory on this disk 8 bytes + total number of entries in the + central directory 8 bytes + size of the central directory 8 bytes + offset of start of central + directory with respect to + the starting disk number 8 bytes + zip64 extensible data sector (variable size) + + The value stored into the "size of zip64 end of central + directory record" should be the size of the remaining + record and should not include the leading 12 bytes. + + Size = SizeOfFixedFields + SizeOfVariableData - 12. + + The above record structure defines Version 1 of the + zip64 end of central directory record. Version 1 was + implemented in versions of this specification preceding + 6.2 in support of the ZIP64 large file feature. The + introduction of the Central Directory Encryption feature + implemented in version 6.2 as part of the Strong Encryption + Specification defines Version 2 of this record structure. + Refer to the section describing the Strong Encryption + Specification for details on the version 2 format for + this record. + + Special purpose data may reside in the zip64 extensible data + sector field following either a V1 or V2 version of this + record. To ensure identification of this special purpose data + it must include an identifying header block consisting of the + following: + + Header ID - 2 bytes + Data Size - 4 bytes + + The Header ID field indicates the type of data that is in the + data block that follows. + + Data Size identifies the number of bytes that follow for this + data block type. + + Multiple special purpose data blocks may be present, but each + must be preceded by a Header ID and Data Size field. Current + mappings of Header ID values supported in this field are as + defined in APPENDIX C. + + H. Zip64 end of central directory locator + + zip64 end of central dir locator + signature 4 bytes (0x07064b50) + number of the disk with the + start of the zip64 end of + central directory 4 bytes + relative offset of the zip64 + end of central directory record 8 bytes + total number of disks 4 bytes + + I. End of central directory record: + + end of central dir signature 4 bytes (0x06054b50) + number of this disk 2 bytes + number of the disk with the + start of the central directory 2 bytes + total number of entries in the + central directory on this disk 2 bytes + total number of entries in + the central directory 2 bytes + size of the central directory 4 bytes + offset of start of central + directory with respect to + the starting disk number 4 bytes + .ZIP file comment length 2 bytes + .ZIP file comment (variable size) + + J. Explanation of fields: + + version made by (2 bytes) + + The upper byte indicates the compatibility of the file + attribute information. If the external file attributes + are compatible with MS-DOS and can be read by PKZIP for + DOS version 2.04g then this value will be zero. If these + attributes are not compatible, then this value will + identify the host system on which the attributes are + compatible. Software can use this information to determine + the line record format for text files etc. The current + mappings are: + + 0 - MS-DOS and OS/2 (FAT / VFAT / FAT32 file systems) + 1 - Amiga 2 - OpenVMS + 3 - UNIX 4 - VM/CMS + 5 - Atari ST 6 - OS/2 H.P.F.S. + 7 - Macintosh 8 - Z-System + 9 - CP/M 10 - Windows NTFS + 11 - MVS (OS/390 - Z/OS) 12 - VSE + 13 - Acorn Risc 14 - VFAT + 15 - alternate MVS 16 - BeOS + 17 - Tandem 18 - OS/400 + 19 - OS/X (Darwin) 20 thru 255 - unused + + The lower byte indicates the ZIP specification version + (the version of this document) supported by the software + used to encode the file. The value/10 indicates the major + version number, and the value mod 10 is the minor version + number. + + version needed to extract (2 bytes) + + The minimum supported ZIP specification version needed to + extract the file, mapped as above. This value is based on + the specific format features a ZIP program must support to + be able to extract the file. If multiple features are + applied to a file, the minimum version should be set to the + feature having the highest value. New features or feature + changes affecting the published format specification will be + implemented using higher version numbers than the last + published value to avoid conflict. + + Current minimum feature versions are as defined below: + + 1.0 - Default value + 1.1 - File is a volume label + 2.0 - File is a folder (directory) + 2.0 - File is compressed using Deflate compression + 2.0 - File is encrypted using traditional PKWARE encryption + 2.1 - File is compressed using Deflate64(tm) + 2.5 - File is compressed using PKWARE DCL Implode + 2.7 - File is a patch data set + 4.5 - File uses ZIP64 format extensions + 4.6 - File is compressed using BZIP2 compression* + 5.0 - File is encrypted using DES + 5.0 - File is encrypted using 3DES + 5.0 - File is encrypted using original RC2 encryption + 5.0 - File is encrypted using RC4 encryption + 5.1 - File is encrypted using AES encryption + 5.1 - File is encrypted using corrected RC2 encryption** + 5.2 - File is encrypted using corrected RC2-64 encryption** + 6.1 - File is encrypted using non-OAEP key wrapping*** + 6.2 - Central directory encryption + 6.3 - File is compressed using LZMA + 6.3 - File is compressed using PPMd+ + 6.3 - File is encrypted using Blowfish + 6.3 - File is encrypted using Twofish + + + * Early 7.x (pre-7.2) versions of PKZIP incorrectly set the + version needed to extract for BZIP2 compression to be 50 + when it should have been 46. + + ** Refer to the section on Strong Encryption Specification + for additional information regarding RC2 corrections. + + *** Certificate encryption using non-OAEP key wrapping is the + intended mode of operation for all versions beginning with 6.1. + Support for OAEP key wrapping should only be used for + backward compatibility when sending ZIP files to be opened by + versions of PKZIP older than 6.1 (5.0 or 6.0). + + + Files compressed using PPMd should set the version + needed to extract field to 6.3, however, not all ZIP + programs enforce this and may be unable to decompress + data files compressed using PPMd if this value is set. + + When using ZIP64 extensions, the corresponding value in the + zip64 end of central directory record should also be set. + This field should be set appropriately to indicate whether + Version 1 or Version 2 format is in use. + + general purpose bit flag: (2 bytes) + + Bit 0: If set, indicates that the file is encrypted. + + (For Method 6 - Imploding) + Bit 1: If the compression method used was type 6, + Imploding, then this bit, if set, indicates + an 8K sliding dictionary was used. If clear, + then a 4K sliding dictionary was used. + Bit 2: If the compression method used was type 6, + Imploding, then this bit, if set, indicates + 3 Shannon-Fano trees were used to encode the + sliding dictionary output. If clear, then 2 + Shannon-Fano trees were used. + + (For Methods 8 and 9 - Deflating) + Bit 2 Bit 1 + 0 0 Normal (-en) compression option was used. + 0 1 Maximum (-exx/-ex) compression option was used. + 1 0 Fast (-ef) compression option was used. + 1 1 Super Fast (-es) compression option was used. + + (For Method 14 - LZMA) + Bit 1: If the compression method used was type 14, + LZMA, then this bit, if set, indicates + an end-of-stream (EOS) marker is used to + mark the end of the compressed data stream. + If clear, then an EOS marker is not present + and the compressed data size must be known + to extract. + + Note: Bits 1 and 2 are undefined if the compression + method is any other. + + Bit 3: If this bit is set, the fields crc-32, compressed + size and uncompressed size are set to zero in the + local header. The correct values are put in the + data descriptor immediately following the compressed + data. (Note: PKZIP version 2.04g for DOS only + recognizes this bit for method 8 compression, newer + versions of PKZIP recognize this bit for any + compression method.) + + Bit 4: Reserved for use with method 8, for enhanced + deflating. + + Bit 5: If this bit is set, this indicates that the file is + compressed patched data. (Note: Requires PKZIP + version 2.70 or greater) + + Bit 6: Strong encryption. If this bit is set, you should + set the version needed to extract value to at least + 50 and you must also set bit 0. If AES encryption + is used, the version needed to extract value must + be at least 51. + + Bit 7: Currently unused. + + Bit 8: Currently unused. + + Bit 9: Currently unused. + + Bit 10: Currently unused. + + Bit 11: Language encoding flag (EFS). If this bit is set, + the filename and comment fields for this file + must be encoded using UTF-8. (see APPENDIX D) + + Bit 12: Reserved by PKWARE for enhanced compression. + + Bit 13: Used when encrypting the Central Directory to indicate + selected data values in the Local Header are masked to + hide their actual values. See the section describing + the Strong Encryption Specification for details. + + Bit 14: Reserved by PKWARE. + + Bit 15: Reserved by PKWARE. + + compression method: (2 bytes) + + (see accompanying documentation for algorithm + descriptions) + + 0 - The file is stored (no compression) + 1 - The file is Shrunk + 2 - The file is Reduced with compression factor 1 + 3 - The file is Reduced with compression factor 2 + 4 - The file is Reduced with compression factor 3 + 5 - The file is Reduced with compression factor 4 + 6 - The file is Imploded + 7 - Reserved for Tokenizing compression algorithm + 8 - The file is Deflated + 9 - Enhanced Deflating using Deflate64(tm) + 10 - PKWARE Data Compression Library Imploding (old IBM TERSE) + 11 - Reserved by PKWARE + 12 - File is compressed using BZIP2 algorithm + 13 - Reserved by PKWARE + 14 - LZMA (EFS) + 15 - Reserved by PKWARE + 16 - Reserved by PKWARE + 17 - Reserved by PKWARE + 18 - File is compressed using IBM TERSE (new) + 19 - IBM LZ77 z Architecture (PFS) + 97 - WavPack compressed data + 98 - PPMd version I, Rev 1 + + date and time fields: (2 bytes each) + + The date and time are encoded in standard MS-DOS format. + If input came from standard input, the date and time are + those at which compression was started for this data. + If encrypting the central directory and general purpose bit + flag 13 is set indicating masking, the value stored in the + Local Header will be zero. + + CRC-32: (4 bytes) + + The CRC-32 algorithm was generously contributed by + David Schwaderer and can be found in his excellent + book "C Programmers Guide to NetBIOS" published by + Howard W. Sams & Co. Inc. The 'magic number' for + the CRC is 0xdebb20e3. The proper CRC pre and post + conditioning is used, meaning that the CRC register + is pre-conditioned with all ones (a starting value + of 0xffffffff) and the value is post-conditioned by + taking the one's complement of the CRC residual. + If bit 3 of the general purpose flag is set, this + field is set to zero in the local header and the correct + value is put in the data descriptor and in the central + directory. When encrypting the central directory, if the + local header is not in ZIP64 format and general purpose + bit flag 13 is set indicating masking, the value stored + in the Local Header will be zero. + + compressed size: (4 bytes) + uncompressed size: (4 bytes) + + The size of the file compressed and uncompressed, + respectively. When a decryption header is present it will + be placed in front of the file data and the value of the + compressed file size will include the bytes of the decryption + header. If bit 3 of the general purpose bit flag is set, + these fields are set to zero in the local header and the + correct values are put in the data descriptor and + in the central directory. If an archive is in ZIP64 format + and the value in this field is 0xFFFFFFFF, the size will be + in the corresponding 8 byte ZIP64 extended information + extra field. When encrypting the central directory, if the + local header is not in ZIP64 format and general purpose bit + flag 13 is set indicating masking, the value stored for the + uncompressed size in the Local Header will be zero. + + file name length: (2 bytes) + extra field length: (2 bytes) + file comment length: (2 bytes) + + The length of the file name, extra field, and comment + fields respectively. The combined length of any + directory record and these three fields should not + generally exceed 65,535 bytes. If input came from standard + input, the file name length is set to zero. + + disk number start: (2 bytes) + + The number of the disk on which this file begins. If an + archive is in ZIP64 format and the value in this field is + 0xFFFF, the size will be in the corresponding 4 byte zip64 + extended information extra field. + + internal file attributes: (2 bytes) + + Bits 1 and 2 are reserved for use by PKWARE. + + The lowest bit of this field indicates, if set, that + the file is apparently an ASCII or text file. If not + set, that the file apparently contains binary data. + The remaining bits are unused in version 1.0. + + The 0x0002 bit of this field indicates, if set, that a + 4 byte variable record length control field precedes each + logical record indicating the length of the record. The + record length control field is stored in little-endian byte + order. This flag is independent of text control characters, + and if used in conjunction with text data, includes any + control characters in the total length of the record. This + value is provided for mainframe data transfer support. + + external file attributes: (4 bytes) + + The mapping of the external attributes is + host-system dependent (see 'version made by'). For + MS-DOS, the low order byte is the MS-DOS directory + attribute byte. If input came from standard input, this + field is set to zero. + + relative offset of local header: (4 bytes) + + This is the offset from the start of the first disk on + which this file appears, to where the local header should + be found. If an archive is in ZIP64 format and the value + in this field is 0xFFFFFFFF, the size will be in the + corresponding 8 byte zip64 extended information extra field. + + file name: (Variable) + + The name of the file, with optional relative path. + The path stored should not contain a drive or + device letter, or a leading slash. All slashes + should be forward slashes '/' as opposed to + backwards slashes '\' for compatibility with Amiga + and UNIX file systems etc. If input came from standard + input, there is no file name field. If encrypting + the central directory and general purpose bit flag 13 is set + indicating masking, the file name stored in the Local Header + will not be the actual file name. A masking value consisting + of a unique hexadecimal value will be stored. This value will + be sequentially incremented for each file in the archive. See + the section on the Strong Encryption Specification for details + on retrieving the encrypted file name. + + extra field: (Variable) + + This is for expansion. If additional information + needs to be stored for special needs or for specific + platforms, it should be stored here. Earlier versions + of the software can then safely skip this file, and + find the next file or header. This field will be 0 + length in version 1.0. + + In order to allow different programs and different types + of information to be stored in the 'extra' field in .ZIP + files, the following structure should be used for all + programs storing data in this field: + + header1+data1 + header2+data2 . . . + + Each header should consist of: + + Header ID - 2 bytes + Data Size - 2 bytes + + Note: all fields stored in Intel low-byte/high-byte order. + + The Header ID field indicates the type of data that is in + the following data block. + + Header ID's of 0 thru 31 are reserved for use by PKWARE. + The remaining ID's can be used by third party vendors for + proprietary usage. + + The current Header ID mappings defined by PKWARE are: + + 0x0001 Zip64 extended information extra field + 0x0007 AV Info + 0x0008 Reserved for extended language encoding data (PFS) + (see APPENDIX D) + 0x0009 OS/2 + 0x000a NTFS + 0x000c OpenVMS + 0x000d UNIX + 0x000e Reserved for file stream and fork descriptors + 0x000f Patch Descriptor + 0x0014 PKCS#7 Store for X.509 Certificates + 0x0015 X.509 Certificate ID and Signature for + individual file + 0x0016 X.509 Certificate ID for Central Directory + 0x0017 Strong Encryption Header + 0x0018 Record Management Controls + 0x0019 PKCS#7 Encryption Recipient Certificate List + 0x0065 IBM S/390 (Z390), AS/400 (I400) attributes + - uncompressed + 0x0066 Reserved for IBM S/390 (Z390), AS/400 (I400) + attributes - compressed + 0x4690 POSZIP 4690 (reserved) + + Third party mappings commonly used are: + + + 0x07c8 Macintosh + 0x2605 ZipIt Macintosh + 0x2705 ZipIt Macintosh 1.3.5+ + 0x2805 ZipIt Macintosh 1.3.5+ + 0x334d Info-ZIP Macintosh + 0x4341 Acorn/SparkFS + 0x4453 Windows NT security descriptor (binary ACL) + 0x4704 VM/CMS + 0x470f MVS + 0x4b46 FWKCS MD5 (see below) + 0x4c41 OS/2 access control list (text ACL) + 0x4d49 Info-ZIP OpenVMS + 0x4f4c Xceed original location extra field + 0x5356 AOS/VS (ACL) + 0x5455 extended timestamp + 0x554e Xceed unicode extra field + 0x5855 Info-ZIP UNIX (original, also OS/2, NT, etc) + 0x6375 Info-ZIP Unicode Comment Extra Field + 0x6542 BeOS/BeBox + 0x7075 Info-ZIP Unicode Path Extra Field + 0x756e ASi UNIX + 0x7855 Info-ZIP UNIX (new) + 0xa220 Microsoft Open Packaging Growth Hint + 0xfd4a SMS/QDOS + + Detailed descriptions of Extra Fields defined by third + party mappings will be documented as information on + these data structures is made available to PKWARE. + PKWARE does not guarantee the accuracy of any published + third party data. + + The Data Size field indicates the size of the following + data block. Programs can use this value to skip to the + next header block, passing over any data blocks that are + not of interest. + + Note: As stated above, the size of the entire .ZIP file + header, including the file name, comment, and extra + field should not exceed 64K in size. + + In case two different programs should appropriate the same + Header ID value, it is strongly recommended that each + program place a unique signature of at least two bytes in + size (and preferably 4 bytes or bigger) at the start of + each data area. Every program should verify that its + unique signature is present, in addition to the Header ID + value being correct, before assuming that it is a block of + known type. + + -Zip64 Extended Information Extra Field (0x0001): + + The following is the layout of the zip64 extended + information "extra" block. If one of the size or + offset fields in the Local or Central directory + record is too small to hold the required data, + a Zip64 extended information record is created. + The order of the fields in the zip64 extended + information record is fixed, but the fields will + only appear if the corresponding Local or Central + directory record field is set to 0xFFFF or 0xFFFFFFFF. + + Note: all fields stored in Intel low-byte/high-byte order. + + Value Size Description + ----- ---- ----------- + (ZIP64) 0x0001 2 bytes Tag for this "extra" block type + Size 2 bytes Size of this "extra" block + Original + Size 8 bytes Original uncompressed file size + Compressed + Size 8 bytes Size of compressed data + Relative Header + Offset 8 bytes Offset of local header record + Disk Start + Number 4 bytes Number of the disk on which + this file starts + + This entry in the Local header must include BOTH original + and compressed file size fields. If encrypting the + central directory and bit 13 of the general purpose bit + flag is set indicating masking, the value stored in the + Local Header for the original file size will be zero. + + + -OS/2 Extra Field (0x0009): + + The following is the layout of the OS/2 attributes "extra" + block. (Last Revision 09/05/95) + + Note: all fields stored in Intel low-byte/high-byte order. + + Value Size Description + ----- ---- ----------- + (OS/2) 0x0009 2 bytes Tag for this "extra" block type + TSize 2 bytes Size for the following data block + BSize 4 bytes Uncompressed Block Size + CType 2 bytes Compression type + EACRC 4 bytes CRC value for uncompress block + (var) variable Compressed block + + The OS/2 extended attribute structure (FEA2LIST) is + compressed and then stored in it's entirety within this + structure. There will only ever be one "block" of data in + VarFields[]. + + -NTFS Extra Field (0x000a): + + The following is the layout of the NTFS attributes + "extra" block. (Note: At this time the Mtime, Atime + and Ctime values may be used on any WIN32 system.) + + Note: all fields stored in Intel low-byte/high-byte order. + + Value Size Description + ----- ---- ----------- + (NTFS) 0x000a 2 bytes Tag for this "extra" block type + TSize 2 bytes Size of the total "extra" block + Reserved 4 bytes Reserved for future use + Tag1 2 bytes NTFS attribute tag value #1 + Size1 2 bytes Size of attribute #1, in bytes + (var.) Size1 Attribute #1 data + . + . + . + TagN 2 bytes NTFS attribute tag value #N + SizeN 2 bytes Size of attribute #N, in bytes + (var.) SizeN Attribute #N data + + For NTFS, values for Tag1 through TagN are as follows: + (currently only one set of attributes is defined for NTFS) + + Tag Size Description + ----- ---- ----------- + 0x0001 2 bytes Tag for attribute #1 + Size1 2 bytes Size of attribute #1, in bytes + Mtime 8 bytes File last modification time + Atime 8 bytes File last access time + Ctime 8 bytes File creation time + + -OpenVMS Extra Field (0x000c): + + The following is the layout of the OpenVMS attributes + "extra" block. + + Note: all fields stored in Intel low-byte/high-byte order. + + Value Size Description + ----- ---- ----------- + (VMS) 0x000c 2 bytes Tag for this "extra" block type + TSize 2 bytes Size of the total "extra" block + CRC 4 bytes 32-bit CRC for remainder of the block + Tag1 2 bytes OpenVMS attribute tag value #1 + Size1 2 bytes Size of attribute #1, in bytes + (var.) Size1 Attribute #1 data + . + . + . + TagN 2 bytes OpenVMS attribute tag value #N + SizeN 2 bytes Size of attribute #N, in bytes + (var.) SizeN Attribute #N data + + Rules: + + 1. There will be one or more of attributes present, which + will each be preceded by the above TagX & SizeX values. + These values are identical to the ATR$C_XXXX and + ATR$S_XXXX constants which are defined in ATR.H under + OpenVMS C. Neither of these values will ever be zero. + + 2. No word alignment or padding is performed. + + 3. A well-behaved PKZIP/OpenVMS program should never produce + more than one sub-block with the same TagX value. Also, + there will never be more than one "extra" block of type + 0x000c in a particular directory record. + + -UNIX Extra Field (0x000d): + + The following is the layout of the UNIX "extra" block. + Note: all fields are stored in Intel low-byte/high-byte + order. + + Value Size Description + ----- ---- ----------- + (UNIX) 0x000d 2 bytes Tag for this "extra" block type + TSize 2 bytes Size for the following data block + Atime 4 bytes File last access time + Mtime 4 bytes File last modification time + Uid 2 bytes File user ID + Gid 2 bytes File group ID + (var) variable Variable length data field + + The variable length data field will contain file type + specific data. Currently the only values allowed are + the original "linked to" file names for hard or symbolic + links, and the major and minor device node numbers for + character and block device nodes. Since device nodes + cannot be either symbolic or hard links, only one set of + variable length data is stored. Link files will have the + name of the original file stored. This name is NOT NULL + terminated. Its size can be determined by checking TSize - + 12. Device entries will have eight bytes stored as two 4 + byte entries (in little endian format). The first entry + will be the major device number, and the second the minor + device number. + + -PATCH Descriptor Extra Field (0x000f): + + The following is the layout of the Patch Descriptor "extra" + block. + + Note: all fields stored in Intel low-byte/high-byte order. + + Value Size Description + ----- ---- ----------- + (Patch) 0x000f 2 bytes Tag for this "extra" block type + TSize 2 bytes Size of the total "extra" block + Version 2 bytes Version of the descriptor + Flags 4 bytes Actions and reactions (see below) + OldSize 4 bytes Size of the file about to be patched + OldCRC 4 bytes 32-bit CRC of the file to be patched + NewSize 4 bytes Size of the resulting file + NewCRC 4 bytes 32-bit CRC of the resulting file + + Actions and reactions + + Bits Description + ---- ---------------- + 0 Use for auto detection + 1 Treat as a self-patch + 2-3 RESERVED + 4-5 Action (see below) + 6-7 RESERVED + 8-9 Reaction (see below) to absent file + 10-11 Reaction (see below) to newer file + 12-13 Reaction (see below) to unknown file + 14-15 RESERVED + 16-31 RESERVED + + Actions + + Action Value + ------ ----- + none 0 + add 1 + delete 2 + patch 3 + + Reactions + + Reaction Value + -------- ----- + ask 0 + skip 1 + ignore 2 + fail 3 + + Patch support is provided by PKPatchMaker(tm) technology and is + covered under U.S. Patents and Patents Pending. The use or + implementation in a product of certain technological aspects set + forth in the current APPNOTE, including those with regard to + strong encryption, patching, or extended tape operations requires + a license from PKWARE. Please contact PKWARE with regard to + acquiring a license. + + -PKCS#7 Store for X.509 Certificates (0x0014): + + This field contains information about each of the certificates + files may be signed with. When the Central Directory Encryption + feature is enabled for a ZIP file, this record will appear in + the Archive Extra Data Record, otherwise it will appear in the + first central directory record and will be ignored in any + other record. + + Note: all fields stored in Intel low-byte/high-byte order. + + Value Size Description + ----- ---- ----------- + (Store) 0x0014 2 bytes Tag for this "extra" block type + TSize 2 bytes Size of the store data + TData TSize Data about the store + + + -X.509 Certificate ID and Signature for individual file (0x0015): + + This field contains the information about which certificate in + the PKCS#7 store was used to sign a particular file. It also + contains the signature data. This field can appear multiple + times, but can only appear once per certificate. + + Note: all fields stored in Intel low-byte/high-byte order. + + Value Size Description + ----- ---- ----------- + (CID) 0x0015 2 bytes Tag for this "extra" block type + TSize 2 bytes Size of data that follows + TData TSize Signature Data + + -X.509 Certificate ID and Signature for central directory (0x0016): + + This field contains the information about which certificate in + the PKCS#7 store was used to sign the central directory structure. + When the Central Directory Encryption feature is enabled for a + ZIP file, this record will appear in the Archive Extra Data Record, + otherwise it will appear in the first central directory record. + + Note: all fields stored in Intel low-byte/high-byte order. + + Value Size Description + ----- ---- ----------- + (CDID) 0x0016 2 bytes Tag for this "extra" block type + TSize 2 bytes Size of data that follows + TData TSize Data + + -Strong Encryption Header (0x0017): + + Value Size Description + ----- ---- ----------- + 0x0017 2 bytes Tag for this "extra" block type + TSize 2 bytes Size of data that follows + Format 2 bytes Format definition for this record + AlgID 2 bytes Encryption algorithm identifier + Bitlen 2 bytes Bit length of encryption key + Flags 2 bytes Processing flags + CertData TSize-8 Certificate decryption extra field data + (refer to the explanation for CertData + in the section describing the + Certificate Processing Method under + the Strong Encryption Specification) + + + -Record Management Controls (0x0018): + + Value Size Description + ----- ---- ----------- +(Rec-CTL) 0x0018 2 bytes Tag for this "extra" block type + CSize 2 bytes Size of total extra block data + Tag1 2 bytes Record control attribute 1 + Size1 2 bytes Size of attribute 1, in bytes + Data1 Size1 Attribute 1 data + . + . + . + TagN 2 bytes Record control attribute N + SizeN 2 bytes Size of attribute N, in bytes + DataN SizeN Attribute N data + + + -PKCS#7 Encryption Recipient Certificate List (0x0019): + + This field contains information about each of the certificates + used in encryption processing and it can be used to identify who is + allowed to decrypt encrypted files. This field should only appear + in the archive extra data record. This field is not required and + serves only to aide archive modifications by preserving public + encryption key data. Individual security requirements may dictate + that this data be omitted to deter information exposure. + + Note: all fields stored in Intel low-byte/high-byte order. + + Value Size Description + ----- ---- ----------- + (CStore) 0x0019 2 bytes Tag for this "extra" block type + TSize 2 bytes Size of the store data + TData TSize Data about the store + + TData: + + Value Size Description + ----- ---- ----------- + Version 2 bytes Format version number - must 0x0001 at this time + CStore (var) PKCS#7 data blob + + + -MVS Extra Field (0x0065): + + The following is the layout of the MVS "extra" block. + Note: Some fields are stored in Big Endian format. + All text is in EBCDIC format unless otherwise specified. + + Value Size Description + ----- ---- ----------- + (MVS) 0x0065 2 bytes Tag for this "extra" block type + TSize 2 bytes Size for the following data block + ID 4 bytes EBCDIC "Z390" 0xE9F3F9F0 or + "T4MV" for TargetFour + (var) TSize-4 Attribute data (see APPENDIX B) + + + -OS/400 Extra Field (0x0065): + + The following is the layout of the OS/400 "extra" block. + Note: Some fields are stored in Big Endian format. + All text is in EBCDIC format unless otherwise specified. + + Value Size Description + ----- ---- ----------- + (OS400) 0x0065 2 bytes Tag for this "extra" block type + TSize 2 bytes Size for the following data block + ID 4 bytes EBCDIC "I400" 0xC9F4F0F0 or + "T4MV" for TargetFour + (var) TSize-4 Attribute data (see APPENDIX A) + + + Third-party Mappings: + + -ZipIt Macintosh Extra Field (long) (0x2605): + + The following is the layout of the ZipIt extra block + for Macintosh. The local-header and central-header versions + are identical. This block must be present if the file is + stored MacBinary-encoded and it should not be used if the file + is not stored MacBinary-encoded. + + Value Size Description + ----- ---- ----------- + (Mac2) 0x2605 Short tag for this extra block type + TSize Short total data size for this block + "ZPIT" beLong extra-field signature + FnLen Byte length of FileName + FileName variable full Macintosh filename + FileType Byte[4] four-byte Mac file type string + Creator Byte[4] four-byte Mac creator string + + + -ZipIt Macintosh Extra Field (short, for files) (0x2705): + + The following is the layout of a shortened variant of the + ZipIt extra block for Macintosh (without "full name" entry). + This variant is used by ZipIt 1.3.5 and newer for entries of + files (not directories) that do not have a MacBinary encoded + file. The local-header and central-header versions are identical. + + Value Size Description + ----- ---- ----------- + (Mac2b) 0x2705 Short tag for this extra block type + TSize Short total data size for this block (12) + "ZPIT" beLong extra-field signature + FileType Byte[4] four-byte Mac file type string + Creator Byte[4] four-byte Mac creator string + fdFlags beShort attributes from FInfo.frFlags, + may be omitted + 0x0000 beShort reserved, may be omitted + + + -ZipIt Macintosh Extra Field (short, for directories) (0x2805): + + The following is the layout of a shortened variant of the + ZipIt extra block for Macintosh used only for directory + entries. This variant is used by ZipIt 1.3.5 and newer to + save some optional Mac-specific information about directories. + The local-header and central-header versions are identical. + + Value Size Description + ----- ---- ----------- + (Mac2c) 0x2805 Short tag for this extra block type + TSize Short total data size for this block (12) + "ZPIT" beLong extra-field signature + frFlags beShort attributes from DInfo.frFlags, may + be omitted + View beShort ZipIt view flag, may be omitted + + + The View field specifies ZipIt-internal settings as follows: + + Bits of the Flags: + bit 0 if set, the folder is shown expanded (open) + when the archive contents are viewed in ZipIt. + bits 1-15 reserved, zero; + + + -FWKCS MD5 Extra Field (0x4b46): + + The FWKCS Contents_Signature System, used in + automatically identifying files independent of file name, + optionally adds and uses an extra field to support the + rapid creation of an enhanced contents_signature: + + Header ID = 0x4b46 + Data Size = 0x0013 + Preface = 'M','D','5' + followed by 16 bytes containing the uncompressed file's + 128_bit MD5 hash(1), low byte first. + + When FWKCS revises a .ZIP file central directory to add + this extra field for a file, it also replaces the + central directory entry for that file's uncompressed + file length with a measured value. + + FWKCS provides an option to strip this extra field, if + present, from a .ZIP file central directory. In adding + this extra field, FWKCS preserves .ZIP file Authenticity + Verification; if stripping this extra field, FWKCS + preserves all versions of AV through PKZIP version 2.04g. + + FWKCS, and FWKCS Contents_Signature System, are + trademarks of Frederick W. Kantor. + + (1) R. Rivest, RFC1321.TXT, MIT Laboratory for Computer + Science and RSA Data Security, Inc., April 1992. + ll.76-77: "The MD5 algorithm is being placed in the + public domain for review and possible adoption as a + standard." + + + -Info-ZIP Unicode Comment Extra Field (0x6375): + + Stores the UTF-8 version of the file comment as stored in the + central directory header. (Last Revision 20070912) + + Value Size Description + ----- ---- ----------- + (UCom) 0x6375 Short tag for this extra block type ("uc") + TSize Short total data size for this block + Version 1 byte version of this extra field, currently 1 + ComCRC32 4 bytes Comment Field CRC32 Checksum + UnicodeCom Variable UTF-8 version of the entry comment + + Currently Version is set to the number 1. If there is a need + to change this field, the version will be incremented. Changes + may not be backward compatible so this extra field should not be + used if the version is not recognized. + + The ComCRC32 is the standard zip CRC32 checksum of the File Comment + field in the central directory header. This is used to verify that + the comment field has not changed since the Unicode Comment extra field + was created. This can happen if a utility changes the File Comment + field but does not update the UTF-8 Comment extra field. If the CRC + check fails, this Unicode Comment extra field should be ignored and + the File Comment field in the header should be used instead. + + The UnicodeCom field is the UTF-8 version of the File Comment field + in the header. As UnicodeCom is defined to be UTF-8, no UTF-8 byte + order mark (BOM) is used. The length of this field is determined by + subtracting the size of the previous fields from TSize. If both the + File Name and Comment fields are UTF-8, the new General Purpose Bit + Flag, bit 11 (Language encoding flag (EFS)), can be used to indicate + both the header File Name and Comment fields are UTF-8 and, in this + case, the Unicode Path and Unicode Comment extra fields are not + needed and should not be created. Note that, for backward + compatibility, bit 11 should only be used if the native character set + of the paths and comments being zipped up are already in UTF-8. It is + expected that the same file comment storage method, either general + purpose bit 11 or extra fields, be used in both the Local and Central + Directory Header for a file. + + + -Info-ZIP Unicode Path Extra Field (0x7075): + + Stores the UTF-8 version of the file name field as stored in the + local header and central directory header. (Last Revision 20070912) + + Value Size Description + ----- ---- ----------- + (UPath) 0x7075 Short tag for this extra block type ("up") + TSize Short total data size for this block + Version 1 byte version of this extra field, currently 1 + NameCRC32 4 bytes File Name Field CRC32 Checksum + UnicodeName Variable UTF-8 version of the entry File Name + + Currently Version is set to the number 1. If there is a need + to change this field, the version will be incremented. Changes + may not be backward compatible so this extra field should not be + used if the version is not recognized. + + The NameCRC32 is the standard zip CRC32 checksum of the File Name + field in the header. This is used to verify that the header + File Name field has not changed since the Unicode Path extra field + was created. This can happen if a utility renames the File Name but + does not update the UTF-8 path extra field. If the CRC check fails, + this UTF-8 Path Extra Field should be ignored and the File Name field + in the header should be used instead. + + The UnicodeName is the UTF-8 version of the contents of the File Name + field in the header. As UnicodeName is defined to be UTF-8, no UTF-8 + byte order mark (BOM) is used. The length of this field is determined + by subtracting the size of the previous fields from TSize. If both + the File Name and Comment fields are UTF-8, the new General Purpose + Bit Flag, bit 11 (Language encoding flag (EFS)), can be used to + indicate that both the header File Name and Comment fields are UTF-8 + and, in this case, the Unicode Path and Unicode Comment extra fields + are not needed and should not be created. Note that, for backward + compatibility, bit 11 should only be used if the native character set + of the paths and comments being zipped up are already in UTF-8. It is + expected that the same file name storage method, either general + purpose bit 11 or extra fields, be used in both the Local and Central + Directory Header for a file. + + + -Microsoft Open Packaging Growth Hint (0xa220): + + Value Size Description + ----- ---- ----------- + 0xa220 Short tag for this extra block type + TSize Short size of Sig + PadVal + Padding + Sig Short verification signature (A028) + PadVal Short Initial padding value + Padding variable filled with NULL characters + + + file comment: (Variable) + + The comment for this file. + + number of this disk: (2 bytes) + + The number of this disk, which contains central + directory end record. If an archive is in ZIP64 format + and the value in this field is 0xFFFF, the size will + be in the corresponding 4 byte zip64 end of central + directory field. + + + number of the disk with the start of the central + directory: (2 bytes) + + The number of the disk on which the central + directory starts. If an archive is in ZIP64 format + and the value in this field is 0xFFFF, the size will + be in the corresponding 4 byte zip64 end of central + directory field. + + total number of entries in the central dir on + this disk: (2 bytes) + + The number of central directory entries on this disk. + If an archive is in ZIP64 format and the value in + this field is 0xFFFF, the size will be in the + corresponding 8 byte zip64 end of central + directory field. + + total number of entries in the central dir: (2 bytes) + + The total number of files in the .ZIP file. If an + archive is in ZIP64 format and the value in this field + is 0xFFFF, the size will be in the corresponding 8 byte + zip64 end of central directory field. + + size of the central directory: (4 bytes) + + The size (in bytes) of the entire central directory. + If an archive is in ZIP64 format and the value in + this field is 0xFFFFFFFF, the size will be in the + corresponding 8 byte zip64 end of central + directory field. + + offset of start of central directory with respect to + the starting disk number: (4 bytes) + + Offset of the start of the central directory on the + disk on which the central directory starts. If an + archive is in ZIP64 format and the value in this + field is 0xFFFFFFFF, the size will be in the + corresponding 8 byte zip64 end of central + directory field. + + .ZIP file comment length: (2 bytes) + + The length of the comment for this .ZIP file. + + .ZIP file comment: (Variable) + + The comment for this .ZIP file. ZIP file comment data + is stored unsecured. No encryption or data authentication + is applied to this area at this time. Confidential information + should not be stored in this section. + + zip64 extensible data sector (variable size) + + (currently reserved for use by PKWARE) + + + K. Splitting and Spanning ZIP files + + Spanning is the process of segmenting a ZIP file across + multiple removable media. This support has typically only + been provided for DOS formatted floppy diskettes. + + File splitting is a newer derivative of spanning. + Splitting follows the same segmentation process as + spanning, however, it does not require writing each + segment to a unique removable medium and instead supports + placing all pieces onto local or non-removable locations + such as file systems, local drives, folders, etc... + + A key difference between spanned and split ZIP files is + that all pieces of a spanned ZIP file have the same name. + Since each piece is written to a separate volume, no name + collisions occur and each segment can reuse the original + .ZIP file name given to the archive. + + Sequence ordering for DOS spanned archives uses the DOS + volume label to determine segment numbers. Volume labels + for each segment are written using the form PKBACK#xxx, + where xxx is the segment number written as a decimal + value from 001 - nnn. + + Split ZIP files are typically written to the same location + and are subject to name collisions if the spanned name + format is used since each segment will reside on the same + drive. To avoid name collisions, split archives are named + as follows. + + Segment 1 = filename.z01 + Segment n-1 = filename.z(n-1) + Segment n = filename.zip + + The .ZIP extension is used on the last segment to support + quickly reading the central directory. The segment number + n should be a decimal value. + + Spanned ZIP files may be PKSFX Self-extracting ZIP files. + PKSFX files may also be split, however, in this case + the first segment must be named filename.exe. The first + segment of a split PKSFX archive must be large enough to + include the entire executable program. + + Capacities for split archives are as follows. + + Maximum number of segments = 4,294,967,295 - 1 + Maximum .ZIP segment size = 4,294,967,295 bytes + Minimum segment size = 64K + Maximum PKSFX segment size = 2,147,483,647 bytes + + Segment sizes may be different however by convention, all + segment sizes should be the same with the exception of the + last, which may be smaller. Local and central directory + header records must never be split across a segment boundary. + When writing a header record, if the number of bytes remaining + within a segment is less than the size of the header record, + end the current segment and write the header at the start + of the next segment. The central directory may span segment + boundaries, but no single record in the central directory + should be split across segments. + + Spanned/Split archives created using PKZIP for Windows + (V2.50 or greater), PKZIP Command Line (V2.50 or greater), + or PKZIP Explorer will include a special spanning + signature as the first 4 bytes of the first segment of + the archive. This signature (0x08074b50) will be + followed immediately by the local header signature for + the first file in the archive. + + A special spanning marker may also appear in spanned/split + archives if the spanning or splitting process starts but + only requires one segment. In this case the 0x08074b50 + signature will be replaced with the temporary spanning + marker signature of 0x30304b50. Split archives can + only be uncompressed by other versions of PKZIP that + know how to create a split archive. + + The signature value 0x08074b50 is also used by some + ZIP implementations as a marker for the Data Descriptor + record. Conflict in this alternate assignment can be + avoided by ensuring the position of the signature + within the ZIP file to determine the use for which it + is intended. + + L. General notes: + + 1) All fields unless otherwise noted are unsigned and stored + in Intel low-byte:high-byte, low-word:high-word order. + + 2) String fields are not null terminated, since the + length is given explicitly. + + 3) The entries in the central directory may not necessarily + be in the same order that files appear in the .ZIP file. + + 4) If one of the fields in the end of central directory + record is too small to hold required data, the field + should be set to -1 (0xFFFF or 0xFFFFFFFF) and the + ZIP64 format record should be created. + + 5) The end of central directory record and the + Zip64 end of central directory locator record must + reside on the same disk when splitting or spanning + an archive. + +VI. Explanation of compression methods +-------------------------------------- + +UnShrinking - Method 1 +---------------------- + +Shrinking is a Dynamic Ziv-Lempel-Welch compression algorithm +with partial clearing. The initial code size is 9 bits, and +the maximum code size is 13 bits. Shrinking differs from +conventional Dynamic Ziv-Lempel-Welch implementations in several +respects: + +1) The code size is controlled by the compressor, and is not + automatically increased when codes larger than the current + code size are created (but not necessarily used). When + the decompressor encounters the code sequence 256 + (decimal) followed by 1, it should increase the code size + read from the input stream to the next bit size. No + blocking of the codes is performed, so the next code at + the increased size should be read from the input stream + immediately after where the previous code at the smaller + bit size was read. Again, the decompressor should not + increase the code size used until the sequence 256,1 is + encountered. + +2) When the table becomes full, total clearing is not + performed. Rather, when the compressor emits the code + sequence 256,2 (decimal), the decompressor should clear + all leaf nodes from the Ziv-Lempel tree, and continue to + use the current code size. The nodes that are cleared + from the Ziv-Lempel tree are then re-used, with the lowest + code value re-used first, and the highest code value + re-used last. The compressor can emit the sequence 256,2 + at any time. + +Expanding - Methods 2-5 +----------------------- + +The Reducing algorithm is actually a combination of two +distinct algorithms. The first algorithm compresses repeated +byte sequences, and the second algorithm takes the compressed +stream from the first algorithm and applies a probabilistic +compression method. + +The probabilistic compression stores an array of 'follower +sets' S(j), for j=0 to 255, corresponding to each possible +ASCII character. Each set contains between 0 and 32 +characters, to be denoted as S(j)[0],...,S(j)[m], where m<32. +The sets are stored at the beginning of the data area for a +Reduced file, in reverse order, with S(255) first, and S(0) +last. + +The sets are encoded as { N(j), S(j)[0],...,S(j)[N(j)-1] }, +where N(j) is the size of set S(j). N(j) can be 0, in which +case the follower set for S(j) is empty. Each N(j) value is +encoded in 6 bits, followed by N(j) eight bit character values +corresponding to S(j)[0] to S(j)[N(j)-1] respectively. If +N(j) is 0, then no values for S(j) are stored, and the value +for N(j-1) immediately follows. + +Immediately after the follower sets, is the compressed data +stream. The compressed data stream can be interpreted for the +probabilistic decompression as follows: + +let Last-Character <- 0. +loop until done + if the follower set S(Last-Character) is empty then + read 8 bits from the input stream, and copy this + value to the output stream. + otherwise if the follower set S(Last-Character) is non-empty then + read 1 bit from the input stream. + if this bit is not zero then + read 8 bits from the input stream, and copy this + value to the output stream. + otherwise if this bit is zero then + read B(N(Last-Character)) bits from the input + stream, and assign this value to I. + Copy the value of S(Last-Character)[I] to the + output stream. + + assign the last value placed on the output stream to + Last-Character. +end loop + +B(N(j)) is defined as the minimal number of bits required to +encode the value N(j)-1. + +The decompressed stream from above can then be expanded to +re-create the original file as follows: + +let State <- 0. + +loop until done + read 8 bits from the input stream into C. + case State of + 0: if C is not equal to DLE (144 decimal) then + copy C to the output stream. + otherwise if C is equal to DLE then + let State <- 1. + + 1: if C is non-zero then + let V <- C. + let Len <- L(V) + let State <- F(Len). + otherwise if C is zero then + copy the value 144 (decimal) to the output stream. + let State <- 0 + + 2: let Len <- Len + C + let State <- 3. + + 3: move backwards D(V,C) bytes in the output stream + (if this position is before the start of the output + stream, then assume that all the data before the + start of the output stream is filled with zeros). + copy Len+3 bytes from this position to the output stream. + let State <- 0. + end case +end loop + +The functions F,L, and D are dependent on the 'compression +factor', 1 through 4, and are defined as follows: + +For compression factor 1: + L(X) equals the lower 7 bits of X. + F(X) equals 2 if X equals 127 otherwise F(X) equals 3. + D(X,Y) equals the (upper 1 bit of X) * 256 + Y + 1. +For compression factor 2: + L(X) equals the lower 6 bits of X. + F(X) equals 2 if X equals 63 otherwise F(X) equals 3. + D(X,Y) equals the (upper 2 bits of X) * 256 + Y + 1. +For compression factor 3: + L(X) equals the lower 5 bits of X. + F(X) equals 2 if X equals 31 otherwise F(X) equals 3. + D(X,Y) equals the (upper 3 bits of X) * 256 + Y + 1. +For compression factor 4: + L(X) equals the lower 4 bits of X. + F(X) equals 2 if X equals 15 otherwise F(X) equals 3. + D(X,Y) equals the (upper 4 bits of X) * 256 + Y + 1. + +Imploding - Method 6 +-------------------- + +The Imploding algorithm is actually a combination of two distinct +algorithms. The first algorithm compresses repeated byte +sequences using a sliding dictionary. The second algorithm is +used to compress the encoding of the sliding dictionary output, +using multiple Shannon-Fano trees. + +The Imploding algorithm can use a 4K or 8K sliding dictionary +size. The dictionary size used can be determined by bit 1 in the +general purpose flag word; a 0 bit indicates a 4K dictionary +while a 1 bit indicates an 8K dictionary. + +The Shannon-Fano trees are stored at the start of the compressed +file. The number of trees stored is defined by bit 2 in the +general purpose flag word; a 0 bit indicates two trees stored, a +1 bit indicates three trees are stored. If 3 trees are stored, +the first Shannon-Fano tree represents the encoding of the +Literal characters, the second tree represents the encoding of +the Length information, the third represents the encoding of the +Distance information. When 2 Shannon-Fano trees are stored, the +Length tree is stored first, followed by the Distance tree. + +The Literal Shannon-Fano tree, if present is used to represent +the entire ASCII character set, and contains 256 values. This +tree is used to compress any data not compressed by the sliding +dictionary algorithm. When this tree is present, the Minimum +Match Length for the sliding dictionary is 3. If this tree is +not present, the Minimum Match Length is 2. + +The Length Shannon-Fano tree is used to compress the Length part +of the (length,distance) pairs from the sliding dictionary +output. The Length tree contains 64 values, ranging from the +Minimum Match Length, to 63 plus the Minimum Match Length. + +The Distance Shannon-Fano tree is used to compress the Distance +part of the (length,distance) pairs from the sliding dictionary +output. The Distance tree contains 64 values, ranging from 0 to +63, representing the upper 6 bits of the distance value. The +distance values themselves will be between 0 and the sliding +dictionary size, either 4K or 8K. + +The Shannon-Fano trees themselves are stored in a compressed +format. The first byte of the tree data represents the number of +bytes of data representing the (compressed) Shannon-Fano tree +minus 1. The remaining bytes represent the Shannon-Fano tree +data encoded as: + + High 4 bits: Number of values at this bit length + 1. (1 - 16) + Low 4 bits: Bit Length needed to represent value + 1. (1 - 16) + +The Shannon-Fano codes can be constructed from the bit lengths +using the following algorithm: + +1) Sort the Bit Lengths in ascending order, while retaining the + order of the original lengths stored in the file. + +2) Generate the Shannon-Fano trees: + + Code <- 0 + CodeIncrement <- 0 + LastBitLength <- 0 + i <- number of Shannon-Fano codes - 1 (either 255 or 63) + + loop while i >= 0 + Code = Code + CodeIncrement + if BitLength(i) <> LastBitLength then + LastBitLength=BitLength(i) + CodeIncrement = 1 shifted left (16 - LastBitLength) + ShannonCode(i) = Code + i <- i - 1 + end loop + +3) Reverse the order of all the bits in the above ShannonCode() + vector, so that the most significant bit becomes the least + significant bit. For example, the value 0x1234 (hex) would + become 0x2C48 (hex). + +4) Restore the order of Shannon-Fano codes as originally stored + within the file. + +Example: + + This example will show the encoding of a Shannon-Fano tree + of size 8. Notice that the actual Shannon-Fano trees used + for Imploding are either 64 or 256 entries in size. + +Example: 0x02, 0x42, 0x01, 0x13 + + The first byte indicates 3 values in this table. Decoding the + bytes: + 0x42 = 5 codes of 3 bits long + 0x01 = 1 code of 2 bits long + 0x13 = 2 codes of 4 bits long + + This would generate the original bit length array of: + (3, 3, 3, 3, 3, 2, 4, 4) + + There are 8 codes in this table for the values 0 thru 7. Using + the algorithm to obtain the Shannon-Fano codes produces: + + Reversed Order Original +Val Sorted Constructed Code Value Restored Length +--- ------ ----------------- -------- -------- ------ +0: 2 1100000000000000 11 101 3 +1: 3 1010000000000000 101 001 3 +2: 3 1000000000000000 001 110 3 +3: 3 0110000000000000 110 010 3 +4: 3 0100000000000000 010 100 3 +5: 3 0010000000000000 100 11 2 +6: 4 0001000000000000 1000 1000 4 +7: 4 0000000000000000 0000 0000 4 + +The values in the Val, Order Restored and Original Length columns +now represent the Shannon-Fano encoding tree that can be used for +decoding the Shannon-Fano encoded data. How to parse the +variable length Shannon-Fano values from the data stream is beyond +the scope of this document. (See the references listed at the end of +this document for more information.) However, traditional decoding +schemes used for Huffman variable length decoding, such as the +Greenlaw algorithm, can be successfully applied. + +The compressed data stream begins immediately after the +compressed Shannon-Fano data. The compressed data stream can be +interpreted as follows: + +loop until done + read 1 bit from input stream. + + if this bit is non-zero then (encoded data is literal data) + if Literal Shannon-Fano tree is present + read and decode character using Literal Shannon-Fano tree. + otherwise + read 8 bits from input stream. + copy character to the output stream. + otherwise (encoded data is sliding dictionary match) + if 8K dictionary size + read 7 bits for offset Distance (lower 7 bits of offset). + otherwise + read 6 bits for offset Distance (lower 6 bits of offset). + + using the Distance Shannon-Fano tree, read and decode the + upper 6 bits of the Distance value. + + using the Length Shannon-Fano tree, read and decode + the Length value. + + Length <- Length + Minimum Match Length + + if Length = 63 + Minimum Match Length + read 8 bits from the input stream, + add this value to Length. + + move backwards Distance+1 bytes in the output stream, and + copy Length characters from this position to the output + stream. (if this position is before the start of the output + stream, then assume that all the data before the start of + the output stream is filled with zeros). +end loop + +Tokenizing - Method 7 +--------------------- + +This method is not used by PKZIP. + +Deflating - Method 8 +-------------------- + +The Deflate algorithm is similar to the Implode algorithm using +a sliding dictionary of up to 32K with secondary compression +from Huffman/Shannon-Fano codes. + +The compressed data is stored in blocks with a header describing +the block and the Huffman codes used in the data block. The header +format is as follows: + + Bit 0: Last Block bit This bit is set to 1 if this is the last + compressed block in the data. + Bits 1-2: Block type + 00 (0) - Block is stored - All stored data is byte aligned. + Skip bits until next byte, then next word = block + length, followed by the ones compliment of the block + length word. Remaining data in block is the stored + data. + + 01 (1) - Use fixed Huffman codes for literal and distance codes. + Lit Code Bits Dist Code Bits + --------- ---- --------- ---- + 0 - 143 8 0 - 31 5 + 144 - 255 9 + 256 - 279 7 + 280 - 287 8 + + Literal codes 286-287 and distance codes 30-31 are + never used but participate in the huffman construction. + + 10 (2) - Dynamic Huffman codes. (See expanding Huffman codes) + + 11 (3) - Reserved - Flag a "Error in compressed data" if seen. + +Expanding Huffman Codes +----------------------- +If the data block is stored with dynamic Huffman codes, the Huffman +codes are sent in the following compressed format: + + 5 Bits: # of Literal codes sent - 256 (256 - 286) + All other codes are never sent. + 5 Bits: # of Dist codes - 1 (1 - 32) + 4 Bits: # of Bit Length codes - 3 (3 - 19) + +The Huffman codes are sent as bit lengths and the codes are built as +described in the implode algorithm. The bit lengths themselves are +compressed with Huffman codes. There are 19 bit length codes: + + 0 - 15: Represent bit lengths of 0 - 15 + 16: Copy the previous bit length 3 - 6 times. + The next 2 bits indicate repeat length (0 = 3, ... ,3 = 6) + Example: Codes 8, 16 (+2 bits 11), 16 (+2 bits 10) will + expand to 12 bit lengths of 8 (1 + 6 + 5) + 17: Repeat a bit length of 0 for 3 - 10 times. (3 bits of length) + 18: Repeat a bit length of 0 for 11 - 138 times (7 bits of length) + +The lengths of the bit length codes are sent packed 3 bits per value +(0 - 7) in the following order: + + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 + +The Huffman codes should be built as described in the Implode algorithm +except codes are assigned starting at the shortest bit length, i.e. the +shortest code should be all 0's rather than all 1's. Also, codes with +a bit length of zero do not participate in the tree construction. The +codes are then used to decode the bit lengths for the literal and +distance tables. + +The bit lengths for the literal tables are sent first with the number +of entries sent described by the 5 bits sent earlier. There are up +to 286 literal characters; the first 256 represent the respective 8 +bit character, code 256 represents the End-Of-Block code, the remaining +29 codes represent copy lengths of 3 thru 258. There are up to 30 +distance codes representing distances from 1 thru 32k as described +below. + + Length Codes + ------------ + Extra Extra Extra Extra + Code Bits Length Code Bits Lengths Code Bits Lengths Code Bits Length(s) + ---- ---- ------ ---- ---- ------- ---- ---- ------- ---- ---- --------- + 257 0 3 265 1 11,12 273 3 35-42 281 5 131-162 + 258 0 4 266 1 13,14 274 3 43-50 282 5 163-194 + 259 0 5 267 1 15,16 275 3 51-58 283 5 195-226 + 260 0 6 268 1 17,18 276 3 59-66 284 5 227-257 + 261 0 7 269 2 19-22 277 4 67-82 285 0 258 + 262 0 8 270 2 23-26 278 4 83-98 + 263 0 9 271 2 27-30 279 4 99-114 + 264 0 10 272 2 31-34 280 4 115-130 + + Distance Codes + -------------- + Extra Extra Extra Extra + Code Bits Dist Code Bits Dist Code Bits Distance Code Bits Distance + ---- ---- ---- ---- ---- ------ ---- ---- -------- ---- ---- -------- + 0 0 1 8 3 17-24 16 7 257-384 24 11 4097-6144 + 1 0 2 9 3 25-32 17 7 385-512 25 11 6145-8192 + 2 0 3 10 4 33-48 18 8 513-768 26 12 8193-12288 + 3 0 4 11 4 49-64 19 8 769-1024 27 12 12289-16384 + 4 1 5,6 12 5 65-96 20 9 1025-1536 28 13 16385-24576 + 5 1 7,8 13 5 97-128 21 9 1537-2048 29 13 24577-32768 + 6 2 9-12 14 6 129-192 22 10 2049-3072 + 7 2 13-16 15 6 193-256 23 10 3073-4096 + +The compressed data stream begins immediately after the +compressed header data. The compressed data stream can be +interpreted as follows: + +do + read header from input stream. + + if stored block + skip bits until byte aligned + read count and 1's compliment of count + copy count bytes data block + otherwise + loop until end of block code sent + decode literal character from input stream + if literal < 256 + copy character to the output stream + otherwise + if literal = end of block + break from loop + otherwise + decode distance from input stream + + move backwards distance bytes in the output stream, and + copy length characters from this position to the output + stream. + end loop +while not last block + +if data descriptor exists + skip bits until byte aligned + read crc and sizes +endif + +Enhanced Deflating - Method 9 +----------------------------- + +The Enhanced Deflating algorithm is similar to Deflate but +uses a sliding dictionary of up to 64K. Deflate64(tm) is supported +by the Deflate extractor. + +BZIP2 - Method 12 +----------------- + +BZIP2 is an open-source data compression algorithm developed by +Julian Seward. Information and source code for this algorithm +can be found on the internet. + +LZMA - Method 14 (EFS) +---------------------- + +LZMA is a block-oriented, general purpose data compression algorithm +developed and maintained by Igor Pavlov. It is a derivative of LZ77 +that utilizes Markov chains and a range coder. Information and +source code for this algorithm can be found on the internet. Consult +with the author of this algorithm for information on terms or +restrictions on use. + +Support for LZMA within the ZIP format is defined as follows: + +The Compression method field within the ZIP Local and Central +Header records will be set to the value 14 to indicate data was +compressed using LZMA. + +The Version needed to extract field within the ZIP Local and +Central Header records will be set to 6.3 to indicate the +minimum ZIP format version supporting this feature. + +File data compressed using the LZMA algorithm must be placed +immediately following the Local Header for the file. If a +standard ZIP encryption header is required, it will follow +the Local Header and will precede the LZMA compressed file +data segment. The location of LZMA compressed data segment +within the ZIP format will be as shown: + + [local header file 1] + [encryption header file 1] + [LZMA compressed data segment for file 1] + [data descriptor 1] + [local header file 2] + +The encryption header and data descriptor records may +be conditionally present. The LZMA Compressed Data Segment +will consist of an LZMA Properties Header followed by the +LZMA Compressed Data as shown: + + [LZMA properties header for file 1] + [LZMA compressed data for file 1] + +The LZMA Compressed Data will be stored as provided by the +LZMA compression library. Compressed size, uncompressed +size and other file characteristics about the file being +compressed must be stored in standard ZIP storage format. + +The LZMA Properties Header will store specific data required to +decompress the LZMA compressed Data. This data is set by the +LZMA compression engine using the function WriteCoderProperties() +as documented within the LZMA SDK. + +Storage fields for the property information within the LZMA +Properties Header are as follows: + + LZMA Version Information 2 bytes + LZMA Properties Size 2 bytes + LZMA Properties Data variable, defined by "LZMA Properties Size" + +LZMA Version Information - this field identifies which version of + the LZMA SDK was used to compress a file. The first byte will + store the major version number of the LZMA SDK and the second + byte will store the minor number. + +LZMA Properties Size - this field defines the size of the remaining + property data. Typically this size should be determined by the + version of the SDK. This size field is included as a convenience + and to help avoid any ambiguity should it arise in the future due + to changes in this compression algorithm. + +LZMA Property Data - this variable sized field records the required + values for the decompressor as defined by the LZMA SDK. The + data stored in this field should be obtained using the + WriteCoderProperties() in the version of the SDK defined by + the "LZMA Version Information" field. + +The layout of the "LZMA Properties Data" field is a function of the +LZMA compression algorithm. It is possible that this layout may be +changed by the author over time. The data layout in version 4.32 +of the LZMA SDK defines a 5 byte array that uses 4 bytes to store +the dictionary size in little-endian order. This is preceded by a +single packed byte as the first element of the array that contains +the following fields: + + PosStateBits + LiteralPosStateBits + LiteralContextBits + +Refer to the LZMA documentation for a more detailed explanation of +these fields. + +Data compressed with method 14, LZMA, may include an end-of-stream +(EOS) marker ending the compressed data stream. This marker is not +required, but its use is highly recommended to facilitate processing +and implementers should include the EOS marker whenever possible. +When the EOS marker is used, general purpose bit 1 must be set. If +general purpose bit 1 is not set, the EOS marker is not present. + +WavPack - Method 97 +------------------- + +Information describing the use of compression method 97 is +provided by WinZIP International, LLC. This method relies on the +open source WavPack audio compression utility developed by David Bryant. +Information on WavPack is available at www.wavpack.com. Please consult +with the author of this algorithm for information on terms and +restrictions on use. + +WavPack data for a file begins immediately after the end of the +local header data. This data is the output from WavPack compression +routines. Within the ZIP file, the use of WavPack compression is +indicated by setting the compression method field to a value of 97 +in both the local header and the central directory header. The Version +needed to extract and version made by fields use the same values as are +used for data compressed using the Deflate algorithm. + +An implementation note for storing digital sample data when using +WavPack compression within ZIP files is that all of the bytes of +the sample data should be compressed. This includes any unused +bits up to the byte boundary. An example is a 2 byte sample that +uses only 12 bits for the sample data with 4 unused bits. If only +12 bits are passed as the sample size to the WavPack routines, the 4 +unused bits will be set to 0 on extraction regardless of their original +state. To avoid this, the full 16 bits of the sample data size +should be provided. + +PPMd - Method 98 +---------------- + +PPMd is a data compression algorithm developed by Dmitry Shkarin +which includes a carryless rangecoder developed by Dmitry Subbotin. +This algorithm is based on predictive phrase matching on multiple +order contexts. Information and source code for this algorithm +can be found on the internet. Consult with the author of this +algorithm for information on terms or restrictions on use. + +Support for PPMd within the ZIP format currently is provided only +for version I, revision 1 of the algorithm. Storage requirements +for using this algorithm are as follows: + +Parameters needed to control the algorithm are stored in the two +bytes immediately preceding the compressed data. These bytes are +used to store the following fields: + +Model order - sets the maximum model order, default is 8, possible + values are from 2 to 16 inclusive + +Sub-allocator size - sets the size of sub-allocator in MB, default is 50, + possible values are from 1MB to 256MB inclusive + +Model restoration method - sets the method used to restart context + model at memory insufficiency, values are: + + 0 - restarts model from scratch - default + 1 - cut off model - decreases performance by as much as 2x + 2 - freeze context tree - not recommended + +An example for packing these fields into the 2 byte storage field is +illustrated below. These values are stored in Intel low-byte/high-byte +order. + +wPPMd = (Model order - 1) + + ((Sub-allocator size - 1) << 4) + + (Model restoration method << 12) + + +VII. Traditional PKWARE Encryption +---------------------------------- + +The following information discusses the decryption steps +required to support traditional PKWARE encryption. This +form of encryption is considered weak by today's standards +and its use is recommended only for situations with +low security needs or for compatibility with older .ZIP +applications. + +Decryption +---------- + +PKWARE is grateful to Mr. Roger Schlafly for his expert contribution +towards the development of PKWARE's traditional encryption. + +PKZIP encrypts the compressed data stream. Encrypted files must +be decrypted before they can be extracted. + +Each encrypted file has an extra 12 bytes stored at the start of +the data area defining the encryption header for that file. The +encryption header is originally set to random values, and then +itself encrypted, using three, 32-bit keys. The key values are +initialized using the supplied encryption password. After each byte +is encrypted, the keys are then updated using pseudo-random number +generation techniques in combination with the same CRC-32 algorithm +used in PKZIP and described elsewhere in this document. + +The following is the basic steps required to decrypt a file: + +1) Initialize the three 32-bit keys with the password. +2) Read and decrypt the 12-byte encryption header, further + initializing the encryption keys. +3) Read and decrypt the compressed data stream using the + encryption keys. + +Step 1 - Initializing the encryption keys +----------------------------------------- + +Key(0) <- 305419896 +Key(1) <- 591751049 +Key(2) <- 878082192 + +loop for i <- 0 to length(password)-1 + update_keys(password(i)) +end loop + +Where update_keys() is defined as: + +update_keys(char): + Key(0) <- crc32(key(0),char) + Key(1) <- Key(1) + (Key(0) & 000000ffH) + Key(1) <- Key(1) * 134775813 + 1 + Key(2) <- crc32(key(2),key(1) >> 24) +end update_keys + +Where crc32(old_crc,char) is a routine that given a CRC value and a +character, returns an updated CRC value after applying the CRC-32 +algorithm described elsewhere in this document. + +Step 2 - Decrypting the encryption header +----------------------------------------- + +The purpose of this step is to further initialize the encryption +keys, based on random data, to render a plaintext attack on the +data ineffective. + +Read the 12-byte encryption header into Buffer, in locations +Buffer(0) thru Buffer(11). + +loop for i <- 0 to 11 + C <- buffer(i) ^ decrypt_byte() + update_keys(C) + buffer(i) <- C +end loop + +Where decrypt_byte() is defined as: + +unsigned char decrypt_byte() + local unsigned short temp + temp <- Key(2) | 2 + decrypt_byte <- (temp * (temp ^ 1)) >> 8 +end decrypt_byte + +After the header is decrypted, the last 1 or 2 bytes in Buffer +should be the high-order word/byte of the CRC for the file being +decrypted, stored in Intel low-byte/high-byte order. Versions of +PKZIP prior to 2.0 used a 2 byte CRC check; a 1 byte CRC check is +used on versions after 2.0. This can be used to test if the password +supplied is correct or not. + +Step 3 - Decrypting the compressed data stream +---------------------------------------------- + +The compressed data stream can be decrypted as follows: + +loop until done + read a character into C + Temp <- C ^ decrypt_byte() + update_keys(temp) + output Temp +end loop + + +VIII. Strong Encryption Specification +------------------------------------- + +The Strong Encryption technology defined in this specification is +covered under a pending patent application. The use or implementation +in a product of certain technological aspects set forth in the current +APPNOTE, including those with regard to strong encryption, patching, +or extended tape operations requires a license from PKWARE. Portions +of this Strong Encryption technology are available for use at no charge. +Contact PKWARE for licensing terms and conditions. Refer to section II +of this APPNOTE (Contacting PKWARE) for information on how to +contact PKWARE. + +Version 5.x of this specification introduced support for strong +encryption algorithms. These algorithms can be used with either +a password or an X.509v3 digital certificate to encrypt each file. +This format specification supports either password or certificate +based encryption to meet the security needs of today, to enable +interoperability between users within both PKI and non-PKI +environments, and to ensure interoperability between different +computing platforms that are running a ZIP program. + +Password based encryption is the most common form of encryption +people are familiar with. However, inherent weaknesses with +passwords (e.g. susceptibility to dictionary/brute force attack) +as well as password management and support issues make certificate +based encryption a more secure and scalable option. Industry +efforts and support are defining and moving towards more advanced +security solutions built around X.509v3 digital certificates and +Public Key Infrastructures(PKI) because of the greater scalability, +administrative options, and more robust security over traditional +password based encryption. + +Most standard encryption algorithms are supported with this +specification. Reference implementations for many of these +algorithms are available from either commercial or open source +distributors. Readily available cryptographic toolkits make +implementation of the encryption features straight-forward. +This document is not intended to provide a treatise on data +encryption principles or theory. Its purpose is to document the +data structures required for implementing interoperable data +encryption within the .ZIP format. It is strongly recommended that +you have a good understanding of data encryption before reading +further. + +The algorithms introduced in Version 5.0 of this specification +include: + + RC2 40 bit, 64 bit, and 128 bit + RC4 40 bit, 64 bit, and 128 bit + DES + 3DES 112 bit and 168 bit + +Version 5.1 adds support for the following: + + AES 128 bit, 192 bit, and 256 bit + + +Version 6.1 introduces encryption data changes to support +interoperability with Smartcard and USB Token certificate storage +methods which do not support the OAEP strengthening standard. + +Version 6.2 introduces support for encrypting metadata by compressing +and encrypting the central directory data structure to reduce information +leakage. Information leakage can occur in legacy ZIP applications +through exposure of information about a file even though that file is +stored encrypted. The information exposed consists of file +characteristics stored within the records and fields defined by this +specification. This includes data such as a files name, its original +size, timestamp and CRC32 value. + +Version 6.3 introduces support for encrypting data using the Blowfish +and Twofish algorithms. These are symmetric block ciphers developed +by Bruce Schneier. Blowfish supports using a variable length key from +32 to 448 bits. Block size is 64 bits. Implementations should use 16 +rounds and the only mode supported within ZIP files is CBC. Twofish +supports key sizes 128, 192 and 256 bits. Block size is 128 bits. +Implementations should use 16 rounds and the only mode supported within +ZIP files is CBC. Information and source code for both Blowfish and +Twofish algorithms can be found on the internet. Consult with the author +of these algorithms for information on terms or restrictions on use. + +Central Directory Encryption provides greater protection against +information leakage by encrypting the Central Directory structure and +by masking key values that are replicated in the unencrypted Local +Header. ZIP compatible programs that cannot interpret an encrypted +Central Directory structure cannot rely on the data in the corresponding +Local Header for decompression information. + +Extra Field records that may contain information about a file that should +not be exposed should not be stored in the Local Header and should only +be written to the Central Directory where they can be encrypted. This +design currently does not support streaming. Information in the End of +Central Directory record, the Zip64 End of Central Directory Locator, +and the Zip64 End of Central Directory records are not encrypted. Access +to view data on files within a ZIP file with an encrypted Central Directory +requires the appropriate password or private key for decryption prior to +viewing any files, or any information about the files, in the archive. + +Older ZIP compatible programs not familiar with the Central Directory +Encryption feature will no longer be able to recognize the Central +Directory and may assume the ZIP file is corrupt. Programs that +attempt streaming access using Local Headers will see invalid +information for each file. Central Directory Encryption need not be +used for every ZIP file. Its use is recommended for greater security. +ZIP files not using Central Directory Encryption should operate as +in the past. + +This strong encryption feature specification is intended to provide for +scalable, cross-platform encryption needs ranging from simple password +encryption to authenticated public/private key encryption. + +Encryption provides data confidentiality and privacy. It is +recommended that you combine X.509 digital signing with encryption +to add authentication and non-repudiation. + + +Single Password Symmetric Encryption Method: +------------------------------------------- + +The Single Password Symmetric Encryption Method using strong +encryption algorithms operates similarly to the traditional +PKWARE encryption defined in this format. Additional data +structures are added to support the processing needs of the +strong algorithms. + +The Strong Encryption data structures are: + +1. General Purpose Bits - Bits 0 and 6 of the General Purpose bit +flag in both local and central header records. Both bits set +indicates strong encryption. Bit 13, when set indicates the Central +Directory is encrypted and that selected fields in the Local Header +are masked to hide their actual value. + + +2. Extra Field 0x0017 in central header only. + + Fields to consider in this record are: + + Format - the data format identifier for this record. The only + value allowed at this time is the integer value 2. + + AlgId - integer identifier of the encryption algorithm from the + following range + + 0x6601 - DES + 0x6602 - RC2 (version needed to extract < 5.2) + 0x6603 - 3DES 168 + 0x6609 - 3DES 112 + 0x660E - AES 128 + 0x660F - AES 192 + 0x6610 - AES 256 + 0x6702 - RC2 (version needed to extract >= 5.2) + 0x6720 - Blowfish + 0x6721 - Twofish + 0x6801 - RC4 + 0xFFFF - Unknown algorithm + + Bitlen - Explicit bit length of key + + 32 - 448 bits + + Flags - Processing flags needed for decryption + + 0x0001 - Password is required to decrypt + 0x0002 - Certificates only + 0x0003 - Password or certificate required to decrypt + + Values > 0x0003 reserved for certificate processing + + +3. Decryption header record preceding compressed file data. + + -Decryption Header: + + Value Size Description + ----- ---- ----------- + IVSize 2 bytes Size of initialization vector (IV) + IVData IVSize Initialization vector for this file + Size 4 bytes Size of remaining decryption header data + Format 2 bytes Format definition for this record + AlgID 2 bytes Encryption algorithm identifier + Bitlen 2 bytes Bit length of encryption key + Flags 2 bytes Processing flags + ErdSize 2 bytes Size of Encrypted Random Data + ErdData ErdSize Encrypted Random Data + Reserved1 4 bytes Reserved certificate processing data + Reserved2 (var) Reserved for certificate processing data + VSize 2 bytes Size of password validation data + VData VSize-4 Password validation data + VCRC32 4 bytes Standard ZIP CRC32 of password validation data + + IVData - The size of the IV should match the algorithm block size. + The IVData can be completely random data. If the size of + the randomly generated data does not match the block size + it should be complemented with zero's or truncated as + necessary. If IVSize is 0,then IV = CRC32 + Uncompressed + File Size (as a 64 bit little-endian, unsigned integer value). + + Format - the data format identifier for this record. The only + value allowed at this time is the integer value 3. + + AlgId - integer identifier of the encryption algorithm from the + following range + + 0x6601 - DES + 0x6602 - RC2 (version needed to extract < 5.2) + 0x6603 - 3DES 168 + 0x6609 - 3DES 112 + 0x660E - AES 128 + 0x660F - AES 192 + 0x6610 - AES 256 + 0x6702 - RC2 (version needed to extract >= 5.2) + 0x6720 - Blowfish + 0x6721 - Twofish + 0x6801 - RC4 + 0xFFFF - Unknown algorithm + + Bitlen - Explicit bit length of key + + 32 - 448 bits + + Flags - Processing flags needed for decryption + + 0x0001 - Password is required to decrypt + 0x0002 - Certificates only + 0x0003 - Password or certificate required to decrypt + + Values > 0x0003 reserved for certificate processing + + ErdData - Encrypted random data is used to store random data that + is used to generate a file session key for encrypting + each file. SHA1 is used to calculate hash data used to + derive keys. File session keys are derived from a master + session key generated from the user-supplied password. + If the Flags field in the decryption header contains + the value 0x4000, then the ErdData field must be + decrypted using 3DES. If the value 0x4000 is not set, + then the ErdData field must be decrypted using AlgId. + + + Reserved1 - Reserved for certificate processing, if value is + zero, then Reserved2 data is absent. See the explanation + under the Certificate Processing Method for details on + this data structure. + + Reserved2 - If present, the size of the Reserved2 data structure + is located by skipping the first 4 bytes of this field + and using the next 2 bytes as the remaining size. See + the explanation under the Certificate Processing Method + for details on this data structure. + + VSize - This size value will always include the 4 bytes of the + VCRC32 data and will be greater than 4 bytes. + + VData - Random data for password validation. This data is VSize + in length and VSize must be a multiple of the encryption + block size. VCRC32 is a checksum value of VData. + VData and VCRC32 are stored encrypted and start the + stream of encrypted data for a file. + + +4. Useful Tips + +Strong Encryption is always applied to a file after compression. The +block oriented algorithms all operate in Cypher Block Chaining (CBC) +mode. The block size used for AES encryption is 16. All other block +algorithms use a block size of 8. Two ID's are defined for RC2 to +account for a discrepancy found in the implementation of the RC2 +algorithm in the cryptographic library on Windows XP SP1 and all +earlier versions of Windows. It is recommended that zero length files +not be encrypted, however programs should be prepared to extract them +if they are found within a ZIP file. + +A pseudo-code representation of the encryption process is as follows: + +Password = GetUserPassword() +MasterSessionKey = DeriveKey(SHA1(Password)) +RD = CryptographicStrengthRandomData() +For Each File + IV = CryptographicStrengthRandomData() + VData = CryptographicStrengthRandomData() + VCRC32 = CRC32(VData) + FileSessionKey = DeriveKey(SHA1(IV + RD) + ErdData = Encrypt(RD,MasterSessionKey,IV) + Encrypt(VData + VCRC32 + FileData, FileSessionKey,IV) +Done + +The function names and parameter requirements will depend on +the choice of the cryptographic toolkit selected. Almost any +toolkit supporting the reference implementations for each +algorithm can be used. The RSA BSAFE(r), OpenSSL, and Microsoft +CryptoAPI libraries are all known to work well. + + +Single Password - Central Directory Encryption: +----------------------------------------------- + +Central Directory Encryption is achieved within the .ZIP format by +encrypting the Central Directory structure. This encapsulates the metadata +most often used for processing .ZIP files. Additional metadata is stored for +redundancy in the Local Header for each file. The process of concealing +metadata by encrypting the Central Directory does not protect the data within +the Local Header. To avoid information leakage from the exposed metadata +in the Local Header, the fields containing information about a file are masked. + +Local Header: + +Masking replaces the true content of the fields for a file in the Local +Header with false information. When masked, the Local Header is not +suitable for streaming access and the options for data recovery of damaged +archives is reduced. Extra Data fields that may contain confidential +data should not be stored within the Local Header. The value set into +the Version needed to extract field should be the correct value needed to +extract the file without regard to Central Directory Encryption. The fields +within the Local Header targeted for masking when the Central Directory is +encrypted are: + + Field Name Mask Value + ------------------ --------------------------- + compression method 0 + last mod file time 0 + last mod file date 0 + crc-32 0 + compressed size 0 + uncompressed size 0 + file name (variable size) Base 16 value from the + range 1 - 0xFFFFFFFFFFFFFFFF + represented as a string whose + size will be set into the + file name length field + +The Base 16 value assigned as a masked file name is simply a sequentially +incremented value for each file starting with 1 for the first file. +Modifications to a ZIP file may cause different values to be stored for +each file. For compatibility, the file name field in the Local Header +should never be left blank. As of Version 6.2 of this specification, +the Compression Method and Compressed Size fields are not yet masked. +Fields having a value of 0xFFFF or 0xFFFFFFFF for the ZIP64 format +should not be masked. + +Encrypting the Central Directory: + +Encryption of the Central Directory does not include encryption of the +Central Directory Signature data, the Zip64 End of Central Directory +record, the Zip64 End of Central Directory Locator, or the End +of Central Directory record. The ZIP file comment data is never +encrypted. + +Before encrypting the Central Directory, it may optionally be compressed. +Compression is not required, but for storage efficiency it is assumed +this structure will be compressed before encrypting. Similarly, this +specification supports compressing the Central Directory without +requiring that it also be encrypted. Early implementations of this +feature will assume the encryption method applied to files matches the +encryption applied to the Central Directory. + +Encryption of the Central Directory is done in a manner similar to +that of file encryption. The encrypted data is preceded by a +decryption header. The decryption header is known as the Archive +Decryption Header. The fields of this record are identical to +the decryption header preceding each encrypted file. The location +of the Archive Decryption Header is determined by the value in the +Start of the Central Directory field in the Zip64 End of Central +Directory record. When the Central Directory is encrypted, the +Zip64 End of Central Directory record will always be present. + +The layout of the Zip64 End of Central Directory record for all +versions starting with 6.2 of this specification will follow the +Version 2 format. The Version 2 format is as follows: + +The leading fixed size fields within the Version 1 format for this +record remain unchanged. The record signature for both Version 1 +and Version 2 will be 0x06064b50. Immediately following the last +byte of the field known as the Offset of Start of Central +Directory With Respect to the Starting Disk Number will begin the +new fields defining Version 2 of this record. + +New fields for Version 2: + +Note: all fields stored in Intel low-byte/high-byte order. + + Value Size Description + ----- ---- ----------- + Compression Method 2 bytes Method used to compress the + Central Directory + Compressed Size 8 bytes Size of the compressed data + Original Size 8 bytes Original uncompressed size + AlgId 2 bytes Encryption algorithm ID + BitLen 2 bytes Encryption key length + Flags 2 bytes Encryption flags + HashID 2 bytes Hash algorithm identifier + Hash Length 2 bytes Length of hash data + Hash Data (variable) Hash data + +The Compression Method accepts the same range of values as the +corresponding field in the Central Header. + +The Compressed Size and Original Size values will not include the +data of the Central Directory Signature which is compressed or +encrypted. + +The AlgId, BitLen, and Flags fields accept the same range of values +the corresponding fields within the 0x0017 record. + +Hash ID identifies the algorithm used to hash the Central Directory +data. This data does not have to be hashed, in which case the +values for both the HashID and Hash Length will be 0. Possible +values for HashID are: + + Value Algorithm + ------ --------- + 0x0000 none + 0x0001 CRC32 + 0x8003 MD5 + 0x8004 SHA1 + 0x8007 RIPEMD160 + 0x800C SHA256 + 0x800D SHA384 + 0x800E SHA512 + +When the Central Directory data is signed, the same hash algorithm +used to hash the Central Directory for signing should be used. +This is recommended for processing efficiency, however, it is +permissible for any of the above algorithms to be used independent +of the signing process. + +The Hash Data will contain the hash data for the Central Directory. +The length of this data will vary depending on the algorithm used. + +The Version Needed to Extract should be set to 62. + +The value for the Total Number of Entries on the Current Disk will +be 0. These records will no longer support random access when +encrypting the Central Directory. + +When the Central Directory is compressed and/or encrypted, the +End of Central Directory record will store the value 0xFFFFFFFF +as the value for the Total Number of Entries in the Central +Directory. The value stored in the Total Number of Entries in +the Central Directory on this Disk field will be 0. The actual +values will be stored in the equivalent fields of the Zip64 +End of Central Directory record. + +Decrypting and decompressing the Central Directory is accomplished +in the same manner as decrypting and decompressing a file. + +Certificate Processing Method: +----------------------------- + +The Certificate Processing Method of for ZIP file encryption +defines the following additional data fields: + +1. Certificate Flag Values + +Additional processing flags that can be present in the Flags field of both +the 0x0017 field of the central directory Extra Field and the Decryption +header record preceding compressed file data are: + + 0x0007 - reserved for future use + 0x000F - reserved for future use + 0x0100 - Indicates non-OAEP key wrapping was used. If this + this field is set, the version needed to extract must + be at least 61. This means OAEP key wrapping is not + used when generating a Master Session Key using + ErdData. + 0x4000 - ErdData must be decrypted using 3DES-168, otherwise use the + same algorithm used for encrypting the file contents. + 0x8000 - reserved for future use + + +2. CertData - Extra Field 0x0017 record certificate data structure + +The data structure used to store certificate data within the section +of the Extra Field defined by the CertData field of the 0x0017 +record are as shown: + + Value Size Description + ----- ---- ----------- + RCount 4 bytes Number of recipients. + HashAlg 2 bytes Hash algorithm identifier + HSize 2 bytes Hash size + SRList (var) Simple list of recipients hashed public keys + + + RCount This defines the number intended recipients whose + public keys were used for encryption. This identifies + the number of elements in the SRList. + + HashAlg This defines the hash algorithm used to calculate + the public key hash of each public key used + for encryption. This field currently supports + only the following value for SHA-1 + + 0x8004 - SHA1 + + HSize This defines the size of a hashed public key. + + SRList This is a variable length list of the hashed + public keys for each intended recipient. Each + element in this list is HSize. The total size of + SRList is determined using RCount * HSize. + + +3. Reserved1 - Certificate Decryption Header Reserved1 Data: + + Value Size Description + ----- ---- ----------- + RCount 4 bytes Number of recipients. + + RCount This defines the number intended recipients whose + public keys were used for encryption. This defines + the number of elements in the REList field defined below. + + +4. Reserved2 - Certificate Decryption Header Reserved2 Data Structures: + + + Value Size Description + ----- ---- ----------- + HashAlg 2 bytes Hash algorithm identifier + HSize 2 bytes Hash size + REList (var) List of recipient data elements + + + HashAlg This defines the hash algorithm used to calculate + the public key hash of each public key used + for encryption. This field currently supports + only the following value for SHA-1 + + 0x8004 - SHA1 + + HSize This defines the size of a hashed public key + defined in REHData. + + REList This is a variable length of list of recipient data. + Each element in this list consists of a Recipient + Element data structure as follows: + + + Recipient Element (REList) Data Structure: + + Value Size Description + ----- ---- ----------- + RESize 2 bytes Size of REHData + REKData + REHData HSize Hash of recipients public key + REKData (var) Simple key blob + + + RESize This defines the size of an individual REList + element. This value is the combined size of the + REHData field + REKData field. REHData is defined by + HSize. REKData is variable and can be calculated + for each REList element using RESize and HSize. + + REHData Hashed public key for this recipient. + + REKData Simple Key Blob. The format of this data structure + is identical to that defined in the Microsoft + CryptoAPI and generated using the CryptExportKey() + function. The version of the Simple Key Blob + supported at this time is 0x02 as defined by + Microsoft. + +Certificate Processing - Central Directory Encryption: +------------------------------------------------------ + +Central Directory Encryption using Digital Certificates will +operate in a manner similar to that of Single Password Central +Directory Encryption. This record will only be present when there +is data to place into it. Currently, data is placed into this +record when digital certificates are used for either encrypting +or signing the files within a ZIP file. When only password +encryption is used with no certificate encryption or digital +signing, this record is not currently needed. When present, this +record will appear before the start of the actual Central Directory +data structure and will be located immediately after the Archive +Decryption Header if the Central Directory is encrypted. + +The Archive Extra Data record will be used to store the following +information. Additional data may be added in future versions. + +Extra Data Fields: + +0x0014 - PKCS#7 Store for X.509 Certificates +0x0016 - X.509 Certificate ID and Signature for central directory +0x0019 - PKCS#7 Encryption Recipient Certificate List + +The 0x0014 and 0x0016 Extra Data records that otherwise would be +located in the first record of the Central Directory for digital +certificate processing. When encrypting or compressing the Central +Directory, the 0x0014 and 0x0016 records must be located in the +Archive Extra Data record and they should not remain in the first +Central Directory record. The Archive Extra Data record will also +be used to store the 0x0019 data. + +When present, the size of the Archive Extra Data record will be +included in the size of the Central Directory. The data of the +Archive Extra Data record will also be compressed and encrypted +along with the Central Directory data structure. + +Certificate Processing Differences: + +The Certificate Processing Method of encryption differs from the +Single Password Symmetric Encryption Method as follows. Instead +of using a user-defined password to generate a master session key, +cryptographically random data is used. The key material is then +wrapped using standard key-wrapping techniques. This key material +is wrapped using the public key of each recipient that will need +to decrypt the file using their corresponding private key. + +This specification currently assumes digital certificates will follow +the X.509 V3 format for 1024 bit and higher RSA format digital +certificates. Implementation of this Certificate Processing Method +requires supporting logic for key access and management. This logic +is outside the scope of this specification. + +OAEP Processing with Certificate-based Encryption: + +OAEP stands for Optimal Asymmetric Encryption Padding. It is a +strengthening technique used for small encoded items such as decryption +keys. This is commonly applied in cryptographic key-wrapping techniques +and is supported by PKCS #1. Versions 5.0 and 6.0 of this specification +were designed to support OAEP key-wrapping for certificate-based +decryption keys for additional security. + +Support for private keys stored on Smartcards or Tokens introduced +a conflict with this OAEP logic. Most card and token products do +not support the additional strengthening applied to OAEP key-wrapped +data. In order to resolve this conflict, versions 6.1 and above of this +specification will no longer support OAEP when encrypting using +digital certificates. + +Versions of PKZIP available during initial development of the +certificate processing method set a value of 61 into the +version needed to extract field for a file. This indicates that +non-OAEP key wrapping is used. This affects certificate encryption +only, and password encryption functions should not be affected by +this value. This means values of 61 may be found on files encrypted +with certificates only, or on files encrypted with both password +encryption and certificate encryption. Files encrypted with both +methods can safely be decrypted using the password methods documented. + +IX. Change Process +------------------ + +In order for the .ZIP file format to remain a viable definition, this +specification should be considered as open for periodic review and +revision. Although this format was originally designed with a +certain level of extensibility, not all changes in technology +(present or future) were or will be necessarily considered in its +design. If your application requires new definitions to the +extensible sections in this format, or if you would like to +submit new data structures, please forward your request to +zipformat@pkware.com. All submissions will be reviewed by the +ZIP File Specification Committee for possible inclusion into +future versions of this specification. Periodic revisions +to this specification will be published to ensure interoperability. +We encourage comments and feedback that may help improve clarity +or content. + +X. Incorporating PKWARE Proprietary Technology into Your Product +---------------------------------------------------------------- + +PKWARE is committed to the interoperability and advancement of the +.ZIP format. PKWARE offers a free license for certain technological +aspects described above under certain restrictions and conditions. +However, the use or implementation in a product of certain technological +aspects set forth in the current APPNOTE, including those with regard to +strong encryption, patching, or extended tape operations requires a +license from PKWARE. Please contact PKWARE with regard to acquiring +a license. + +XI. Acknowledgements +--------------------- + +In addition to the above mentioned contributors to PKZIP and PKUNZIP, +I would like to extend special thanks to Robert Mahoney for suggesting +the extension .ZIP for this software. + +XII. References +--------------- + + Fiala, Edward R., and Greene, Daniel H., "Data compression with + finite windows", Communications of the ACM, Volume 32, Number 4, + April 1989, pages 490-505. + + Held, Gilbert, "Data Compression, Techniques and Applications, + Hardware and Software Considerations", John Wiley & Sons, 1987. + + Huffman, D.A., "A method for the construction of minimum-redundancy + codes", Proceedings of the IRE, Volume 40, Number 9, September 1952, + pages 1098-1101. + + Nelson, Mark, "LZW Data Compression", Dr. Dobbs Journal, Volume 14, + Number 10, October 1989, pages 29-37. + + Nelson, Mark, "The Data Compression Book", M&T Books, 1991. + + Storer, James A., "Data Compression, Methods and Theory", + Computer Science Press, 1988 + + Welch, Terry, "A Technique for High-Performance Data Compression", + IEEE Computer, Volume 17, Number 6, June 1984, pages 8-19. + + Ziv, J. and Lempel, A., "A universal algorithm for sequential data + compression", Communications of the ACM, Volume 30, Number 6, + June 1987, pages 520-540. + + Ziv, J. and Lempel, A., "Compression of individual sequences via + variable-rate coding", IEEE Transactions on Information Theory, + Volume 24, Number 5, September 1978, pages 530-536. + + +APPENDIX A - AS/400 Extra Field (0x0065) Attribute Definitions +-------------------------------------------------------------- + +Field Definition Structure: + + a. field length including length 2 bytes + b. field code 2 bytes + c. data x bytes + +Field Code Description + 4001 Source type i.e. CLP etc + 4002 The text description of the library + 4003 The text description of the file + 4004 The text description of the member + 4005 x'F0' or 0 is PF-DTA, x'F1' or 1 is PF_SRC + 4007 Database Type Code 1 byte + 4008 Database file and fields definition + 4009 GZIP file type 2 bytes + 400B IFS code page 2 bytes + 400C IFS Creation Time 4 bytes + 400D IFS Access Time 4 bytes + 400E IFS Modification time 4 bytes + 005C Length of the records in the file 2 bytes + 0068 GZIP two words 8 bytes + +APPENDIX B - z/OS Extra Field (0x0065) Attribute Definitions +------------------------------------------------------------ + +Field Definition Structure: + + a. field length including length 2 bytes + b. field code 2 bytes + c. data x bytes + +Field Code Description + 0001 File Type 2 bytes + 0002 NonVSAM Record Format 1 byte + 0003 Reserved + 0004 NonVSAM Block Size 2 bytes Big Endian + 0005 Primary Space Allocation 3 bytes Big Endian + 0006 Secondary Space Allocation 3 bytes Big Endian + 0007 Space Allocation Type1 byte flag + 0008 Modification Date Retired with PKZIP 5.0 + + 0009 Expiration Date Retired with PKZIP 5.0 + + 000A PDS Directory Block Allocation 3 bytes Big Endian binary value + 000B NonVSAM Volume List variable + 000C UNIT Reference Retired with PKZIP 5.0 + + 000D DF/SMS Management Class 8 bytes EBCDIC Text Value + 000E DF/SMS Storage Class 8 bytes EBCDIC Text Value + 000F DF/SMS Data Class 8 bytes EBCDIC Text Value + 0010 PDS/PDSE Member Info. 30 bytes + 0011 VSAM sub-filetype 2 bytes + 0012 VSAM LRECL 13 bytes EBCDIC "(num_avg num_max)" + 0013 VSAM Cluster Name Retired with PKZIP 5.0 + + 0014 VSAM KSDS Key Information 13 bytes EBCDIC "(num_length num_position)" + 0015 VSAM Average LRECL 5 bytes EBCDIC num_value padded with blanks + 0016 VSAM Maximum LRECL 5 bytes EBCDIC num_value padded with blanks + 0017 VSAM KSDS Key Length 5 bytes EBCDIC num_value padded with blanks + 0018 VSAM KSDS Key Position 5 bytes EBCDIC num_value padded with blanks + 0019 VSAM Data Name 1-44 bytes EBCDIC text string + 001A VSAM KSDS Index Name 1-44 bytes EBCDIC text string + 001B VSAM Catalog Name 1-44 bytes EBCDIC text string + 001C VSAM Data Space Type 9 bytes EBCDIC text string + 001D VSAM Data Space Primary 9 bytes EBCDIC num_value left-justified + 001E VSAM Data Space Secondary 9 bytes EBCDIC num_value left-justified + 001F VSAM Data Volume List variable EBCDIC text list of 6-character Volume IDs + 0020 VSAM Data Buffer Space 8 bytes EBCDIC num_value left-justified + 0021 VSAM Data CISIZE 5 bytes EBCDIC num_value left-justified + 0022 VSAM Erase Flag 1 byte flag + 0023 VSAM Free CI % 3 bytes EBCDIC num_value left-justified + 0024 VSAM Free CA % 3 bytes EBCDIC num_value left-justified + 0025 VSAM Index Volume List variable EBCDIC text list of 6-character Volume IDs + 0026 VSAM Ordered Flag 1 byte flag + 0027 VSAM REUSE Flag 1 byte flag + 0028 VSAM SPANNED Flag 1 byte flag + 0029 VSAM Recovery Flag 1 byte flag + 002A VSAM WRITECHK Flag 1 byte flag + 002B VSAM Cluster/Data SHROPTS 3 bytes EBCDIC "n,y" + 002C VSAM Index SHROPTS 3 bytes EBCDIC "n,y" + 002D VSAM Index Space Type 9 bytes EBCDIC text string + 002E VSAM Index Space Primary 9 bytes EBCDIC num_value left-justified + 002F VSAM Index Space Secondary 9 bytes EBCDIC num_value left-justified + 0030 VSAM Index CISIZE 5 bytes EBCDIC num_value left-justified + 0031 VSAM Index IMBED 1 byte flag + 0032 VSAM Index Ordered Flag 1 byte flag + 0033 VSAM REPLICATE Flag 1 byte flag + 0034 VSAM Index REUSE Flag 1 byte flag + 0035 VSAM Index WRITECHK Flag 1 byte flag Retired with PKZIP 5.0 + + 0036 VSAM Owner 8 bytes EBCDIC text string + 0037 VSAM Index Owner 8 bytes EBCDIC text string + 0038 Reserved + 0039 Reserved + 003A Reserved + 003B Reserved + 003C Reserved + 003D Reserved + 003E Reserved + 003F Reserved + 0040 Reserved + 0041 Reserved + 0042 Reserved + 0043 Reserved + 0044 Reserved + 0045 Reserved + 0046 Reserved + 0047 Reserved + 0048 Reserved + 0049 Reserved + 004A Reserved + 004B Reserved + 004C Reserved + 004D Reserved + 004E Reserved + 004F Reserved + 0050 Reserved + 0051 Reserved + 0052 Reserved + 0053 Reserved + 0054 Reserved + 0055 Reserved + 0056 Reserved + 0057 Reserved + 0058 PDS/PDSE Member TTR Info. 6 bytes Big Endian + 0059 PDS 1st LMOD Text TTR 3 bytes Big Endian + 005A PDS LMOD EP Rec # 4 bytes Big Endian + 005B Reserved + 005C Max Length of records 2 bytes Big Endian + 005D PDSE Flag 1 byte flag + 005E Reserved + 005F Reserved + 0060 Reserved + 0061 Reserved + 0062 Reserved + 0063 Reserved + 0064 Reserved + 0065 Last Date Referenced 4 bytes Packed Hex "yyyymmdd" + 0066 Date Created 4 bytes Packed Hex "yyyymmdd" + 0068 GZIP two words 8 bytes + 0071 Extended NOTE Location 12 bytes Big Endian + 0072 Archive device UNIT 6 bytes EBCDIC + 0073 Archive 1st Volume 6 bytes EBCDIC + 0074 Archive 1st VOL File Seq# 2 bytes Binary + +APPENDIX C - Zip64 Extensible Data Sector Mappings (EFS) +-------------------------------------------------------- + + -Z390 Extra Field: + + The following is the general layout of the attributes for the + ZIP 64 "extra" block for extended tape operations. Portions of + this extended tape processing technology is covered under a + pending patent application. The use or implementation in a + product of certain technological aspects set forth in the + current APPNOTE, including those with regard to strong encryption, + patching or extended tape operations, requires a license from + PKWARE. Please contact PKWARE with regard to acquiring a license. + + + Note: some fields stored in Big Endian format. All text is + in EBCDIC format unless otherwise specified. + + Value Size Description + ----- ---- ----------- + (Z390) 0x0065 2 bytes Tag for this "extra" block type + Size 4 bytes Size for the following data block + Tag 4 bytes EBCDIC "Z390" + Length71 2 bytes Big Endian + Subcode71 2 bytes Enote type code + FMEPos 1 byte + Length72 2 bytes Big Endian + Subcode72 2 bytes Unit type code + Unit 1 byte Unit + Length73 2 bytes Big Endian + Subcode73 2 bytes Volume1 type code + FirstVol 1 byte Volume + Length74 2 bytes Big Endian + Subcode74 2 bytes FirstVol file sequence + FileSeq 2 bytes Sequence + +APPENDIX D - Language Encoding (EFS) +------------------------------------ + +The ZIP format has historically supported only the original IBM PC character +encoding set, commonly referred to as IBM Code Page 437. This limits storing +file name characters to only those within the original MS-DOS range of values +and does not properly support file names in other character encodings, or +languages. To address this limitation, this specification will support the +following change. + +If general purpose bit 11 is unset, the file name and comment should conform +to the original ZIP character encoding. If general purpose bit 11 is set, the +filename and comment must support The Unicode Standard, Version 4.1.0 or +greater using the character encoding form defined by the UTF-8 storage +specification. The Unicode Standard is published by the The Unicode +Consortium (www.unicode.org). UTF-8 encoded data stored within ZIP files +is expected to not include a byte order mark (BOM). + +Applications may choose to supplement this file name storage through the use +of the 0x0008 Extra Field. Storage for this optional field is currently +undefined, however it will be used to allow storing extended information +on source or target encoding that may further assist applications with file +name, or file content encoding tasks. Please contact PKWARE with any +requirements on how this field should be used. + +The 0x0008 Extra Field storage may be used with either setting for general +purpose bit 11. Examples of the intended usage for this field is to store +whether "modified-UTF-8" (JAVA) is used, or UTF-8-MAC. Similarly, other +commonly used character encoding (code page) designations can be indicated +through this field. Formalized values for use of the 0x0008 record remain +undefined at this time. The definition for the layout of the 0x0008 field +will be published when available. Use of the 0x0008 Extra Field provides +for storing data within a ZIP file in an encoding other than IBM Code +Page 437 or UTF-8. + +General purpose bit 11 will not imply any encoding of file content or +password. Values defining character encoding for file content or +password must be stored within the 0x0008 Extended Language Encoding +Extra Field. + +Ed Gordon of the Info-ZIP group has defined a pair of "extra field" records +that can be used to store UTF-8 file name and file comment fields. These +records can be used for cases when the general purpose bit 11 method +for storing UTF-8 data in the standard file name and comment fields is +not desirable. A common case for this alternate method is if backward +compatibility with older programs is required. + +Definitions for the record structure of these fields are included above +in the section on 3rd party mappings for "extra field" records. These +records are identified by Header ID's 0x6375 (Info-ZIP Unicode Comment +Extra Field) and 0x7075 (Info-ZIP Unicode Path Extra Field). + +The choice of which storage method to use when writing a ZIP file is left +to the implementation. Developers should expect that a ZIP file may +contain either method and should provide support for reading data in +either format. Use of general purpose bit 11 reduces storage requirements +for file name data by not requiring additional "extra field" data for +each file, but can result in older ZIP programs not being able to extract +files. Use of the 0x6375 and 0x7075 records will result in a ZIP file +that should always be readable by older ZIP programs, but requires more +storage per file to write file name and/or file comment fields. + + + + diff --git a/imgsrc/catalog.svg b/imgsrc/catalog.svg index 724e0cf8e5..7ee05e4214 100644 --- a/imgsrc/catalog.svg +++ b/imgsrc/catalog.svg @@ -1,157 +1,157 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/imgsrc/sd.svg b/imgsrc/sd.svg index 8d33283fea..746299b693 100644 --- a/imgsrc/sd.svg +++ b/imgsrc/sd.svg @@ -1,198 +1,198 @@ - - - - - - - - - - - - -]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 12.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 51448) --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [ + <!ENTITY ns_extend "http://ns.adobe.com/Extensibility/1.0/"> + <!ENTITY ns_ai "http://ns.adobe.com/AdobeIllustrator/10.0/"> + <!ENTITY ns_graphs "http://ns.adobe.com/Graphs/1.0/"> + <!ENTITY ns_vars "http://ns.adobe.com/Variables/1.0/"> + <!ENTITY ns_imrep "http://ns.adobe.com/ImageReplacement/1.0/"> + <!ENTITY ns_sfw "http://ns.adobe.com/SaveForWeb/1.0/"> + <!ENTITY ns_custom "http://ns.adobe.com/GenericCustomNamespace/1.0/"> + <!ENTITY ns_adobe_xpath "http://ns.adobe.com/XPath/1.0/"> + <!ENTITY ns_svg "http://www.w3.org/2000/svg"> + <!ENTITY ns_xlink "http://www.w3.org/1999/xlink"> +]> +<svg version="1.1" id="Ebene_1" xmlns:x="&ns_extend;" xmlns:i="&ns_ai;" xmlns:graph="&ns_graphs;" + xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="128" height="128" viewBox="0 0 128 128" + overflow="visible" enable-background="new 0 0 128 128" xml:space="preserve"> +<metadata> + <sfw xmlns="&ns_sfw;"> + <slices> + <slice x="0" y="0" height="128" width="128" sliceID="1654033371"></slice> + </slices> + <sliceSourceBounds x="-8127" y="-8128" height="16383" width="16383" bottomLeftOrigin="true"></sliceSourceBounds> + </sfw> +</metadata> +<switch> + <foreignObject requiredExtensions="&ns_ai;" x="0" y="0" width="1" height="1"> + <i:pgfRef xlink:href="#adobe_illustrator_pgf"> + </i:pgfRef> + </foreignObject> + <g i:extraneous="self"> + <rect id="_x3C_Sezione_x3E_" fill="none" width="128" height="128"/> + <path opacity="0.05" fill="#323232" d="M21.884,3c-3.267,0-5.925,2.658-5.925,5.925v24.544c0,0.667,0.198,1.365,0.519,2.098 + c-0.321,0.731-0.519,1.426-0.519,2.086v7.371c0,2.422,1.572,4.476,3.851,5.347c0,0.963,0,4.704,0,5.667 + c-2.279,0.872-3.851,2.926-3.851,5.347v59.688c0,3.268,2.658,5.926,5.925,5.926h34.47c0.899,0,1.851-0.36,2.826-0.978 + c0.434,0.001,10.105,0.014,10.525,0.015c0.971,0.608,1.945,0.963,2.904,0.963h33.507c3.268,0,5.926-2.658,5.926-5.926V50.32 + c0-1.978-1.07-3.726-2.775-4.799c1.686-1.082,2.775-2.861,2.775-4.794V21.44c0-1.045-0.4-2.034-1.128-2.784L96.958,4.221 + C96.211,3.445,95.163,3,94.083,3H21.884z"/> + <path opacity="0.1" fill="#323232" d="M21.884,4c-2.716,0-4.925,2.209-4.925,4.925v24.544c0,0.708,0.23,1.401,0.591,2.099 + c-0.361,0.696-0.591,1.385-0.591,2.085v7.371c0,2.308,1.672,4.184,3.851,4.693c0,1.161,0,5.814,0,6.975 + c-2.179,0.51-3.851,2.386-3.851,4.693v59.688c0,2.716,2.209,4.926,4.925,4.926h34.47c0.846,0,1.716-0.364,2.59-0.978 + c0.48,0.001,10.534,0.014,10.992,0.015c0.852,0.597,1.761,0.963,2.674,0.963h33.507c2.716,0,4.926-2.21,4.926-4.926V50.32 + c0-1.911-1.155-3.535-2.889-4.332c0-0.38,0-0.548,0-0.926c1.713-0.802,2.889-2.454,2.889-4.335V21.44 + c0-0.784-0.301-1.526-0.846-2.088L96.239,4.916C95.679,4.334,94.893,4,94.083,4H21.884z"/> + <path opacity="0.15" fill="#323232" d="M21.884,5c-2.165,0-3.925,1.761-3.925,3.925v24.544c0,0.771,0.286,1.47,0.697,2.1 + c-0.41,0.628-0.697,1.321-0.697,2.084v7.371c0,2.138,1.723,3.868,3.851,3.91c0,1.451,0,7.09,0,8.54 + c-2.128,0.044-3.851,1.775-3.851,3.911v59.688c0,2.165,1.761,3.926,3.925,3.926h34.47c0.782,0,1.574-0.376,2.33-0.978 + c0.548,0.001,10.913,0.014,11.505,0.015c0.543,0.443,1.385,0.963,2.421,0.963h33.507c2.165,0,3.926-1.761,3.926-3.926V50.32 + c0-1.783-1.24-3.238-2.889-3.706c0-0.722,0-1.454,0-2.175c1.646-0.468,2.889-1.929,2.889-3.712V21.44 + c0-0.523-0.2-1.017-0.563-1.392L95.521,5.61C95.146,5.223,94.622,5,94.083,5H21.884z"/> + <path opacity="0.2" fill="#323232" d="M21.884,6c-1.613,0-2.925,1.312-2.925,2.925v24.544c0,0.782,0.305,1.518,0.858,2.07 + c0.01,0.01,0.024,0.013,0.034,0.023c-0.547,0.532-0.893,1.27-0.893,2.091v7.371c0,1.613,1.312,2.925,2.925,2.925 + c0,0,0.463,0,0.925,0c0,1.546,0,8.965,0,10.509c-0.464,0.001-0.929,0.001-0.929,0.001c-1.611,0.003-2.922,1.315-2.922,2.925 + v59.688c0,1.613,1.312,2.926,2.925,2.926h34.47c0.774,0,1.492-0.462,2.038-0.978c0.65,0.001,11.395,0.014,12.165,0.015 + c0.522,0.5,1.264,0.963,2.054,0.963h33.507c1.613,0,2.926-1.312,2.926-2.926V50.32c0-1.6-1.294-2.896-2.889-2.918 + c0-1.075,0-2.684,0-3.75c0.001,0,0.017,0,0.017,0c1.584-0.028,2.872-1.34,2.872-2.925V21.44c0-0.259-0.101-0.509-0.281-0.695 + L94.802,6.305C94.613,6.11,94.354,6,94.083,6H21.884z"/> + <path opacity="0.25" fill="#323232" d="M106.152,42.652c1.05-0.019,1.89-0.875,1.89-1.925V21.44L94.083,7H21.884 + c-1.063,0-1.925,0.862-1.925,1.925v24.544c0,0.512,0.203,1.001,0.565,1.363c0.362,0.361,0.853,0.563,1.364,0.562l1.921-0.004 + v0.338h-1.925c-1.063,0-1.925,0.862-1.925,1.925v7.371c0,1.063,0.862,1.925,1.925,1.925h1.925v12.508l-1.927,0.003 + c-1.062,0.002-1.923,0.863-1.923,1.925v59.688c0,1.063,0.862,1.926,1.925,1.926h34.47c0.584,0,1.29-0.486,1.655-0.943l0.027-0.034 + l12.943,0.015c0.366,0.456,1.046,0.963,1.63,0.963h33.507c1.062,0,1.926-0.862,1.926-1.926V50.32c0-1.063-0.863-1.925-1.926-1.925 + h-0.963V42.67L106.152,42.652z"/> + <linearGradient id="XMLID_12_" gradientUnits="userSpaceOnUse" x1="14.5835" y1="20.999" x2="94.4877" y2="100.9032"> + <stop offset="0" style="stop-color:#A4C0E4"/> + <stop offset="1" style="stop-color:#001C56"/> + </linearGradient> + <path fill="url(#XMLID_12_)" d="M94.083,6H21.884c-1.063,0-1.925,0.862-1.925,1.925v24.544c0,0.966-0.001,1.927,1.929,1.925 + l1.921-0.004v24.067l-1.927,0.003c-1.924,0.003-1.923,0.485-1.923,1.925v59.688c0,1.063,0.862,1.926,1.925,1.926h34.47 + c0.584,0,1.29-0.486,1.655-0.943l0.027-0.034l12.943,0.015c0.366,0.456,1.046,0.963,1.63,0.963h33.507 + c1.062,0,1.926-0.862,1.926-1.926V49.32c0-1.444-0.481-1.925-1.926-1.925h-0.963V41.67l0.999-0.018 + c1.408-0.033,1.89-0.514,1.89-1.925V20.44L94.083,6z"/> + <linearGradient id="XMLID_13_" gradientUnits="userSpaceOnUse" x1="21.1328" y1="42.0396" x2="28.8344" y2="38.1887"> + <stop offset="0" style="stop-color:#EEEEEE"/> + <stop offset="1" style="stop-color:#BBBBBB"/> + </linearGradient> + <path fill="url(#XMLID_13_)" d="M29.104,44.025c0,1.063-0.862,1.925-1.925,1.925h-5.294c-1.063,0-1.925-0.862-1.925-1.925v-7.371 + c0-1.063,0.862-1.925,1.925-1.925h5.294c1.063,0,1.925,0.862,1.925,1.925V44.025z"/> + <path fill="#DDDDDD" d="M21.884,35.691c-0.531,0-0.963,0.432-0.963,0.962v7.371c0,0.531,0.432,0.963,0.963,0.963h5.294 + c0.531,0,0.963-0.432,0.963-0.963v-7.371c0-0.53-0.432-0.962-0.963-0.962H21.884z"/> + <linearGradient id="XMLID_14_" gradientUnits="userSpaceOnUse" x1="14.5835" y1="20.999" x2="94.4877" y2="100.9032"> + <stop offset="0" style="stop-color:#A4C0E4"/> + <stop offset="1" style="stop-color:#0057AE"/> + </linearGradient> + <path fill="url(#XMLID_14_)" d="M94.083,6H21.884c-1.063,0-1.925,0.862-1.925,1.925v24.544c0,0.512,0.203,1.001,0.565,1.363 + c0.362,0.361,0.853,0.563,1.364,0.562l1.921-0.004v24.067l-1.927,0.003c-1.062,0.002-1.923,0.863-1.923,1.925v59.688 + c0,1.063,0.862,1.926,1.925,1.926h34.47c0.584,0,1.29-0.486,1.655-0.943l0.027-0.034l12.943,0.015 + c0.366,0.456,1.046,0.963,1.63,0.963h33.507c1.062,0,1.926-0.862,1.926-1.926V49.32c0-1.063-0.863-1.925-1.926-1.925h-0.963V41.67 + l0.999-0.018c1.05-0.019,1.89-0.875,1.89-1.925V20.44L94.083,6z"/> + <linearGradient id="XMLID_15_" gradientUnits="userSpaceOnUse" x1="14.5835" y1="20.999" x2="94.4877" y2="100.9032"> + <stop offset="0" style="stop-color:#A4C0E4"/> + <stop offset="1" style="stop-color:#6193CF"/> + </linearGradient> + <path fill="url(#XMLID_15_)" d="M94.083,6H21.884c-1.063,0-1.925,0.862-1.925,1.925v24.544c0,0.512,0.203,1.001,0.565,1.363 + c0.362,0.361,0.853,0.563,1.364,0.562l1.921-0.004v24.067l-1.927,0.003c-1.062,0.002-1.923,0.863-1.923,1.925v59.688 + c0,1.063,0.862,1.926,1.925,1.926h34.47c0.584,0,1.29-0.486,1.655-0.943l0.027-0.034l12.943,0.015 + c0.366,0.456,1.046,0.963,1.63,0.963h33.507c1.062,0,1.926-0.862,1.926-1.926V49.32c0-1.063-0.863-1.925-1.926-1.925h-0.963V41.67 + l0.999-0.018c1.05-0.019,1.89-0.875,1.89-1.925V20.44L94.083,6z"/> + <linearGradient id="XMLID_16_" gradientUnits="userSpaceOnUse" x1="14.582" y1="21.002" x2="94.4862" y2="100.9061"> + <stop offset="0" style="stop-color:#2C72C7"/> + <stop offset="1" style="stop-color:#0057AE"/> + </linearGradient> + <path fill="url(#XMLID_16_)" d="M21.884,7c-0.51,0-0.925,0.415-0.925,0.925v24.544c0,0.248,0.096,0.48,0.271,0.655 + c0.175,0.174,0.408,0.271,0.656,0.27l2.923-0.006v26.068l-2.926,0.004c-0.51,0.001-0.925,0.416-0.925,0.925v59.688 + c0,0.511,0.415,0.926,0.925,0.926h34.47c0.165,0,0.615-0.244,0.875-0.568l0.301-0.376l0.508-0.033l13.422,0.016l0.3,0.373 + c0.274,0.342,0.698,0.589,0.851,0.589h33.507c0.511,0,0.926-0.415,0.926-0.926V49.32c0-0.51-0.415-0.925-0.926-0.925h-1.963 + v-7.707l1.98-0.036c0.501-0.009,0.908-0.424,0.908-0.925c0,0,0-18.107,0-18.882C106.514,20.298,94.212,7.572,93.659,7 + C92.82,7,21.884,7,21.884,7z"/> + <linearGradient id="XMLID_17_" gradientUnits="userSpaceOnUse" x1="70.9512" y1="111.9561" x2="58.4364" y2="23.39"> + <stop offset="0" style="stop-color:#0057AE"/> + <stop offset="1" style="stop-color:#001C56"/> + </linearGradient> + <path fill="url(#XMLID_17_)" d="M102.747,108.042c0,3.189-2.587,5.775-5.776,5.775H31.992c-3.189,0-5.776-2.586-5.776-5.775V24.29 + c0-3.189,2.586-5.776,5.776-5.776h64.979c3.189,0,5.776,2.586,5.776,5.776V108.042z"/> + <path fill="#0057AE" d="M31.992,19.514c-2.633,0-4.776,2.143-4.776,4.776v83.752c0,2.633,2.143,4.775,4.776,4.775h64.979 + c2.634,0,4.776-2.143,4.776-4.775V24.29c0-2.633-2.143-4.776-4.776-4.776H31.992z"/> + <linearGradient id="XMLID_18_" gradientUnits="userSpaceOnUse" x1="103.7051" y1="26.9414" x2="25.2571" y2="105.3894"> + <stop offset="0" style="stop-color:#DDDDDD"/> + <stop offset="1" style="stop-color:#BBBBBB"/> + </linearGradient> + <path fill="url(#XMLID_18_)" d="M31.992,21.402c-1.592,0-2.888,1.296-2.888,2.888v83.752c0,1.593,1.296,2.888,2.888,2.888h64.979 + c1.593,0,2.889-1.295,2.889-2.888V24.29c0-1.592-1.296-2.888-2.889-2.888H31.992z"/> + <linearGradient id="XMLID_19_" gradientUnits="userSpaceOnUse" x1="81.2979" y1="79.79" x2="40.4776" y2="120.6103"> + <stop offset="0" style="stop-color:#779BC7"/> + <stop offset="1" style="stop-color:#91ADCF"/> + </linearGradient> + <path fill="url(#XMLID_19_)" d="M99.859,108.042v-9.69c-19.253,5.841-34.655-16.098-41.876-19.467 + c-8.569-3.998-18.985-3.672-28.879,5.092v24.065c0,1.593,1.296,2.888,2.888,2.888h64.979 + C98.563,110.93,99.859,109.635,99.859,108.042z"/> + <linearGradient id="XMLID_20_" gradientUnits="userSpaceOnUse" x1="64.2349" y1="121.3604" x2="64.2349" y2="116.0661"> + <stop offset="0" style="stop-color:#6193CF"/> + <stop offset="1" style="stop-color:#00316E"/> + </linearGradient> + <path fill="url(#XMLID_20_)" d="M92.71,117.511c0,0.931-0.753,1.684-1.684,1.684H37.444c-0.93,0-1.685-0.753-1.685-1.684l0,0 + c0-0.932,0.755-1.686,1.685-1.686h53.582C91.957,115.825,92.71,116.579,92.71,117.511L92.71,117.511z"/> + <g> + <path fill="#FFFFFF" d="M43.835,97.712c-0.453,1.075-1.316,1.944-2.589,2.603c-1.273,0.659-2.719,0.988-4.336,0.988 + c-1.658,0-2.977-0.375-3.956-1.126l2.126-2.012c0.54,0.589,1.262,0.881,2.168,0.881c0.494,0,0.96-0.108,1.399-0.328 + c0.439-0.22,0.731-0.504,0.877-0.85c0.137-0.323,0.113-0.666-0.068-1.025c-0.13-0.231-0.462-0.657-0.998-1.282 + c-0.338-0.37-0.763-0.862-1.278-1.476c-0.415-0.658-0.459-1.377-0.133-2.15c0.403-0.96,1.182-1.73,2.333-2.308 + c1.151-0.579,2.468-0.868,3.95-0.868c1.294,0,2.416,0.271,3.362,0.813l-1.919,1.903c-0.605-0.307-1.173-0.461-1.706-0.461 + c-0.879,0-1.426,0.256-1.641,0.763c-0.082,0.198-0.076,0.396,0.022,0.591c0.096,0.197,0.358,0.521,0.782,0.972 + c0.497,0.532,0.954,1.111,1.372,1.735C44.152,95.896,44.229,96.775,43.835,97.712z"/> + <path fill="#FFFFFF" d="M60.945,94.719c-0.977,2.321-2.727,4.064-5.246,5.23c-1.656,0.764-3.652,1.143-5.988,1.143h-4.667 + l5.102-12.123h4.427c1.508,0,2.569,0.053,3.178,0.156c1.633,0.278,2.729,0.91,3.289,1.897 + C61.597,92.009,61.567,93.241,60.945,94.719z M56.497,94.79c0.605-1.438,0.52-2.446-0.257-3.022 + c-0.428-0.32-1.152-0.481-2.17-0.481h-0.724l-3.153,7.49h0.644c1.274,0,2.325-0.265,3.15-0.794 + C55.055,97.292,55.892,96.229,56.497,94.79z"/> + </g> + <linearGradient id="XMLID_21_" gradientUnits="userSpaceOnUse" x1="29.1035" y1="30.3066" x2="99.8594" y2="30.3066"> + <stop offset="0" style="stop-color:#EEEEEE"/> + <stop offset="1" style="stop-color:#FFFFFF"/> + </linearGradient> + <path fill="url(#XMLID_21_)" d="M99.859,39.212V24.29c0-1.592-1.296-2.888-2.889-2.888H31.992c-1.592,0-2.888,1.296-2.888,2.888 + v14.922H99.859z"/> + <g> + <path fill="#6193CF" d="M39.646,33.284c0,4.384-1.508,6.065-3.379,6.065c-1.941,0-3.24-2.062-3.24-5.996 + c0-3.864,1.386-5.96,3.431-5.96C38.45,27.393,39.646,29.559,39.646,33.284z M34.413,33.371c0,2.409,0.468,4.8,1.94,4.8 + c1.508,0,1.906-2.547,1.906-4.834c0-2.184-0.398-4.765-1.923-4.765C34.881,28.571,34.413,30.997,34.413,33.371z"/> + <path fill="#6193CF" d="M45.156,39.21l-1.057-2.807c-0.243-0.641-0.451-1.248-0.71-2.044h-0.052 + c-0.26,0.779-0.485,1.455-0.71,2.079l-1.005,2.772h-1.369l2.409-5.961l-2.322-5.718h1.386l1.04,2.703 + c0.226,0.537,0.416,1.091,0.693,1.854h0.035c0.26-0.814,0.433-1.334,0.624-1.906l0.953-2.651h1.369l-2.288,5.683l2.409,5.996 + H45.156z"/> + <path fill="#6193CF" d="M49.748,39.21v-4.938l-2.564-6.74h1.403l1.04,2.928c0.294,0.814,0.606,1.733,0.866,2.634h0.035 + c0.243-0.901,0.537-1.785,0.849-2.686l0.988-2.876h1.403l-2.686,6.688v4.99H49.748z"/> + <path fill="#6193CF" d="M60.145,38.916c-0.502,0.208-1.334,0.398-2.079,0.398c-1.022,0-1.976-0.277-2.755-1.144 + c-0.849-0.901-1.421-2.513-1.403-4.644c0.017-4.54,2.339-6.099,4.401-6.099c0.728,0,1.3,0.139,1.664,0.329L59.677,28.9 + c-0.312-0.156-0.728-0.277-1.352-0.277c-1.456,0-3.032,1.161-3.032,4.783c0,3.604,1.369,4.765,2.772,4.765 + c0.45,0,0.71-0.087,0.814-0.139V34.22h-1.507V33.11h2.772V38.916z"/> + <path fill="#6193CF" d="M66.209,33.665h-2.928v4.384h3.327v1.161h-4.661V27.531h4.453v1.161h-3.119v3.847h2.928V33.665z"/> + <path fill="#6193CF" d="M68.081,39.21V27.531h1.265l2.148,5.476c0.485,1.248,1.092,2.807,1.49,4.072h0.035 + c-0.104-1.837-0.156-3.344-0.156-5.372v-4.176h1.195V39.21h-1.265l-2.218-5.614c-0.468-1.178-0.971-2.513-1.387-3.968h-0.034 + c0.104,1.559,0.139,3.049,0.139,5.544v4.038H68.081z"/> + </g> + <g> + <path fill="#FFFFFF" d="M36.71,50.24h0.878v3.154h1.548v0.739H36.71V50.24z"/> + <path fill="#FFFFFF" d="M40.875,54.196c-0.826,0-1.461-0.543-1.461-1.456s0.601-1.496,1.514-1.496 + c0.861,0,1.438,0.595,1.438,1.449c0,1.029-0.734,1.502-1.484,1.502H40.875z M40.898,53.567c0.347,0,0.56-0.341,0.56-0.849 + c0-0.416-0.162-0.844-0.56-0.844c-0.416,0-0.578,0.428-0.578,0.85c0,0.479,0.202,0.843,0.572,0.843H40.898z"/> + <path fill="#FFFFFF" d="M45.028,54.058c-0.156,0.075-0.45,0.133-0.786,0.133c-0.912,0-1.496-0.561-1.496-1.444 + c0-0.82,0.566-1.496,1.617-1.496c0.231,0,0.485,0.041,0.67,0.11l-0.138,0.652c-0.104-0.046-0.26-0.086-0.491-0.086 + c-0.462,0-0.762,0.329-0.757,0.785c0,0.52,0.347,0.792,0.774,0.792c0.208,0,0.37-0.035,0.502-0.093L45.028,54.058z"/> + <path fill="#FFFFFF" d="M46.391,52.498h0.012c0.063-0.121,0.133-0.236,0.202-0.341l0.572-0.849h1.056l-1.01,1.144l1.155,1.681 + h-1.08l-0.688-1.161l-0.22,0.277v0.884h-0.877v-4.107h0.877V52.498z"/> + </g> + <polygon fill="#FFFFFF" points="32.473,50.764 35.361,50.764 33.917,53.651 "/> + <linearGradient id="XMLID_22_" gradientUnits="userSpaceOnUse" x1="95.4434" y1="35.626" x2="89.8121" y2="29.9947"> + <stop offset="0" style="stop-color:#E20800"/> + <stop offset="1" style="stop-color:#E85752"/> + </linearGradient> + <polygon fill="url(#XMLID_22_)" points="90.221,36.035 92.628,27.178 95.034,36.035 "/> + </g> +</switch> +<i:pgf id="adobe_illustrator_pgf"> + <![CDATA[ eJzsvemOJMmRJvgE8g6xGDTAwi4Ddh9EYwC7vIc7vEB29/RiMCgkq4LFnM7KJDKzurf7ZfZF5t+8 2KrKpaJqau4e7lHsKjJcqyLjcDc3N1MVFfnkk0/+5v/4ze9+On394fdPP60fiwf4m79ZPj69+fzh 488e8LcPP3/37rtPnz/6X/3kt188lNVj4Z40/Xz4kp/4j08fP7398P5n+Cf848m/+ifrm395+/XD @@ -264,9 +264,9 @@ Rmj3hKhu5dZTywaPzN2Kps4bOm/mejZzZOTExFFQTSH1Bu7NyLB5s+aN2swobcUILYGzCydDa06E jnil/HUKV8lfoxkwA3pyV8dfG5/9nBBT92lPn/DEK/G8pF9w/Mj1884fuX/iAKILCOgDihdIfqD/ n7xB8getM0teofiF5BmSU9tjLm0ETKzNCIuJl0h+YoD6XzB/mUYT2SsRB74UDjc82t0V0msExk8+ 8pQ3/CjHkPdtiDccQ963Id5wDHkniPfzUgSXMwSQ2c7uulpwTYKAdsskiEcUt0Xk1iO2Be+kC++i -tIe2vH+WvHealC/cn/ONryFccxHjJK7zDUufbPX4l4QX/t+mp4zs6OIYJNtSVLHP5Q== - - +tIe2vH+WvHealC/cn/ONryFccxHjJK7zDUufbPX4l4QX/t+mp4zs6OIYJNtSVLHP5Q== + + 3noA3OBu2R3v3Fzv3Ora3E7XRhudDcaduZKQtuMspA9ntyiUzQWyfr6peZSgeR/vH0fNHDfTgWz8 nYcOVjpbPZw9IB6Sgy4Dde1gLl4fF1cHntMP7UDG6at1QjP8+uiumCel+9nVS0yVfrP3/e48Dq6Q ElEGs6aUJOHntWDC6TfpQrnrKHetlyx+0J0LFuNQ0XpQuUAxJCc0NQEHQWIIESVAbI03uqJvVagv @@ -338,9 +338,9 @@ YOznIHa4BWM/B7HDrZocR1QqiERBUz2OjCxoWzxUrVUCpV8ga0BT+7UIsoxcAGuEXFP+AeX7qyGw Bu47DJ5JPfqXBnYhCtoKy68masZjSbwMemVfmUKpW17t3reky9G3Rj+Kf/EsLsPTN0/vf//BffFM hvCDO1inLc/Kw1HkxnpKxmaGe8AqjyVSnky1J00nCRWfzDaSgIudJJYdzTZfyiHFHJZnmzQZSflx Mb1WyLVxqxFnpyX6GJRMm/I+grancGZ75RTY5iIYjMCO9dfcUz7UdXBJAI6yyg332bh+dIej9zam -T8aQjDEaUzLmZCywxI81M7bdOKUj5H/AJIPKzKjOjno/IPfLZ43kTcCcTUhbhQ+zmQ== - - +T8aQjDEaUzLmZCywxI81M7bdOKUj5H/AJIPKzKjOjno/IPfLZ43kTcCcTUhbhQ+zmQ== + + dRDWQuirot1VZG1A1GNFhrlJWkTxum2/btvfI+f5eY8L7RJepufCD/uASfMQSH9x77h4QFu6gUx1 GbUZjRktjxBZp4WBCzsDfq2oKnlcGmj53lIgKCOwvyn+nmzBIGjFINcLnqWDtxpYhTLBEKBjvTDs yrVtgJ4v196iLSfeV+q4dDsu3pbybSnhDmXctpg7lHTjgGgvDA/ro0XeW9bHMz7gOfeQnvAfaR4q @@ -412,9 +412,9 @@ fOz7tjaHjX+Pzx09L7PrHr3/9NCNj34zCK/I/pVKqCs6WNs99k3ZmYLp5A/EJOW3btpHtzOZZ6d/ oE/LH79uH8fWklfj3+NzGzxA/+gcmfGhSj9x9q/ULoWPVdWPRV33pgFK8gcq7/aE0LqyPNHwq+dw QP/h/fs33z59/fAN/+oL2P/KH1eIoCpC1o3HWuBbBI4eSYEjRAoWI2X2v+glB8Fvq5gcayYH1eQh r5kcqyUHjeRa6wWkUDc0t4iaWYApB45VwbekFcW+50TwFJowIFp9RzXQsWp4Tj1cVcQhEhJP5MSj -ke22kYyo/8vzHof6IXCVzMiuEv14wPpDaWrwZzlghX60L2safB97Jk1h/ShppnfqGw== - - +ke22kYyo/8vzHof6IXCVzMiuEv14wPpDaWrwZzlghX60L2safB97Jk1h/ShppnfqGw== + + L4gjiU9c+zJijE7EDWZmDtY7Yes2UO9X6p2HpN6ZKp7jOmeucsZojcqcqdDZBdJgGtXv651nVhpf teqZK5+59lnqn6kCuqK65Fob2Usz+1Zb2sdt7aWx/X4YfVtox4xbmPFQeFxsoQPtglXZfzUTMnPA ozYX9Y7nmUf/lZcGSkwLwmBNwkoblZNGDLqVWxnYWLDCSNDFgoBprR6pdH7MTFBbQr20xoLyaHU1 @@ -486,9 +486,9 @@ pSXilmCDUY+YVTViC+4eGBsXrJxViRhMg4y4JcYamzzKZEJk9Wpj9fZ2L251IuoRc2wCQYLJyAoG SxhsYd4axp1ynGd5ZBPD2l8ylnE1sHTSOweMgbQuaBj7jjlHNhLtJCS+ad5DXSKbaceWWlBQz3Xv rdaRvcw5pbF1xAfsfdHYQu6dUOeGlruxczz9eK6zuevP4gdEPw43jdEOiH+8f/xl00ty/E3mWsTa w/sCLelBE0q0hNMQt59hyWFT28m8BLHhjeobCd1JlLZLJTcF2sEk5ZzAjTVLpTJ1aL+o5xHZ7BNS -t2qspGiVtzRji6MVnc4SGxt5zhK2M+rREoujuWF9BfWaomC7Y0M7YVcpz1va0IqSBQ== - - +t2qspGiVtzRji6MVnc4SGxt5zhK2M+rREoujuWF9BfWaomC7Y0M7YVcpz1va0IqSBQ== + + bbHeomcLsQBSlzasLSnQ6pGl8/aNbAdNMW+myCqRHfIWh45BDzIXaCDIKJAPRQbALHf3sH4PLdN4 +dE7ymMDG7Pt3JA03hIbG2KUnYQ9cAaiFJFnN4JYk+2/pPuFySlOUd4RHyCIZio0Eo00L7pPpyry ajOz+eTtcXbpimT0bTmx7xmO//7K/o4L//alf2nxX9I1CAKGe9g4qNvV0u87B2k1PSSFkGlBfdyS @@ -560,9 +560,9 @@ MfPJ9EyveSeXEuakfNmAVw1osdCguNXCNUAnVeqptcNXkOOZY2Ckl8SEM7UuwOfWcZjA8OmCDuUA 3Dcl1f1jXD+Oj41b6gEeuecgRKopnGnx6EYrPesKLq33x5GXN8yf6agQX4r/a+fHGbbN3YcSLQP+ TCM/13z7WBODxx8bcY8EL7rt1XdBJdlMTB315DMbit1OZDOxdMSW66WkmyyJV9qestpVVpQsJ/Xv BuYs9kyGiH26ihkVpfHpNmRjLKB6l+LRDdp+VrQvG/XnSsNw3HjDWvgcGPyEnRCPxT8L9eUs6zHw -HgPzURV4YEd/jOV3OuU+lrrPbYb5OOpux7xHUNKjpHkt17HlTU9ZjhHHMWRyKY+L/g== - - +HgPzURV4YEd/jOV3OuU+lrrPbYb5OOpux7xHUNKjpHkt17HlTU9ZjhHHMWRyKY+L/g== + + ChhuoyAxNmtrs7VRnpZztGuangXOz3YMvobMbBllZpOsrCEnxpTECiTNZ6iHiSif5vP2CnxtzB70 2Tw4z1fDLYf1Yxo/550Dtaq72pKzyq5qmL526lrWLftOoMKsgXrbcegRJml5EZ9XhB7MFA2yrXaS inhrLN/aWa0oKxUFh2pRIWzvIqWokq+20HUTwi6wUyN8BVWI4pqsoA81qdcmflujtAQzhcGwdAf2 @@ -634,9 +634,9 @@ X04SKaV2SGqk1cndc0rUXUbYzfBg7IyhM7sgTelpp77Q4/RdAPtLlZwLCN2DS8z52aq3WqveFqp6 w01tQDh/QyDfw/iT11/23eyo1m1yE+GENW4dtofyUL0H6nu8rxtC9C12Ol3Q/ofmdbMnjjqLXYNb E1RZtmzbibrWtQjGT0gOfS0tei0tMqVFr1PhdSq8ToXXqZAtONyH2Emrnf3frhRwTIPqq19xVxjd 56Lo3gfR2tE4okstCd0h5jYm2ac8sQPK/KPKjjozAtmq4Tw6Oilj5KRU6mnv+2CKez0yX0Eca422 -gElKof6GiuRijkIao0v9TSLzqm3SfX8l/w32nfICSTf02DtnI2BnJK7psre3E2gpwg== - - +gElKof6GiuRijkIao0v9TSLzqm3SfX8l/w32nfICSTf02DtnI2BnJK7psre3E2gpwg== + + nPcAjwd07vGXkdFD7XDTciRbjOTJE2cKkSYp6boyy3qQbSXLLpitvDyU/pjin6j8xxQA4SEumtPz vQijzmeFB8+4toF6q0ct3alVmTMGVHpSPTTDY+ViP6v3evshGAXUVvKNqRHZvb7jSo7hcXC/sijg Ta+P3vux8M3c26iAxB3C/9l/w33vHxt6eg6JvOs4d5nSIYtIDhlE8gUff/kH3PGQ07qHc+zAhG+c @@ -708,9 +708,9 @@ VgYQz+XmND8HBiPPpeiqqIK+S2ro7Q7MmTrIpeuSlB0VPNYmyuo0yuoR7KDK4YF6108Ydo0q+yPF xAtiJCcP8GI+R8qJQ0lxxWXFHJRRPSwg1OIBlwERYQnRRkZjZg7XFg7YPFJz4qCtxPKNioM1/P8H nTEIbl7Ug+Go4i5U20ml3apqeGUZid9ATv0mSXlRXLZw7lPSXLSabYLc22e3BXac2Fq0UUGtugUh MqP+cCE2I++ApIIob+AzB6vF6QSpE6wuoHWM1yliJ5hdQO0Et0PkDlQ9LWh5jVrJ38WlvyqZthgc -T5A8xvIgVUwzdf0C6oXQUIJDCQ/3ejANJJIwIVKUWHGnCrOr9A9BY+epAw1m81KdHA== - - +T5A8xvIgVUwzdf0C6oXQUIJDCQ/3ejANJJIwIVKUWHGnCrOr9A9BY+epAw1m81KdHA== + + cSFTrZy9PkykEPMKn/4g4VMKDE54VhumdBcVAJK7POA+2KkSEN1tf76VqHbxXSdFL1ZKIueCbv/A ImodfhjSCKtVLqhEH/GkkabEmrPEm8AhZ68hZxp0luxinjTyTGPPKPoEDT8lAGUoQsEIgSMW9PEn CUYZlmBgAoMbxCYA0/kITyhAIRDFglGPABUCVQhY0WJcQIAFQxZVEfnJt1t/m/5Vkw9JnfXIX0Od @@ -782,9 +782,9 @@ puvfzk312Nr5w8fWie+izV+N7Aftrbs1MzR97D93rXVPrLtAzRXZCf7oW3BvilFbBb/V5HKCHlQK +lvIc6LdhbBHkl/3Qt8k8/aZ99a68dZ9+dXebXNKUecmn3P73ll1TVxSE+0ldhsascO9uvM3fJ8t 1bWOA224M77/I4sXU3cSOzyiuTR7e+ugFtikjmvVP+3KyGEhlPnr69DuI3+cHQwK7Z6YZMWnmk6i d1+rImXlrLL1y3RTjD08U9NKcRNBztQ6k/JA5DP1C90snHhi8q2Gg9PBrWayT4fujc6IJgsIapUm -jL7mySwl9dwzJtxEU/048a1Sqv3Lv3p+RCg+7fxgv8fxoundH/a+NmocSExhSRkkTg== - - +jL7mySwl9dwzJtxEU/048a1Sqv3Lv3p+RCg+7fxgv8fxoundH/a+NmocSExhSRkkTg== + + RRw6zXkAqKOBkcMjq1258Z1b33cdDMyAC2ZbaHhCDixxD9Oaae0zhKE903ZDDBja0+64S79ZOj4I UJthe6TRNc8OBKBRYD3afyfIf15L6A2sSt8FFiUBa5q8+d3NGZyPRrOk/J1N7dogIwIrOF+xrZG1 3VnfnaCbSrtFrvYOwbIn0gEm3/45gp5IUHifP9OmX4/Gmr7YgCsLmlnU00Ktizmsc3jYMM5hqqtg @@ -856,9 +856,9 @@ ja0sbGflTOtBZjno3BXyM5jKblZYLCUPbGaGfSDdlbhX2l+2xso5HjjLA/dhiW+P1KvwPe57j9R7 YrDf1u/OHm/y2a+YyeVy3FO5fAeM2RPOLzy5xPlFzy7Z5yh7Y+M9J8nYeE9K2u7REa4o9nTAfY6I Ga5XXbNnHJq62hMSTeiMsQeumHk+nutt+6Xk7bOSN+TIuZZkt2A1tyy5cxrYa5rduGKlp5+5uuH5 Z75zxxwQ53OeIeN8zlNkHlf5RgkDkUzADxOfIRkA6/idIwdS9aDTVStPtLvm+rZmN2b5bVNajfND -u+X80BNrHlG9IT8syoTQMLV50sOY+r7+yxl/y4bputKyqaZN97An436lvhij6rkvxg== - - +u+X80BNrHlG9IT8syoTQMLV50sOY+r7+yxl/y4bputKyqaZN97An436lvhij6rkvxg== + + qKaIElOlekjJcM2Ykod9/NvA7sfEIWf3njjk7N4Th56sOk+ujtUV8uQusWcwtPEz1ZXZ8pSx85p6 d+H+OZxWO6tcWenzRqTC4dlqrnAc11nhmM8Kg5fPdUe75aql+/lM4o1uLpN4nkDlEq9nUM2E9JZq t078czgvdi61crHnPUmdyLPqXCc6Lp3omHWiIclyQfYG/MPivFa76RqYHwGGYd9m9TzzmWPNDG1g @@ -930,9 +930,9 @@ VnEmvZkyH0Nyn8yNqzlysSJka0znilm2xnSumH1lkJ1NtotB92GVJ0JYCeWJmKzblcsH5mrX2OXD 7jAoU+7wz0ulyOekb5R9Vkeetu9bKu86bnN1zOx64uVPjH6UAquIuImROKt5OU9a4ILMANmK5gPi vw0z8k32OQjqgatPTH9idgsnvDHKJ2a6rNiyoPc5mQLpc3IF8olBfF/l/QKR+cvDoObRLsuzrt6z ojCzsJXFfTnL76dCPYRCWw6RN4f7sIyutH1cCW/jbeu3rZ/f7elLhPQcPj1GVs9B12tE9mPc8D3+ -Yg3j+ejxPYNjo0+FMUCWCaU7UYlQlu/2RfTC93O37gOfvzuNqQ/354T8vFAPsSVL8A== - - +Yg3j+ejxPYNjo0+FMUCWCaU7UYlQlu/2RfTC93O37gOfvzuNqQ/354T8vFAPsSVL8A== + + yRKa8jy171NUH628NQPSg49xcT6uXhVlDToayVrhPaDx1nrc3aOL32fxCt3JfN4G913DH80TmSf5 7OP8RqCMq/M13E4+1YpV+MmnWrGKsZK5l0hw93i1Kr3uHq9WpTfZP61+pKcwVKsW6ykM1arFeuR9 HQqSesZQ7/uT1bEsF/tnZztZrcfKlTFUer5XGfK9vBmIbsXYH4txfJ+u+CHPGOr9fSyyfhynp0L4 @@ -1004,9 +1004,9 @@ Mw6tQvVft3/+n+3m//0RP/6Hj//tf98+/h3v/9v/GXKjv4uvligZvvXLcENf061lCMvN/uif+KX/ URvB2YDnPnkkOvaBO1OryxLl83Ab/M5j/K3LuO5A7DbQPi4fc+6epy7s5MRTmFrbSRDx7d4PJNBS 4atNAeQ9C5M7GkPENZpJI1S02DN2LU5kz9i9Rm/TbyL8Gryu/M6v2qJHLrBDnD9KUeNs6sGoPAnn BepEoMI3qk3jDxSI7R64RL/J7P+2ZdOOztWR27xBFliEkW9S949pmgOrN5Uge97M6YEguwGZnQv2 -9AP9xfGz9uFBuqjFtzcFJRNAhl0iXTmjUCO62Z9kDwfG6deGIKMs/B7K0SD5qF/HHw== - - +9AP9xfGz9uFBuqjFtzcFJRNAhl0iXTmjUCO62Z9kDwfG6deGIKMs/B7K0SD5qF/HHw== + + EV2Sd9h7Y3Y5UfA3fCjkk1wqoiAuhlNUXGk72MpvhBBhI43BzxBG5feA3DbwvfZfhrTzVVid21QH EJ3Gkhu6u87QNasrisZ9orsc4x4uGVOwFTvO5DhGfXFXSkvDMbaF7lQEHDdQzEhVuzKE/V5TDRqR ndd19NrB5w+uvQEZjiCSL5BvCXb4A0toywD+v6MU9IRktHWdkExaCyAZjqaygvi4siiyDq57m+yA @@ -1078,9 +1078,9 @@ zamUw8j+xNHQT9qcbdrMnhpUCELSycpLccWib6S2xRCodm6qLURqhVYIRnccIvLcBZRxOx7jsW0h G8FkcVTA9oEpcNso5fkWPARumaSaMC0xIcWG9Z1I/T6+auWtfMkY21OV2oC5pCrLGn8k1q9zGOH1 JQu0txV1hRH4hQzRLKRNrh9qFkSfT19pOBBQJHx3/WbEdViyb5t08XK1dzplSPRFi6d5DAKcT2e1 OGZwTIzBVk0xVHzHLo6WTfNo8ytYxmAeQJ4VbM/QzA3ltyAW6AziUlDKmZwb1G0X95NhSTUgkeOe -CIsgPcuet+859PFVU+z7qoF/oVAPHTCYDazm/ivx/5i1Qp3TsW4fVSJWSCL+8Be1ZQ== - - +CIsgPcuet+859PFVU+z7qoF/oVAPHTCYDazm/ivx/5i1Qp3TsW4fVSJWSCL+8Be1ZQ== + + y74gYgxRLrS+2vBX4PjFSKYV2WHZvm1YxiCZtHcq9qGv2kE2Z8eMhopZc5PidGzVTuHf+J3lxNZ0 ihlWlam2Ih5J8SS2axiswzPdroY4uxaNPrRTDjJoZ8UMflhHhImB+3KsWQBhDSHWfXR1cDrRDYTq a9R8OEoMt20e/xVZP+v9VWX2+ZrtSJSmSclsiuoU0TgDQzO2ou5R0DuOcl5LjaALpI9u9qsR1mvJ @@ -1152,9 +1152,9 @@ RUDQDnDIQt+f8D4Du6UBJ7+OPVt3j37PwqF2b42gGnrJLq37Al7bjQi7CjbslhQG9guJsV3eZgC/ sxTR0F5Z2JpKdVStLAQjOXtadnIlfbPMjKhajTLFWTDPbp5K2i0YUuJOShzjWQKijcOaLeS+BjKA QzDyZKh9sMvysUk7OE/ve3ha8T5bgYOhs2op0OZlQdiwtCxIvRk+EpRAgiCq0jcA9VUkV6CaR1GE NkP4YXWQdosoyL2nmak+NiKS1WpCCWBIlGHV4EP1DFXPxDNm0H8DbnMsA2x3KhQuN3ItvggN+mLu -bC6RYo92Mz0ntZ3gEdDL9cKSYV5oyknFhVL/hA62mXZaqq9Cm6B7djaLCcyKOIWNvA== - - +bC6RYo92Mz0ntZ3gEdDL9cKSYV5oyknFhVL/hA62mXZaqq9Cm6B7djaLCcyKOIWNvA== + + cFXoKl2wejFWJYiLIlLNiz1bryaGHqJr1Y+TdK7MZQTVM+7bSqWcKlSJKK5d3VsZGozwJijEcK6W Kts9XVu/iscQaCyAVJpDtaZkfM46RoKh6Uhvxbh26wytAxCMHGPvDF8DVTHHaYeRAJbqifAEnJU2 HY7c7Ms1oAPL1qCqXOTG8I825crMDLYgWpB6MyjG6pqeQ63eaLiCsKHx9E6+CRGH1XIMh5LB4AUb @@ -1226,9 +1226,9 @@ Ts6AlFFEWgNdSOd0SLAxjzJyRegLM3TpP8xBwRHIYUe5AbRgZHrXAsGLhk12SURCy64OXIYuNcly aHWBLgLTgDaMWsmizEq4mkmmTfAx2bExznjIbsfOmoFbHfSZTSEwvZC0FCXd+hOb3Hh0U5wEtycK RLEG5KqyMztMponlGqjYI7kdFjvkOHtjl4ZpJN3S/O0dBtEAOm7WJHKY/pvmTTQOtnenZLEhaC6P vQWeiZVMgRp3R3pX4VSkF/lwWJxCqTe0gEQ7Y+cqu7Fbz5ADmO1QDOOaTZfaeX9mU2HpmOQ7SVUu -bsOWwW2NMNlCNFlATVKsB1Li2WK6qkTcr5IiPJDlIMma7TiULRpiReA9cyd7fuvN1A== - - +bsOWwW2NMNlCNFlATVKsB1Li2WK6qkTcr5IiPJDlIMma7TiULRpiReA9cyd7fuvN1A== + + lw1bulbAP6HNA1scjsAFcPwGuNitxQzjBi5i/oq16wO7hAhnq93GT+KhIzWw9c0ad9V0QCdGnK/6 M5tMvI290keFbrbBvBCx6KTD9uVZ2GK6yLtHLiWLUgRLtDV/Bxqc4siXrcwM/otn0HA0qVX1BMGb 9s+EugAwMVjWjMGbYAYnbbZ5At4gOOk4x2Y8RKfZW/GmTfkZZVd73pgMT6hIQJdsGg3Ho1XMBjWz @@ -1300,9 +1300,9 @@ VMBg5ajd3LjPr/m61DTVx7DzZoU2IXLCDEFNlhB+tyDTPLCgNUybp2GrNTSNmtlYlwxF9TumSE32 SkFVcQCXIO2mCSlxid+yBI70uiO1fJlxPa/n8cuRgwPHAYKBOkwNv+gUoypWrU10f89XZpZJYk7e p6wUYhiR8tDlEFV2huV40FL1uXgWHlZCWprk38uabkN70FKAK+lN6hG8z+myLhvK4majgw1J153Z B3TpaSrd8mBDEzOFEdlxUzvh95wIaI7FQdKttf7wpq9MD5MWPqmfjji/IztT3e1PGm9IYeAZSwlC -t372RBb/ZMeumBBqXDKkSG6Rbs5SCSfYHmf9mDc7krC+6O1oR0TvOLzWzcHJzuo+GA== - - +t372RBb/ZMeumBBqXDKkSG6Rbs5SCSfYHmf9mDc7krC+6O1oR0TvOLzWzcHJzuo+GA== + + sgkbE2I13DVAzjCS1CGIN2SPoqUKHl72lUleih4gy4C5h4pDWFKLNiSywfTLFs8iSKvcLlmSRA7f 7Fgy4oPykWQewbVOPseb6Cq1e3WghimJFMCBFSrBknyuEoU4pqwivHkwpfMsR/AIRKzoU+TuiBnB I6coxP/pbV+Tr6V6R1Y3KxHARwoI5Lzg7iGBNg5dhAYw4p6Sc5WZ80Xtj8lHBYxt8W1s6JtukfQc @@ -1374,9 +1374,9 @@ drsNySfrUc2iBktNCB4QuuXbDKROkgE8jSoViEOID/fnGJGq/Un3VOvrWc+pgISjsCeASDfvRrMK pC00clfbNybfXEKdoWXsYiJmzwCcCPlCUNtDxjyRHRHJayzu+6gsVXfuw7JESZOEGGnIo+BdtNjA R8DfVgHzm1YW2SqnyiPoNaaarEgInqx3G5ZPl4/QxgxllMWWDI6LaSxcQ2lW7kB8kSwxVtmkp88e l7bzdY06bSmr62Kwao9ceZZvG7sRqWFZizP6j7SfCrtZ+sdCeZ+3VkubdrWUrgU4dvO1BFM00dB9 -WAaTNPdRcZyWFIKgxVUi6RQowjBmAjSOkUERnBHdwYBQxGAsbe72B8PdhuTTlR5IBQ== - - +WAaTNPdRcZyWFIKgxVUi6RQowjBmAjSOkUERnBHdwYBQxGAsbe72B8PdhuTTlR5IBQ== + + g3B7iViXY1IU9S5LRG1h4pjpAeRhSffWH2NIOsHNvuVWeiZeaqsHPJuqN/YirciJNsIQ7hzaYgDV S0yFXr7BVI5A/NVsTNH+xVYZMGn08jAkXYRz9zFxKJbEO9V8fmU1F4CCGCEUuHKsULBUjpvsLW8W nVhi536y3CtLLeDFYx1UTqYHpajOU71hSeM7CwYHXkIq1vpzjAqCpnNPI90896ZKCDhrlPuXgLlS @@ -1448,9 +1448,9 @@ oTAcWfRn1xEzzq+ogOi9jWzHjU49WzB+1T0E+IA1tjOO0AoCErFw1XF4hpIfHjF+A4cXmgmqIYDN zu2zWW9D9unEN06qKfHdIBXjk05tiqjAVIuAAU1PeF/xmkdT9DiIFkbBFu5i7blx65S2xmBmH8dU JPvp+SOTmJTpAfUQBhlocHagV+HAUWcP8SvsnfDtUMGDoCJMXaSfLfKx7kTKvjWL6KcD1FPcl1Wt xegRY181CuhVq4z1VoAIAQml3EunX3KYIXEybmW2ua0HuoOwAnqXd7NeI/b5PDs7MQrPSDZOeshY -2aJYY+GuTzQLSxNcZNzpm+EfHjF2lzULPxEHLVeimLSFzUdMoXrA6DdgpVbtcEqULw== - - +2aJYY+GuTzQLSxNcZNzpm+EfHjF2lzULPxEHLVeimLSFzUdMoXrA6DdgpVbtcEqULw== + + uVg8pTYHjLS7HjAmDk6RvcuTxfGR3B/Fgp4FMDxgXQBhtq8WQxOqVZN/jWWIn2QzB4HC8g+JSq+W oxTcccdwsYiCXbBrfBhksDq2+5dno94G7BNZfYRXIMMjjj3nGCot7iJS8YB2AeqSl7PwlWNVgvYg 0M/N8xrZZ0xMikKmy0ZoHeuxvqAV0+jKsGIJtxsHD7Upt0j3PFwlmMTgvnMateOSUi8IVkNICHdn @@ -1522,9 +1522,9 @@ L9tIzmeLndsapehhBjnOUHiNzpWeotgjutSp7E8zz1xAnpSzLDce5qKSE5jU0EmShaQp5gJLureU yzjcbZUVUDVvWOlMXUN5KpZ9eJWXpLyKcQRL3YEyD5uQIUaFJL6TQJSRQ3pY5XwqEgfzh5IdJTiW JUAO+BICu6I8Bbs6on/H+pTezLMtjiohrbMU/do6Qzu3rCM1vXenAwynWfEYTo/MLfrhXV6RnzJr ALbcwPYVU7LCjmT5rGqAZ+Gwqdu/mCjDEShjD9CwNoaSCMWLuRdM7lzc9KckHJs9gNNqS2IBYlJT -nuhAx2weQC1tHAU/UwJ72bHPEsj88UUu24yIx2LlLPo/PKwQ0n+57dvJx5d9a6X0uw== - - +nuhAx2weQC1tHAU/UwJ72bHPEsj88UUu24yIx2LlLPo/PKwQ0n+57dvJx5d9a6X0uw== + + pCX3Vj2aMWtW8SGnqgMZCU94eRnOMtJuAKKNIRLBjIBkKTXeF8U3ioiiyOUGRRQkA+KY7e7p4UX2 nxVJPrx7lTrvupsTcrrE4tAlBVzjXipFkcoH8g9N9PPAkSzJelPEib80xAALmd8pFhz2QL3fg60b 5EvIOux+McN2J/62wXl9BaapyEysV3ZaZud9I6mEuE5C/NqdjMfqT1YPHMNYtU74Kr+0JdWYzP6N @@ -1596,9 +1596,9 @@ RKvfTU2p9pFmexQ5cXw2K4lWF0ip/dmloEAqfsv90mYXJT/r1K2p7lWDxzAI5Z8mwL2KyPo0tYfN 9UGRnfKW5RdxWkoksJ7brblVm/9dSqAjaBeZzq7rRky7DxmaAAPYz9xf+GiTsNTRk/YzW7Vp3kSl m1vfLWPDmmNTolrazt0FTeotN6koW1FmnjKXXnT9IoJMfeKLtn2IxI/IdVaBPkQ1oJFaLx1sVLP4 6/0MVnftBsUwTKbYs/FIhe6m/kA6R2SYfuq9ewjrjPOZb8hGC1s3DgaE4rzH4B/Utv0diYic8abk -zORS5WNU38DxjJ8s7XqN4aPHs7S7Xl8IBYH6o/9+ObKuup/nNqBDfL6sGdG336He3g== - - +zORS5WNU38DxjJ8s7XqN4aPHs7S7Xl8IBYH6o/9+ObKuup/nNqBDfL6sGdG336He3g== + + et5sPUJ+iH8+tlnys+r2OF/JbobKGb2KdkBj8Qfa9O8/zKUfnmPN1BJea4wwQ10dJCvXhLFhOcXy eXipYISx/cejQFjO07arxTaLQ1DW0hRoFo0ECOAMaHK9hRO1G7sCz75LSbt7MM7ErGfIrMk4xOOp L/jP3TylEISHp8SF0u8D9GSYe76NuHHmerbVknCQs+EjR2SIRCq9aJ6UyqTvcAPmL+Ok4LM8cLj4 @@ -1670,9 +1670,9 @@ SxilfnhQOTvVbqTLH56BynLBXEiqRw4sTBVZsjjVDb0VrrRKby7ybHgdZBojFYfPUSyKZB1MDrxJ tvdeqX4sZWOL+Ocow+cv//Uf/uLMamxXgyDJ77crVl2128u6MjC63BQ7emuyCdAQ5U+zlaF0B+Sj nEyKfltOaJh8j/UjlnHEpzxVZmWtSCW/6k5HNOwx/2JuWCCNXRbPIAmF1VGlrO7o/CrnaBQXtXcT QF90ilJ2SEpDAyQbsl+oJLGBAI3k6hRHczrFyN/H9led3uQYQL0jSSlQjfpDK4GbvEsVfth0DPir -TiYZ+E3+ASPsrrZCNDCwxcGff8gBYl9xXAMWn4FfAO9lrfj4TU43a7NxDRRM6HyP9g== - - +TiYZ+E3+ASPsrrZCNDCwxcGff8gBYl9xXAMWn4FfAO9lrfj4TU43a7NxDRRM6HyP9g== + + DjBZNeJJjrIDOo/2ikd7nAnBGpY4qbIIDLAloT/RAq+sWaHCnsi4djAxTIBvF+K38LgCMZIGE1gA VDoMaBjG1Ihw/F4yAogYXTOkemAP4y/WaSCZM7wbCNlGn/E3P2hVZV4Vc4tcUy4c1fBGhg3Oj1DE aELswMF0tz3bici9Poyaut79oAeFIq4GeFrqnRk8tqoP8s3zJKnmvBfxgmdiExtHl05oNR62ynjA @@ -1744,9 +1744,9 @@ YmVRwOBQpDp3FbLi2RoXpUkPNOKKVpoRPCYjFly52Hp9c+bXjqUlcX1bgtU6xrgGvBGg2b3PU1Uu PiyHqUS+yoakEgPCuApjRmEaOEc4U/7oDZjca8Z1YIsC5he4QfAiY3/aEsIm5uSrtzEqwxVhYoBy Xu/PAoeBn5GvWHI0EMK6Y60mwDSG7FhDI3jI5hhPYETiM8ezqO8/rrUhTGEz1SLGDX8LYzVMZg0H iuLcQxAgHOzA4nQzB3f3sXc1UH21/4CpRq65JaU6QDEQYVEG42l6fI3pMTQ9gKwBOINKy8UaRE9D -eE0P0g6Btrl9eShC10Cz5vgfSUDXMyVgWnjVtylRi6+xjeT9v11TgGAJdE0AYILhNg== - - +eE0P0g6Btrl9eShC10Cz5vgfSUDXMyVgWnjVtylRi6+xjeT9v11TgGAJdE0AYILhNg== + + GTovJV8qZOGE9h8GH718lDOZFIBg073bnQhueb8WkK2EidetPfb/OUHY8kDaK46fKCzZmoJxDDQi 2jqA5oGmiHVFO9v2ptbpmR/+7PnR/J3m+cFgHL8DrA2Ak3agyYLu+aG2Z0ufIyytEoLnFoVQmV0A Xudf5XSyYaSLHhknGUqEMCIAGs28bwNH7VwxPwDhoyTVZncve5gxXdBv9jyc1/T43ZkM/EnA0+Pc @@ -1818,9 +1818,9 @@ ezlduK5NHydT1THNBEUgCobkHMjGSW527QOSPkz+/dupi6kxxO2sBoUuF6rW47WmbiL/2xQhABvX ml1CQBRQhINuETISXcgJvqdjT2qh4B5wwBLV5p8TfJfciHi9OQ/KTduYpSVQWeb2ORWi8E9qLVKB yTVgEsFichTt1nxVDCGwV89D+oIgVy7ZumWiuqnrI4tfBMHhFJHjRc+PVYB2MMoUSWK6ZgqZVCWj QaLxbecR7FwXlEnuJeM2UgiPoTHY+ezjnJ/ljLVOeFPWM79QRRpR9cDaDtrDWLOcj2twAdGFZz0A -egEY6yoFATouMdYM5qpAm+1yhSGg0SxGw/grnz3kyvYDmdod/y0RNhMb0rxh5gMG0Q== - - +egEY6yoFATouMdYM5qpAm+1yhSGg0SxGw/grnz3kyvYDmdod/y0RNhMb0rxh5gMG0Q== + + vrN1D1d+1gnNLftpbP5CfOJzd7upN1JWro1pQOdpyXAqVLkzqEFerw4Qyy5Vl/7Mvr1cA+Cajfx/ c2kDGcAxtacE1MIZ4OEe7OBke3jKP35yQndzFHZrt3/XNbZFIs0ApBKx9wJhMEvOLlj3t097hrgn S7NosFegSz0H78u+gFAkGSfbNkJ1GlHG+xk0lgQpnZ4l2WZjnorCG99kafmQS34GrMrsY9HuhXw0 @@ -1892,9 +1892,9 @@ m36X48+ujjdSpSgPYrxjiNca6xPnEeYYkvotmianBpYrencg939Q51TsemgdP0uYBwJSppKNv//t Ji/ISchY1/CT6MbBBJf6C1xwHQmSrKxZFqaMt00T5V43dgFlnQ5psbQny2xHWuVdBLHTAtyGJsrB zmTRKJ/m008x5gqvK2LmYY6PgT27SKhsR/KAPUoKh8HIep7K0+FZMM6ASWyy3S41zkN86mQBKhSl 0uhDFoq/r00ATZgbrikjkkCGm5PhYElRonXD/KCO2IRzcunIUPYxO9b/VVNBhV/yD6qqIo0W+OJd -GgHrpdJfQIqYX74UbAOqC6s/X79GrX517Ua+dMCOcsrspGBEcTCts++SXcaT8lTsKw== - - +GgHrpdJfQIqYX74UbAOqC6s/X79GrX517Ua+dMCOcsrspGBEcTCts++SXcaT8lTsKw== + + +KdB1dRMB8w813UnP11TwW63hQV1V9d8qgrobX4/7MlP51rao56b2x+PwJ0RUU4ChsmsikvToBvI eMU8opCJkd50hyKhL02MVa9TX54qgrW2ME9GYE0qmwEaAp5OQfHsg2tVQbtiGg78LoYpMFj3Wlue K8T3EJ3OxZWPf6JBLz0/Neil/i8FYm3XV1lO1unnJJ8bmx4sMf6k5lAhrNkcFaimsIUis75WxWUZ @@ -1966,9 +1966,9 @@ vac5996e/VEjCu8JZRZXu6tChuOBbE0Gi3UJfltM/Q3FoM1qTksiiJLkF+VxQwBx5kHgMZtNCJYR CiHXqAvBTHLQASG/v6LqW/0VZP9gZWtVIRxoSy73kH++Mr4BDhO84jwU4PHMsMIlj13WwjRR7lp4 FCjIFtoh0OI2cR4KSf4c/BkuU8tuDPP+zp+sbfmzIRN9N1RTyyELhcWeMTHmzTelMVdyOGwlgKNP NEOhcyys17Cj9ieD1jygaWO13fDEkJndi0t9bKqcAyhoKrwnaubo87KTqwOguMZeNyBdoMgpSeAH -eAg8X/rRkq1xKVYHIDSCiNbGgfrR7AZ+w9EcYmQd2cQsE1k57IBcqlEGDOVlzSXycQ== - - +eAg8X/rRkq1xKVYHIDSCiNbGgfrR7AZ+w9EcYmQd2cQsE1k57IBcqlEGDOVlzSXycQ== + + t6eTyC9VRlgwbMEEEBu5Bt4GEuQif91CInY1ecA4A0e6dt2Hn26qC8S3jv6/unb0luUXfHeB+WIH iN7f+GHDWRSqwDuasXcwTyTbqyJmwugBVukuHOjuoIPUd92kezAmjI2UJqc8OwFvU4ttAql6xH95 AE5KvDYX1Q85O63dvHysXVNzBl6DQoD0df+muM4/oLguHfxj0cHxZ9NeHd4ZQsbn4uXvn/9plpfz @@ -2040,9 +2040,9 @@ iy1CS8qzWRXVATZZEcXoGKQyharCVDdJbbZzmi3TA2mGWRjVlKpdygcqmf6y5kiedgEDNMNNTgk9 ALQOmNw/VGuQxJg3lcDxFJPpcgZPx0P6P9l81G1ioTbpLp9j6VAR7ltTJfq+SycR+KDk/QRuXnFW nuuCr9MENdl9RS/P46XSPwftfInHvSy+Lmd49i8mkrR01UxeDGqXIXwCml7me7zxZ5Ush50MQKS2 EhVjj1QYLaCmiRVrTUeEIahwUy5gqL66/xpbyzDcXURNosvvigpNOyvba5juUyMG66WI6eQ/L3Wh -Oreg5xR8+MQlN4HUJt2d3W29jxmtakOFfQ1JHBMpc4Kze534UqFtKXZGFBnbv6i5kQ== - - +Oreg5xR8+MQlN4HUJt2d3W29jxmtakOFfQ1JHBMpc4Kze534UqFtKXZGFBnbv6i5kQ== + + dapUcS5N8qg2EXvj0A4mm5dFqnGz2gALSIyGGGRXoiPW3ABLfytD7+kjDfVQI5OuV4QjIWZSSTOD HMNH38npm2IPn6qXOETfhUYjUT7dxIfofpzk+cdbcbFxEEpmdsu+JBpi1EDgwI1iJXgVAFUWcycx trHo69zJm7cmbLw2lL7oB5IOBOTs3Dvuv0UEr+t5LXJHwBRB8t0MUrzW3S12qnLB1widhGd2xfOM @@ -2114,9 +2114,9 @@ rPjD3VSx+q7HG3XpgLiNDY/auK+179p/yArwt4fN77/o7bs/bzJDCO6fYo4bv34nMJrvum4ESIDE +I5+wCzjO9pRgRL8HSecrPuY34+KMLT05viO0qotl/O9b/KLeRnelYuLcL+d1/qd2upOTjP6eF9j dSjqNo5rqnc/EtaIFS+xbN/Pm5IX2IcDVt9dlnBC48lRoKzxridBqwaGO647QjzsboI4eV8L6rxx 147Et8FvC7m+y+DzjAAqnighS+Pbea3fIw2pleshNY0+P67Jhzryot1A93w+bxpKcHx5zCAgAofE -qWVngQLoeSiNcktjBAH7MfvDq6X0x8zw25BnOmbmIYNP269NOQyQRnTIxMZkrdrjBA== - - +qWVngQLoeSiNcktjBAH7MfvDq6X0x8zw25BnOmbmIYNP269NOQyQRnTIxMZkrdrjBA== + + oPm7a9myWPeYIux/yrvF2Osts7r2tXW9/21/QDKmv/vOYTvLUvo9L3Vaju3AJtkknzpSqxLOj2uu Vgqmfz+veiXsOa0xp9f9HTG+M4GNbdAr8L4vevge72XTlLfVu+fjAMi0YTkfxTM97Wu3nMcP/vZt fj/RzwpOjnHbvFa9Es4vv35wzRI669aaCYZR7tPLm0bUA7gTs9Aez0vvqwjepu3RPGYrrMY509Km @@ -2188,9 +2188,9 @@ kB39PIlltgxx3kNzYug2igShAfK0JrucNQEsEcVDKSwVoCuhX9ycj0fplm81W+pMxVWW9olDZqCo K0+tmEgyJji+Rot4sSMlT+TF0TFPLMmEGJi/ls5XnWuSTu9ylXxReWbEIHEMYEcLLX7WmpamaDbd SWnk3iLoBtj6AkOI3+Gh17FnNiOGX6I179vUfDgaoNZ4Zd6ZRaRo2ERu/urmtw1huGJ6yq+aWZJr gRUhsREmD/r4CdolTS0DvMWsY0v7N6YWpyasjMYv5VdpanmEo7eRGIQQh4PRmNhPmxbXimgKWpgU -ThN4QrIbp5qKDxNL/7bIc/LEKg9b1NMuD7PjsYUhZMttHA3zIiK6BLNG/3h8Yr6zuw== - - +ThN4QrIbp5qKDxNL/7bIc/LEKg9b1NMuD7PjsYUhZMttHA3zIiK6BLNG/3h8Yr6zuw== + + C00jeabTnBWclf03s0lL1YP39fvS1A8nubJDn9B8x4HOafhZNuCirtKuqp1CTKedUbzIrcKK6FZ1 dLnEg9Iurerr7pV+P+yj53cUJaHedA9L98SwOo5ZWcFvZJ/FcECfGols+OTXfeyOrgieTZStkAtW Hs/9qk+IFkMoaewi6aEIxx43e1Rn9wyt3ooU4v2zcZPJTIWlbiGfnejZr/pMog9U2iI8gD3GDcBw @@ -2262,9 +2262,9 @@ UlNhtid9Ti4a1XNNZVrcOSKLGKgKrxlFQOz5qSBbRIObVKAoIudv5Pw0gVdEIVYcYR2/BskK9mMQ fqpRU1cuUa40BlXJNgeHg8RFl0plMfXD4XzY+4WZZjEAi7r4k8X1nuoKb2i6BgdVDBeba6NCEitC k9EDW4jDtiittMtOFfFUmQwEx6AKJn/cOHfwtLi0Cejjyr/vogRT6FRQXU93QX4FdBCN26W56+mH ecJJMToV5MQ+BsDYEqWFJ5xRfAC0higCzkn5yYhsFB9jabayly+NPbt5YMaiAbhLhr76AMC/Yqfk -oNLP9ZjTy2XPLzGo9rnSQCsterngKt8F1vgiHHUmI8sONU15X57PBdKoKTo4mDnUfQ== - - +oNLP9ZjTy2XPLzGo9rnSQCsterngKt8F1vgiHHUmI8sONU15X57PBdKoKTo4mDnUfQ== + + dFZpMtqGAJ/AYzvfkNk+3WRXRCg3hdpYIIkkx3PxImehOh1oNhZld4Pl4iSrXMnf5A5y8x6qzQAt KNbTUIHbF93BQOrU6QW19q8NHFWO64rJZM0hvbd+14LHdHxCTW4xNj4fjQbgGrCEw0Fgun6Lu+TG 3oVPh6lqWpP0H7LZkWMLrbyFpymsOJaluLcUQ/GJy7ZHQ14YCoT2pww1owuJkx5MBTwOs6hblqU7 @@ -2336,9 +2336,9 @@ ISr/1QTZf5Z4mYGGbYBVX9kNNaucr9XE/vZbOOHwpddSzBKfXC/FdBmenQA9kHVjikecu0FR8wOI mMhjHKi6bAnZ3Ra8wswIDLHNf9hG9kGFd0URPrDirM65K1yZ18W5dPfDfdhzYole/WXo5shCSa2m A+70B46hCmyID/UL011JbmM9GPSFOAcI6L/Ze3+dALsOnsjPc1EIyedKA2ppkxd6BmroPtCJSUvA W8XIkMArWsODXgazJtPHraTwV1/WLZb97g++FCWaRRWN37QHE//3EnYlFQUiSZNuHXuFId4IczaX -aPJ27Jr0x0w/ELTm6L4oDrOAzNEE7nVKZG8RRExxkEDGr/hkWw1tQDyT6GJkLEFkMA== - - +aPJ27Jr0x0w/ELTm6L4oDrOAzNEE7nVKZG8RRExxkEDGr/hkWw1tQDyT6GJkLEFkMA== + + RfSElqZJ4dniIMpV1cmjuUi1Ju0OlbFVHpGRUWPzOAd9cfIhA3JRNg//RlYSwGXVRU0VvUlU68xo wa+qpFlhAQgyZW2wQTlNAb4Cew+i3tNBRYQ2pqhLX4sDUXSUYA8c2TJTjKnuVATfkYXai0zEhXEq ko9EBDm9V33kIQYd8aqAsHrZpiRHhinXy+itSFHwNUhEIijkDAVrU9rcGYrIUn+XoMCx6/Wu0QRL @@ -2410,9 +2410,9 @@ Vkosl49B3Y7QI23hajl8incacC2N2DTmqRwaMnzTyDhvR1bkaf+Pb6gQ9MAT6MEeC3PjwlBKD1/0 +LLJDk40YgaaEbHZp84ozXB3bA3o51J46QNL/9N+aZAtHas9irB4Jiwn3NgRX3/V1dhMPGhBX8DA SbK1+uVpq+dYrIDQRpIsTsYl/NNzsvXaTx894fcdt22puoGb6Vhc+qsdIV9p5ol/zrMjkreH+0Gt NAJG68bjzhVwoqJdxBKLp3AHr3Wq4F+cbNypbTlKS3uiwlrgoeSWyJASg4TaEtt5sM2Jbfnv2CYW -Y10/XIe8OIxxGzyta/BkGj3OyFa3TkH+cdWDE/jxVDiNI7Y0nRISQuMwtrmiATpVGA== - - +Y10/XIe8OIxxGzyta/BkGj3OyFa3TkH+cdWDE/jxVDiNI7Y0nRISQuMwtrmiATpVGA== + + u1uPy+iVRY6q1gtoD7ixlLPgOBM72kXqAO9Lp7s4KiQsSDjdRTDHsqUrelvPMKgKInpEgVsKQywT fCKxe6zO+etQbQwu55PgI2CFd73HrrdVFV8tLDb3jzOM7BaOaWMs9noxPQ7OCweI48QuDQN2tqHW DZdaYFAzTJtiLvN4qx8m3mssxcwbDiXUaR2FMVqfmvQ4Uhg5S81YphrIl8uzFQ++fs/Ay/vfv7+/ @@ -2484,9 +2484,9 @@ gZaCymL0RkiIHY04MERlUYD7ipHBMVwQKufAQHbGGuB6b0a+gnJKxR9WssPMcrg0UmTESqzsxgRO npLieGrMiw0RL7cWUgq4Rh1M9UwL8R2Vb3IAerrwKSpjs7lSlGElJM9vvpUhXUIVuBkpbbsVt/q2 IkBqoHgAbI1Re1a+6FP4aVyus3x4/Lai0iYTLGQXdg61fPAWxblfC5v1+PUrlxudMHKwg7RTyZS1 tTdu6A1JYhWatR4YX8sSy+FsNqPVwkxqVVEfMSl5q4CPOmXS7LGEV/IQlSjM8+1iim6H/Dm2BzCn -Wi6ctu03KH4FyGhzvxpbhD8skrY9sIoJa3YtY0ZnGTRlHrDA77VgBneZ3ckZRfFURg== - - +Wi6ctu03KH4FyGhzvxpbhD8skrY9sIoJa3YtY0ZnGTRlHrDA77VgBneZ3ckZRfFURg== + + w6xNVIchpqVfaXaiYl6NQ3GzD9I5DBnZN2NLmi7uRqjdyUWTvPK8GStibBxl2vy8xLfd4uc6PhtZ XBPvBGERmrB6A10kW2dz/URHcfgsRFY2CRVvx5e2jH2mrVexzV2O6I6KGH6vV5rPZ3CyNRpRae4Q LCTVXLavbhm1drvg7Wa7GRE5d4YCsEAQqxm18WWlQuU4cXisuYIig55jQmGN3sAm4mMI+um/536W @@ -2558,9 +2558,9 @@ KWqWFD3ugXGwjUgILgR9YaTEmF05GJY0c4pvQ8TDw2uU8oFjTjp/LxQE55V+X3d4GlBUMqNAcyu2 bAt9yEjV5VVFbeFZOYR+jJR3auUbSteaWXCCyOWb8YIo8OU8IfXlpTNrNpGwY9VLM5I+6KripbHf 69i8qpQThiR3zKbwW8gO+X1iffCpot/nrNfC7KG9lDvNxzkSfAuIEO14r4/Jp9juWuJ+2eGGs4Tc rlxDbrhzRamBSBXKIfGRrGVfpBxmBC2Vv4B4AyHNM3bwTj/vQAtC433y3WauTddq72wq27EzB0k9 -zBhJQY9t6/eaXzs+dpX0hY5IMLLK2G4UJEJVSFfvlYZ7SBs6oGWpAflpO/heV4ncoQ== - - +zBhJQY9t6/eaXzs+dpX0hY5IMLLK2G4UJEJVSFfvlYZ7SBs6oGWpAflpO/heV4ncoQ== + + rZH7DKtQug2anRJ6ZYcK0xiom9ykSAZlk5kLnHluWoyyaq/kU8msib8P21aOpW9LW8yMLAl7/w7z 7cCVuaLdHaun70RxO+HlnAGDPVspIqhcJnPM7oXjkO6mXP4Kb8/0MiKJSQCnG4t803MaccmOOFXn pu6m2K7WtyDPNNmLrIkbG25CMRIX8C3C1zx0UBRA2n9fdLOLMHZ2pWxJoOfafFrTz6nDlESWJpMT @@ -2632,9 +2632,9 @@ Z0hqg7gtsU2R/eQkYkYzLtF2G0tc13FgtCKWuIkiMAsopCBTIzWwRxn6acB3bRzVpBRoJPy+oa4U IiTvjaGSlzYYmdwNDHYMv12WqqM4nnO+vFYtZ+9Fb+s+FK1VCc9g2jsqEk0OutMS8tzRbpa5HCdu 5iheZQ7dqCFdyhL6B03gdjM2ZdG8VEfNtpANOxyIhNj5EwQjXgb3tSsMXR9Mq0Z11RX8Xofwdtge cxxgK447ur+0ZB57dtm6trWma0XTnGNuVJC3x3vhcaIGzbW9w+hVX/FdmEajCrC+izz8etF+Gacw -t+UqEJC/wiaVHnGBmTEFoKIv0fIVYRqtgRXaydqpKDlJ4wod1TVPxx4nen6a4JN4Ig== - - +t+UqEJC/wiaVHnGBmTEFoKIv0fIVYRqtgRXaydqpKDlJ4wod1TVPxx4nen6a4JN4Ig== + + iSyzpOKOgJmzBYfgdYnbfVCOpQR0j/oLP1g9HJ03memTH+lUMx7p1CRVnxEyciNkAHtwnkswi8YY TSEK9OH21q8EuVtzKZM0cwww/0ZHVTrQJUj+zc1j1NSyueHjHLGVfiZ7hX/bLoCL30uqsgxp+O+Z gWwgrQ2HDLQr0kITp9UWFEYrc9Q+zUZtd/dSQxB5jVhbbSJJSk06n6nISyw4vdLG1Hq5xEeMkmpU @@ -2706,9 +2706,9 @@ lXAoxgWRspp/AAVcl2uqvJ/kD07Du1XH/+EB9GSfWn6jWdTfQzVkLp5HOZlLXrhIU3BctEV2KTjS x8noFsE6Bssff/Bkmn1Cby0Ua8Wy0MUH5OtNxPuDGsPl3V+fN/IaH1Qq9eOa3FbonvVBhbrbTTwQ Zix6n5K+RVH2C39OEvVxIm1dy6YzPTZJVH64/ff4HGKGspIJHTzsLfWIsO9Q8QsQUDBGHGh/vYBo du0MZBTdK//GAgaZsMbT+59A6uXnavs9x+RxqRIP1UqOKP9zI/Jy453g3q3/JGKd3XWkli7asw6o -Y0YPsVQJFNCkGktJ9fPtK60aPBWp79enTbzGx1BcfGPN1scQgC94ooxTo4mYJDRXSw== - - +Y0YPsVQJFNCkGktJ9fPtK60aPBWp79enTbzGx1BcfGPN1scQgC94ooxTo4mYJDRXSw== + + hNsnTqwv0QsR5PhJDNcKEHckEGwtqPLiSqirnMnpZYRd92oq3ZXax+cHOC/tQ8N6a1SeM7MUga2E SzAW5d+dbUQl1DkkP+zaHlwwUkQ+JXsrCHyfPdo/MPIjhEkHPPJN8aQh/ogmXeQV+c8eL+KHcWHV IvU4/ZtxycFrKRr90AH1rF/P7EcGrRkKltJZeuXVZ+mpCpsPUKTShwoddCqxO9XNpe07VJssrPUO @@ -2780,9 +2780,9 @@ ks38OKPLbUR8LPdgbrCKaoIfugqpzXk5v95Nnt3o8fPV1dPNGZ8jhejK2XIisyPGJq8l/jkPFabY eYZOYDbSpB7sSEoh5qWC+PNd8gp2QAuYDYEYuXvnSyTAYJgMBZpCgz6LedhdX1aT28ChyBm7wkYS viatzir9M2Eth19F9OXnM7roebAPLEP7oXedxTGdsfXRRpaKFBoB5XCfWlpdpAUl5MWtxHhSshRX d34GynAaHmkCemQs9UzqG7KQgJl96bMZIIrUMs4k+xWALMIYLOlYTigy0ziDF6YMFQC7qLzS3oXi -zRwGTWFWEp3ZtXUIgSc9lXyJFDlYT0eiWQ8iQPwTGcQaEfabGrVauSx5vxpbaBuBWg== - - +zRwGTWFWEp3ZtXUIgSc9lXyJFDlYT0eiWQ8iQPwTGcQaEfabGrVauSx5vxpbaBuBWg== + + QypUlYSHB+Lp4R19wOio9aLLyg0BuhakYul44p721pVgu7VUutjai8gzLctG/Sknhth3zrJyGDmc yIwGCBKFHKNi3SCnYtrw7VLBq0HhvIbN76uHgjyfzN2IMSaEPmwzHv0EmJo0fvmY3TDp8ow7ZRN7 CU65fmXsu6lJKZrqijYwkslDJ/mvrvbTpjA+Qb5m5lXER+6bmUKFCvSP2CJ7ioVsfkOlrV34GNsi @@ -2854,9 +2854,9 @@ C+OzD/w3uo+VTMFq8xfGZaAk3Mfx+D9+iXZtGnrhdaijhhlG740W8emT/v/xFp0OxM2zxewZGr3r jGjzu91mkFa9xBqvwUvzNKMmn9excv9fP5pV60z/vo8TDxQP3OoloW71WjgaCwYNNRhh9JpNN3rd Ib4bNeDc7OAIGB/bQOe9vMzrYXQ2+DBOrZsEibsZFHMWsY4Xuc5qboRY6larRQv3ig+xkMJ9GHsC WtxbdcEhu9KyfmXQWBEp8HYd9+FmgwuhV55ZcZtXTnL6zsYnqB2kc/hqvS50ANVn2GVocrgD1n1n -csdrtbeOnz92QyMpgNkIA2HU8rEAGYHR9XfxVlge6uZz/5xil0rm8hmbskujYt+xow== - - +csdrtbeOnz92QyMpgNkIA2HU8rEAGYHR9XfxVlge6uZz/5xil0rm8hmbskujYt+xow== + + kps8ORkbH1udUJnEMyV+LD9L6/nfD6Ffb3QCwMDpsKgw+DB7iSiXYU8AwVhNkXJ5ItwOBP/Rr7Uw 6tA6bhU3MM41Pkwz49CyHR6trsoXYcRYuXe2awMFRs+7udGrtmH0pIkb20hcw+xmE7u9ioJh5Ou1 3q6pBpIed0NAAtcWrnekfsTjuhiFG10EBO/LUda4kk6zmwcdnoEyHBqrVqqtF/Pphf+qH9MJevAe @@ -2928,9 +2928,9 @@ g5K4FVcMkhnhHVfI8ZhxNMvgSqMWggGKI7Bq8gknkZ+7t27MNnnMOwZl9mUu7sqv82PVD44t4vo6 D+WwyKnalcnr2FIqqZUOfjFIhzKhJzZz4LILOM9qUyyk/f00vAL+3qaMtELGGbeswitGyE6psfpE lj0cc25BAkqNSjwzI+CcMifXwBvouOtH0KWS6fYDOyF7+Oa4FOBR65ne6wH/lekHl2ubJqkYsxWx znibkQfHYproZZXSFi/VcqcYq6k52N9LJsCMqtltRq/kV5S2dAwXlm2FQA7G0AhV0lEEniSkc7+B -A6JVATt8Aaup02ITNWYsD1G8RPA5XJxSSofG19ZrVSj/Q7k/DD63ry8x+hOoCvs3EA== - - +A6JVATt8Aaup02ITNWYsD1G8RPA5XJxSSofG19ZrVSj/Q7k/DD63ry8x+hOoCvs3EA== + + gkB/0ON/kxCURxr8ioMkx2qg4AI58G/ghFUfA9aUpZK86CiAoCA1+VHwS4qtYnUeeNACbZWPJ82r /ISxUL0jG8M+iQ/Yj/tOoJ2bI5g1JjbQouDijDYsxsTNQLAuo9NMYI8I7zGqXwTCZ2tHZcbWDzJI T/8CptqHAovUP1GjCtTROPgCI/PPm0GP8F6D0CZA/PStNmzaOfW8Kf9eNepschKH3w1Hq0ZrBGkY @@ -3002,9 +3002,9 @@ I5ngehgcw91++Vs7FA6gQn4HPlcdfwG0PdG5q+NnGPzyKyvi5Awxy1UIwjUjKkqqzk4hUyk3Y5y7 C4kJ9GMmPCujMals7w1j8hRcnsxN1pOoydOiQHtZqHCJ0fZTEY0XJJ7dYDBlKrrzRPLLyi+AidBp zJ3Z9Dqp/GN/D1gPGpvZb3G/mnYmmMtHFPx8JIIVSWCfQJDKcLi23wC6seZ0kg4jDt3wv0cWUyAt qB+qj1CwMy4U5cQdsfxDfeavZHPPvLZBP1lO6N6xM1KwtDjpTtEz/TjuwC1q84BCJ3+aDmUVnhRC -t2bfXo1KQWTogEOpPmD0zogVI4dgOBZwusdkkPtW8QQsHWjiK+G9NrS5WY89q43BFw== - - +t2bfXo1KQWTogEOpPmD0zogVI4dgOBZwusdkkPtW8QQsHWjiK+G9NrS5WY89q43BFw== + + vABZQyg/SUKxV2xjrGyWwfwwt2e7wctrHMQF+SBuf93mvrQW6jdPDXDzNK6fg0tJe859WLrCgnXN ZkxPjFgyWieyw+A7M4baFGEjC0QC05HmrpMiqYqcZxqyLt8HtysQVhQkl7R3K5s2LqRnAFmRflXZ VxalZKZbvVQyaijuyrawqRrrSB/NmVl5X3Rj2XJJVDWtTU5yZWxJ73VT0U6PCFTadXQ+wQZ6VBpK @@ -3076,9 +3076,9 @@ gwmGXgfei5GNpD1K41t1h7sBjiFXboqtTJcUyg7AV7hZ5l1NbUrTSVBgkacaBBuN8VAXo8rB6A95 L83ufWjua+eFr3VgHqOZuylGO5LFhBRwXs4xEwjZzlgamoXjnyP7dwZrVMY12Z1VMUK+QkuJnuUq f6GuFisjgkDz159EsBVzQ2z8nNg8EpNsnFgfhhbrlILjrOjuv4qRxObBHrfKugCuTBRKuDN4nlUy FRtj8iAmdxKr88FGCgDMUhk61xYBXC+XJPP7PdrsgWwqZsQwwpq0Y0cIIgCu9GrYgy8if5LtNqdI -PxaFec8HrMANSwrdEgmyM/gHFNZl6zS3RWRYLlYLnicDnkiGy6f9sppHSdhGEAYKOQ== - - +PxaFec8HrMANSwrdEgmyM/gHFNZl6zS3RWRYLlYLnicDnkiGy6f9sppHSdhGEAYKOQ== + + HJs2kHVmBD43o0TEggNwWSI9A9RrmzxKZA4gSyilEXzX5eJsaoawqkw37CKtEXect+NWROGgFta9 SSuWOs7kCVNxmorIxCyYGeR2K0maV7bVjkQC6LoqL+diBjhfpByOxFlzGkwBkoQlp5QmpM0cMCfK YV4nh9qKqncs9+qY6lV2ItXdEjL7SipPKHPvDcHZ5QVtdIz3qh/yC/nUWKfVb/QVSCutnreR0fYM @@ -3150,9 +3150,9 @@ r+vqWl6bVB6k/X22KzBa5suLWD++lrUk0uvGzKhEsy+qmqFqL+Zt+80qLprMrljRThDB9d7c+0+Y iUDpo26D22jQ8HiDaUl8hSVNXgv/UzBvG7jMbDnb5c2ZeYOXY0pzWxxD4ucbch2/QIqHoPJ3+Pkd qv4ejt0Ct7cgL0RJD3a/UHUowqTBNRfE3wZKWOsmTwDZx68kYiM12VB2NpSobaa2Z8C81PgAbM2S 0RJDr6ymoV2Pr6Zm9J+rVAGwt7U9RQCHRKVVb9JVvY5qkORNUsTAKaaQ5I6uRwZ5jMYwGujpcwTC -cp8wK2ROzdvOLyGON344bEZ7PRDmihT7RphxIgLXumsZpHcQIC79QD5i6NzHHWYXAw== - - +cp8wK2ROzdvOLyGON344bEZ7PRDmihT7RphxIgLXumsZpHcQIC79QD5i6NzHHWYXAw== + + 8gLs3rJOhojXB34eCDBZeo3YZUpJd2drmtm2aDawgdGhugqmCIcvCvhl7+5QElBX/BMw03rkHgEq OnrR5QEzFjJtgQaPRubfDGMrTfW6mUmkl8RaZa6JDD1F31IZtHuOTrC7aK3wCt6zRaLJMeaieIkQ 7/0VgvfUwv6mWqtMhk+Y6eQVB2+p9gcVLqiNJXjgtOkhVYptps2SQCkORmWcbX43YC7ZN5zy7FKf @@ -3224,9 +3224,9 @@ B84wJ82MO/F0J/1dW9sVj5GM2iDd7qzhtawYtO7q9THSzOxpDz2CE4azGHpz2YuzuPvRihTvnvt9 1w+KbEkbxc43UDmOD1VMWxBwnK4hLnqb7iEdTcVR/NrOyp4qtlopXs7nR3vGSNwzuS5xd+0R0TED 5L2bD2jjwsiuP9RP+mbrqnx6zPflSNwGhIvYCFA9SDH5BATnNpuOZkyLrhBVJftgWxE59H0IZRIg f9K9jWDv3jGwO8OsN5/azboV8Abgxz0UKHv3DqWHC9Z1swZEuvip3U+2oXgnxD4ccp+Jc7K+lYvq -K7WdeYwupdkhj/K0XLTFxS7fNZPtG4T6yqES85tq8w9sJXlNgLQpMivbVqYMyYRWWw== - - +K7WdeYwupdkhj/K0XLTFxS7fNZPtG4T6yqES85tq8w9sJXlNgLQpMivbVqYMyYRWWw== + + W96Ps1hJ1TbT5b0zxYx9b1muEkYLa0TTH6qrxZnxuseOSmUVNrho3WAYZlw8IwAT+QlmLnrqM8Nc 0PqynXCruuyrHHODWvSOM1H2AdAj7ezcyVX+2qEZZPez26OR4YOp0D1cEp5Cok9boTMoP4WYHWBX HsrMcHUfb/EADGKq6qKDhABwxfID9qki5fBqiyO4pWOKKzWSQ/eLhgLYI6S+t9g8oB0x1smGBF9a @@ -3298,9 +3298,9 @@ vSahw0fWP2k7ePajZxVnTe+3WR7dntbygU+uG7YGBdkEyIM1t4Zvi6+Z15mIWCgqLW+eY8ZhGHEV n5qMjL+8QgQHrmTEaCvFUp2joJGRmTHBtmCTBqAu1sreUMuN26LmFvUxdyFnX9t+DkLhtXhq14JU Lfh4U9mVjdkDjJ29uUk1IWG7K5pBl+LZgvdXCCBkafgeNB5AOymVWhG7TEdLpcm+Y8XrwmKErJa0 ZXH8kLQHWgk3cIV6ySeyXwwBjdJQ2BQXtI1NOX9vuRJtmQM5/VfMZbACqbyxmdN8iHSfRhNJi1+Q -zmbHG2mQNNl/lTDL9yH4U1gv7ypTbD4cKFKF2lVXmatJppyXSuXUrjASXP/+AMF7ig== - - +zmbHG2mQNNl/lTDL9yH4U1gv7ypTbD4cKFKF2lVXmatJppyXSuXUrjASXP/+AMF7ig== + + frs8+iA7YRBoJVStrYir1++9jp33f9h7vguafcK8nAFZoQFYjkhzFygDbGSiVdtrP7R0x8ChE94q pTtMB2UZQiPtUn0MK5VhTTMuf+4HIZE5bSXXk3MPTOMviPgRZz8k91+EAMYij4nMBjFOEmu0JxqM ALY0B4pLrRhrT7lNUK+bdHxzdR+3+F6e66NYUroj1avnwhRAWaHxpqCuD/T8TFBjUP1BQg0KuKLV @@ -3372,9 +3372,9 @@ lts7q+KXc2H51pn/4tkTUdmvG/NJc7DfabYDU9f2K/L+Ht4DK6B6t1GZPBISknDetlYQ9esVzpNV E8ZiQLZGyNLGq5S1WVzZPdFfFDPU5+Suk5siYAVK4d78dqdQV0UJc/G8qDgYa6LagkwfEKFrMjyF vfK0Usn7i2E0q2wB6niJwppT+qpirqeZGVsJFT3pdBcj6MRibI3G4fz0TEaQmKFPIcbeaATz+/0J +GgiVqG36OnhVEq7o5HwMbSI8B1mIEp78l1KjHn5Wuzk9AO/L1/TpeSE6r8bfo49BmphQkrGXXJm -ZgQrWX7KxXyr6KUNjHGGeL7G3p1LcfHveUTmByuoCvdqcpKAUyGqBJU7V2qYJPAx7A== - - +ZgQrWX7KxXyr6KUNjHGGeL7G3p1LcfHveUTmByuoCvdqcpKAUyGqBJU7V2qYJPAx7A== + + rs4Br5niD3oGJDgVonZQufc8BiyzBdtr3AEV1jsvvi/lyqrKV+G+iijjzy079uQGHPHMw0UkH9F1 u2ZuaW0/WqDIDYo6UnIDJGuqg0vbtrVrxjV6octHyrY0SbIvKep+kFQUxQVsR8m0msO59JhkjYuQ KWexYruWB35teRgy6Zg03TUZ/Zh/ugd3k8Y8rXw7KRaxzURtfkDIRv0d5rJ64Vlg79LIf5Y5WSx1 @@ -3446,9 +3446,9 @@ M2RbkpCPxnMtVozzzU/gYWHUSrEUL5sB37P8osOEPMDMXHUDiNw2V8PNJIk17D36mlNLoHu0HDP6 HSXPEF81td7S0Pgh1hdNC8tOkjaJ21qNAQoox11VNiJkuDDr3gySDZkWR+oRTObSI2LzzbeMrJRM PyYIGsjQTwX8IkL5hAdx5QEVwCitsnoCuEqBylpR3jMhlqHFVw1Iuz/ZWzCinASRodsnS8Y4BIfB VV2d0+aPGFYMSLA4DPZKRqudtyxmx4/2dFJaJINGWk5YIkOK1cI0x5xNHxvZZDVKoaRRg5oxSDoo -Hp45W0EK+GOigOKFqAXuJ49bXSxhLxsptfxGbWuCuOUenC3uSgs9owNNVO47uLNXUg== - - +Hp45W0EK+GOigOKFqAXuJ49bXSxhLxsptfxGbWuCuOUenC3uSgs9owNNVO47uLNXUg== + + D+zVMDl6mc04EQ1hSsHi5tMCmHWhlMU4XQ3guZBJd1JDgqqPVL8lWowPsgFOyAEM47P8nqrh4Zby 6RNitnA2WPspiZEkSqe7NAOmRWQ7yahAklzIFlJCLElql6ucAUMxJZEyQRKRjVQsxvYrTlJwsLYs ySIxFwRdclLGAKu6ysyU6s/iTOGqo3RTGbbUZLlmloj81NSBRgtwB/CiJETxRwueGlxKCBpBtDVU @@ -3520,9 +3520,9 @@ thr7ARv2+JOrPPj/ur76x7uzDxc3H+9NnvIcAGLTiwCIbTOLlwsQe0lJZ5+9bvtTi+77eLZ+TJly HySpfbnYLRvAzcWb7fJE7f01f95pOA/Jc59CDr7+oaS5z4gNPbvkv5zu8/nznLdX19dvNHfp11dn 53/94pWQrr89O7+8/f6/Da+3ebY/LZ3pXm7V3l+R39K+PKMb8hKf6M+Y0wG/vS8XfF8lpw/fnL25 /tvJy+BSzzHD5pvLt28/bhFBtvfs6XlrED+7RP567rbP47/xgz2clBz+Lbeoa/zok9kuWX+f4f/h -Oa3bP/q0tmVnL9HfGdLDXOTsH5fvPm5j8LaGjw8Deji16sVV/R/bGUpd00efCd+Ghw== - - +Oa3bP/q0tmVnL9HfGdLDXOTsH5fvPm5j8LaGjw8Deji16sVV/R/bGUpd00efCd+Ghw== + + kyftvVzzm0tmuU9ameA3crGfaWECqqnwIooTHKSsPZKyXugbfqgCtVsVqIPEcpBYdpFYDgLLjzGG Z15K6cVILIdySptTeOJyStuerReVbWRfLvfLKam0ta1nf2/1oaTSXuqJWxT32deSSlsU9zmUVHqK od8XgO2Hng5v2c/0Lfs0sejwnu3bAdvbp+xQHfDwlP3YB+Zn8ZQ9HyvqZwHz9lyzPlQJfC6r/9MN @@ -3594,9 +3594,9 @@ FmGN9OTy72tDnepEzCUW/XxtII8vLXxe+PNz5QiRhzrWN3+amFiXOOSchTgRw+BlqUPU61RFp2Ue ZQlpLfjk0L7Vr2kHwyIdFOFfPAKSyCbmdSMdV+IeQ4ly3iqtLg9JYUSsL768hZXIbJwHsBSWWIlc OazKZvWSzmkmYp1gHoeoJ7+KvVE6mOoLpGe/TrzwO1AnlqZp0quTA8tmYxD2qBy4Ln0lVuki07MK bq0SUJVE+A4rs8y8B9QBXVN5XUIVQYhYl3gpeIkq30ws81XxcaodqvyhT38dFi+XyFVjPbyy2lU4 -1/eCZJUhJlnaUNdUH9Nl5BNT1yCOysMn8HC6PHS27OkX5gOyEoX7VWJehHtVYi7M2A== - - +1/eCZJUhJlnaUNdUH9Nl5BNT1yCOysMn8HC6PHS27OkX5gOyEoX7VWJehHtVYi7M2A== + + QTzHizWH1LetDGSeeLoTSaWhp831qQ0LXjxPnurp5etVmXcdDW8utZ7lIawMdJblovs7J17voR40 kScqY0tp0dO1VNF8LCo8RBlXZdSVlw7K2OIQ+HgutLmpyK0b6jHB6ZpFyK+3VkXsysL0dNI5L8oX ScXgl3xWvnaCJ2jgM0d3Wa/3Ug91yMpD+fD/6UjIi4yAxLJ55qtUBzCq0MCvv7BVfXDpBSKec65r @@ -3668,9 +3668,9 @@ oGFM7mNrIvd6okF66l2iCRC3EJ0vi2JNn1XddSChl8dKA6zD1vCyJP7ASiZXjqrKE8xutBYqIDpi ElEZiTPYE8/kPM1F2ypXrcRRtRpqKRAi2jd6x6WDCdgYktySjrbe5Ry1LVwx/PKylMvG5WK/5xvO VLixCcwjTldCnMH+1REnJCgcDPjKbXUAI4AQRAzCvxn0MylcalrmbB3kBdDKWU4czyBNiqJiHIQQ 1ZPLI1iiTUFFFWqrjwXDdTAsenO/19DWKY06rnqsuCWJjKOi/0IY4AtOBjVkgfNEk48wHkgQX1Fg -oMMi/xSi2tSpZVmUGFoGqir0lKIIzqAPcSC4aFbYnrOWNCKDAxDpFRcAgtkddix65Q== - - +oMMi/xSi2tSpZVmUGFoGqir0lKIIzqAPcSC4aFbYnrOWNCKDAxDpFRcAgtkddix65Q== + + KFJHtg7iDLcsoW4KphAJ1iey62xHlohiuSWoC1ByGU8RuSPr4dQOKhdfeGaTWiCFWGbRq2YB5a2J 44QELJW8CICPyEmnUIlJHveug2VigY6IM4LiyXmYRDGeReoQosJ2pyxbL0R9CgnbMy4Wjl3lAW3K 6syVkpNAnCf6bn4F2qSaM6twa2LMiPQiSGYYgyMrscgIihmHaQDjUkAckVhmMIW/rlwUC3waxNEu @@ -3742,9 +3742,9 @@ jhhhV6J4B0jCfVu+i6dK1pA3GIyEqImk678U10NEVqzZXMTGHPTb2rJpSfolN/uMIBVxAt3hOu/H q1agc53wpH7TbMkAShREUfPbCVET8tAxa3WJPBnyHSWXknDYZjzgoKaJj5GHQPcdqA3mnhG0RaQ4 Ba1R4JfcXIREHEUN7olYRCWu19b8wbSIo2SFaw7lO0EJxwxg0LRdzW3HUIcUysbuYgoenNKRwZUZ kT7mDSLmtTq3uo3NdOl2ofmmiKiRJ85Dw0Fko7eSnioV+bHxXLZwMcrKq+d4BLgqzw082JP5iq6J -dpk90bw2LuCsv/gNCW8sonEDJaIDNtx7jwWxEyQzNHcDETWS2DsGfFtlXKeeR5lfwA== - - +dpk90bw2LuCsv/gNCW8sonEDJaIDNtx7jwWxEyQzNHcDETWS2DsGfFtlXKeeR5lfwA== + + M7OO7YGYGqCQyIolgwsArLdlR1ZjvW9rRnXPY9WoDtYLjjwAx+LbtifBmDzejvWTUuSMdLx/VmRr T+yK5XmyJlfrO3CP2p0IqfbWjQCGukeNc5jMhruKCP5hBNaqA/9aWweTC6aklIlsdyXchimb7bVm oMyQVm07eQEtx+aV74WTEPNaYhmFU3x3tCaPDX3WiAYza0TFqZ1sdABR6r4O7sG03Yl/a0TNAeAl @@ -3816,9 +3816,9 @@ AJK6BGBcenFc+Rld5iqXYcoTm6vUxXW4aJFZFn9N1FCPztvrMm25XF+UshmuZbiLW1hI3wFVjEH6 LbisK7Goy8dNwacVc3m2PNm11SKHPjRmkWQRjSiAmkHKhHVtAxeoXbn4w4AijX0WNU+2AA5PdL0i ssV7e8Mg5pjiHdZ3E1sUTNdBi4Lp2moNAp9ezrfkA4oOWr84zN0ImPinjdFav/dM4a7puqCf1tZt uTvKLWlcdx9b0rjmLnZEdx89saE6XL/ueGQqqL5sEJFeruvAt+WPnR6tW9sY2m3oiGOEf745tzuy -cZr2sebxdp/SlpsdwBHuLqkjzij03nnHXZa85hXl+qbLsmKWjfm47HBEZgBa30Fjag== - - +cZr2sebxdp/SlpsdwBHuLqkjzij03nnHXZa85hXl+qbLsmKWjfm47HBEZgBa30Fjag== + + zbnt2F/HrpNBIppbtSMCiuS4rXhAz496Jt4ATkNEZU7nQHRp9/RFW78XXVsE2ymRhb/65JSydkx2 RCjwA+Ht4Gx0H/Pk3DpoROjfXa+WraQfmLW9h9jm1WKXXJrAbgQIOTSTi390VaeW99mTLR+eJ5o0 sYh6WjoXps8z2FRtN4KOiOSHPiLqvraNaOV7PTG3hHp+YBZ42mIxzYTgkx92Kf2W+roVD07s2nrp @@ -3890,9 +3890,9 @@ m+N3x0od+EmKhNjBmmf1tpsbg0aRQcyzEdVAlwRDa2fD4J9zM/ezjUSIY7b59iM40TgJWlK5CHx4 3xkx6EVCsXDnCQmirmwQh8EdWlGTfAd0aYIiPDKCpshSZUWSaSHP7dSDF0wj1ryeGP39aHuGJV99 35GtbqUeW6IVc2100z+xiwOXaJbgKFycWU7InFFGkHV4kcVnxargjI9KDEhUIVcHBZXjYG6jNKFX QwY0nypFxkzt7sCBrOT1aO8kaqZLzE23jB4WEpaMKYgOmAfvvEJh7cHqotrIlNYGJgdhaMw7CoaL -iWwUUmJZtCVbNNHBuIBRxxGLEEXVy4NfmdX428S0HAvAinaYo2EYYUhIZomf5KHvTw== - - +iWwUUmJZtCVbNNHBuIBRxxGLEEXVy4NfmdX428S0HAvAinaYo2EYYUhIZomf5KHvTw== + + zSRVzwy2oNBtUtntVR0Wq1k+mCN8NYLGAFS3gxcRQ5unou1NP64XVGpbEZ45uKi0YkNzPjzVOGgU GbPQOkw03DlbCF6Bl4eBy/g93vvptd3oNlTAxDfH7y7KEFQJYHnfLop4/Cp5KuakVoAoKQGLBZko Po2cBGS1MwNWgenfscZh4pNHxOZtU6QD1BBj+mlRh4JJMhEgINJj2tM1mTHdgUUiMHZA8epo1Tja @@ -3964,9 +3964,9 @@ vqkY01c5GoAtWrPswE5uYvfkcVi9yHlfWZHuhP+0R/lRXFdR8+aG0XdsTTFlFwY8546LUEr0gMGU qdCb4QuRmEKGEcpJjdokhfWdeZA7MtC1EgrjTgOctHz5fbLtaSgpi9sEOM3uB07+2B3mRAP7SzRs KduyIzzNnI57x1YWTFTHnazxON+PYBjC+RgX6+Nk2CnJvs2KOt2SauGbA9FhGrh7Zojx5e4pH+kt fi41izrsqcaWzvWCKBvW8mnIDT4OVw0x/IjpESKQnCv2e74TwH1iU3GX1rGTUu4Gg6FVUgIX+IKQ -jUNYMwcNhLvoH/g4kzX7cgPXsePmJaZXcLCn48OV00NKid4gQ2E1KYl4AF87Ih4GnQ== - - +jUNYMwcNhLvoH/g4kzX7cgPXsePmJaZXcLCn48OV00NKid4gQ2E1KYl4AF87Ih4GnQ== + + 8CVFpsxV90ymw3uQoSgZXFEFpGFBBVgfW/RglCWfwbGy4FgMNwngXx4kcONhZ/joEXaJMl/wzYah FTTy8VZRkmnNyu5Ga7CcAa7pWjX7bxtqv5UlW89/wJDlXV18vocRx2leH3DotT9hrAiH0AOvSB+/ ofXst59svmEFmwpA7GPdR3u/YPAZhglPA9gvWhBSTd3Pque2Puzv+0nDwuk7whCQqWdZJmy/XPPH @@ -4038,9 +4038,9 @@ PciNPwPBWD5whnERKAISzMAmgN8h4Ai6vYNRVMnWofxzCg7SU7wChoZcqJ9ADPfByn8Kd46XpZSe aAsPXvKgVLa6hpUrvHoFzDhFgmUMdtQpHmXCbhzVEZJohPzBcit8XbGjfX/NMAw7w5Hr7IZbxk8I 41SAkyf2FFaiPFZPulFeeFlHwdHnG4La1RhNrsX/uS/NbBkWZ9ktG9IiDLoZ/53ktTckLhjtkd0b /hUwaohY4Jw99rhQsuXacnMVsLlffrxLgRGwUEAwqVsuoNMTA/wOAf1uf9UWN7bSck+CU6MUD/aP -0hY9SK4XbRng99cMI9/u78DpFVCUXV7hQsblJ/BMktjyZig6fFjW1T2/1ylFukZRSg== - - +0hY9SK4XbRng99cMI9/u78DpFVCUXV7hQsblJ/BMktjyZig6fFjW1T2/1ylFukZRSg== + + CGDbNQzZpVtvwM1zXucx2FJ/k4cVMHJejQtph+nqOKFqPnCUzTIwKnCg7Qz2JE0vsDyMIGgZy6Pk FU5kX+vrnqi8qVI7apUARA/YdnTsjy9vjSo94Roy8PCoP2OWidu0XYHvLIW3RtG61S78rgJerCR8 ZJq08ZLFFnI0aKDXwlrpq9l8ljMYUE4/pc2MdIEwJsqnGYhqmrczAfnvV+d9IGxgFkuvYMvqWBRg @@ -4112,9 +4112,9 @@ Ue541HB2YQhYfjAFdJQfqCB6sLkFIRdiwvK66BYLJUq3ght47kHAHwXYluJVVLWsY4HB4VoECHg6 9TzA76+/aPsGfHnU3IMNLpQ2VvUN7LgnMH6PaRDF54T0ypIuvH7cI+DGDpMnTO3AlaRNOwrc2uy8 GgY234AzOVpiJqNtkFyVgweFPOOcXyGAtFE80oV3StomE5N09fg3mD1kAI64iBZoyzEltqYHqiU1 OWCc20svIvnuA/rBj91kY3fc8PeOD3oFXVSqEgfI7Q3MW1nLYj729GvHAuie1/eAqSJx+smrE4yT -ri5AsqVL97u4vyzVJCrzsviT6QG+D7Nc7UihcZoCC7dO31GzKmJ3tEW5mWEnucHYFQ== - - +ri5AsqVL97u4vyzVJCrzsviT6QG+D7Nc7UihcZoCC7dO31GzKmJ3tEW5mWEnucHYFQ== + + nhvqQlobV2fqlfzf8u0v33IdDH4SqyKclPtUkVhIeChIXnGsglFFzIxiPRPlzG+HSEtQOlqSWLZF EZUBeurZIgWwTJV2cg3Av/QKYDGZoWmbzhw0N4vYX3kvYYFmucOZvXDLbMMocQDGK1wt4xJoxuSw +Vt6aFBmNeRe7HlogZnKf9/xFc0lgFDyZ6KciH3MITj9musR13ZH8iHISmzmqUDKZxaeM08J7pZX @@ -4186,9 +4186,9 @@ Q3giKT0SfzWnO8u8DK4ZqAxtR1FLawtWg8ODlPwToAxTBixDKj5BEKTspGixz5Wp5gJOk8BmiEsG F0akI/4LsO+NBoMe4kBikgVeIkPVGPW2SLjnBtCSKGePSvUhwLdhA8PR9tqD76//+vUf/nMcydhK N+dq+Vcc9YjJ3pKuznSU3VNLN9RWYURXyaI+dowxzp7fX780NEQOLwG5kzE0pGxa3ElkgyugCCDI fZcRDLLrMVhCBWQMR9n1GMUhOyQDCCD1v3xVuaVteHOPJdllCijBPG8FUJOUV+g+NQj+fH5dggtj -jBSkB5DBHdrbDLgA+M+vGZbeomMFZLc4peVh5etC6odPXqZHRBnJqSpTSXqgoLxuxg== - - +jBSkB5DBHdrbDLgA+M+vGZbeomMFZLc4peVh5etC6odPXqZHRBnJqSpTSXqgoLxuxg== + + p2jbDLzU8cqQ2NoDKtnS20U0ppxfGVdcx4DqsBzhmT6mmkUmK1X9LrO4VBdUUAQQJAfD37cdUv/L 19s+zL3NuBm+Vyz9+XW3vHyPQwwbDag4Xncq28X+f5Z058Iy/jezxvwr4K3fwVx1XKi6HQu+kZ9I wMUjYL7DxBJBamCbc7B7rIjxWUWQAG0pRiuXbEq8fQ6SkRZNwzosVHm8ehZaPfl9wLOAt+Ag6/sJ @@ -4260,9 +4260,9 @@ lZkgBYTaLGPg4zJPotS6Zb7xE+pQixtE4fyE1MTFPEOrZzHP8HPT1SyfWy4jnETK4CITVq5O2nZl ydoAixuf6oJeNVNX0Utpajq400/WNfHdyZ2ygLh/TgLQVu7/CuYVWsGeHkG57PZBAPur3IqP5D8V e4vxjiHbnBaX7ciCR2IZ2bPekJgAdil7Jff9nZSgNMLEw6pUtxbABFEtC7+KsURk0tQRz4c3LmKb t+YMrDOI4oJiVgnwJ/yB4fp7YNAy06G47cleTNcjBHyHRzKiw1RAei83o0+9IADOzwAhgHC+Qjq8 -t135V+FU1TGgf18EMEBAXkH8vwEi5AGe7dKWYCOFLEEpv6Zys7f0rRcQvvUA4dmGww== - - +t135V+FU1TGgf18EMEBAXkH8vwEi5AGe7dKWYCOFLEEpv6Zys7f0rRcQvvUA4dmGww== + + u7SFa7z0gODK+m0UIGNAf7kIoHM+XuH7a247evDH19w6OXMzDEx7m6E+WEresYyC2g5nVa4CaGQr Avp7AbFCGENVsIg/wrL//pqbZoHEjE6TOAA29K3En55UK7TxMfxJNigGYAH8jt9HvVjscBO7oEY9 MASrgJEXs1n61A5GisyhQYjF7xf4fBUhEQ7JVQfQ3zdD6bRt5ohtlhTVAUY6GEIkvkNAZBLJoSJt @@ -4334,9 +4334,9 @@ rWZrbuFNhuO4gCN42gVs7hJUr+v67Azhub4z8nYx9vVxqYIbcvx+uUCVcS0Z2viAm6cVwcFq4LPW ItohjI3fIWC5tslD+4Bj/yyu2Ae83LVYfJ6ExWlaegvDHMHitn3gbesBt80vlg8YVB21B0cEVqjn +Wk7+Ljq6xK0cCNXudZntTd38Fq0ElbN+ihXR3i+u5dBfLDI4j9PpA8/WK+e9++vGYaTvYBwxz/g ta/qo5/nQM/84QKm1A1FiYrv/4H3e5zREidQ2iKioEhl9MEDLy+RCu9BfQXGP7zKrQJkHbBbhyQg -yyswAuMT2LtvviEVAiy/5eVhwZrwCSw9IJxLWUEEkZRHDfD7RYC0JQgyAAE1DubZIg== - - +yyswAuMT2LtvviEVAiy/5eVhwZrwCSw9IJxLWUEEkZRHDfD7RYC0JQgyAAE1DubZIg== + + xsKubRVMqc92tyJ6oOxGwd9RBaBt2c728zxk45sFyN5p9khEGiCkQDbJJnkj0jaCiX4H/DTeBPY9 eXNKIwQg1I16kyKwsqnLuUTw7ck4HcM42OTI5mHFqLCnZZSpjlCz+RjPADRRA95jqGQiSgQbUt94 j23LlSoI0YiHKxKB6aMXZLrx11X/ObdripGgUgStCgrU4lWCuqlSsS6sxRgk1cBM7/oHYxnw83NW @@ -4408,9 +4408,9 @@ xu83f3jLmPGZh+PnjYg3TBx/zQUCEW+YQ95yjLzwkUDEX5OXvCM58Twq/P4td8pblpUXRhaI+MDf Sjhm/4x0/yD3uT6wA1HEWy6h67wiJwmVEixAzWMIjcrolF6cKNporUMtKoRNGT7zhtwJIm6nVrA/ tKRUutt5vIi4jyMepofX+ENf5Q9YeBd2MJONhLQL1oDjdC3RwWcybDGctwySsVz1GOeMTrmSLcp2 Ri//YeAFlr/jaiJh9y3HeMnycc9RFgLA0GBg/HykhP/w91541aYA2K+e+2PQokGxN0Iw0rId2y0d -iKIH9gdbl7/1D/GLQQf/Cq4E2y2gDs8drZGcVLnRksXshUctO+G2qsq69ty1AN6QgA== - - +iKIH9gdbl7/1D/GLQQf/Cq4E2y2gDs8drZGcVLnRksXshUctO+G2qsq69ty1AN6QgA== + + OXH5KU8JtzubqoTLCwcYiD33AfsBNjjPF3ARpocn1x4oX41s5A4+uOe+A1rrQcnhIK85Vsv0Ojsa X6CufNqCgS8qHbyy6lFEMBuMl06C8rUtO956SX5xVyYN9MwdiNg7RLStgUTvWvDWIncixgsRbfF3 9S9Kbr1HaY/0xSvIlq3luZ+YmOclIp6bVbQOI9xgu7yxYa1X8luHicL2pruJhLA8HWZUeSH5PjOs @@ -4482,9 +4482,9 @@ KrjjE5W3sMCqNTqx7EHRbS6EC5f10BVWy1He4/ptllkRMXaO+IPPwQFeCV4J3riXX5IqeXlkTeAr JawbJHimyZoV4QfYaie2VVr/lj+0VX6RoL7L372gE5PYH9YsadDPfJfY1A2kiYLq/qBlvsNK0bHw LGsGloSdo9y2FdTYZoGjiGcph4htweOe/SMaw/2yDjd3NHzm1yUSVuetMo7wrUHEsjaQnKNGYuZw VkV7PZHEb8XYt6xqCD70FnTyz3N33yN6iecb6aVb8MEjosSSeJc1LgtZgJD83PXKIiTfcRH5dSnR -+p4MB0LKnpUBXAQp5AuDPQjoGxNzyXVf716s2jnqkQUnNosh8PompRDW4m4sf7jetQ== - - ++p4MB0LKnpUBXAQp5AuDPQjoGxNzyXVf716s2jnqkQUnNosh8PompRDW4m4sf7jetQ== + + xo24gLtcUAc/f2/yh1+XV3DdzxcQi2ASYUrBEldZ+ACtQLHn44yDOeYE6yQsbiaECFZKWLS+b+Qr VTDsXuPYakqqEFYSOxzCR7V02GnW0ON/OW2FJ1XbUdsZeLc833i/9umBDTEL6POvweBx7feb+/5i oXx9rSO3rJ68WL70siDYCFUYXMTgPjmXmEUd9K2XmNqSENUW444JfqZpZvwhDtMdN9EBrj3v5Im5 @@ -4556,9 +4556,9 @@ zbcaRPuxPOMA4d8P3+QQogMZb99gmisrWLMw0gCv1ExeQXGsg0PNK9bgn3UqOYNy4GgeOz3i/aOW 3bHUqECb4n4+WJs8/CTqBi5tpdDMQOOjUvIVOG8auJrE81bIC/r2jV72JKw8ZClKlB+lIO6DE+DO fIm0lDsPrGvFP50jKu7acejaoaK9keWc2wD+Caskj0veVXxk+HMwOZbQ/8JQsvFYri7zXZYkJA7A LOYffuTyV2B80w6rbtsUJvIF1QvkNKhBO4t6BGq/YWHwvfBKH4DxKWs2aL7vB72qFE3vpZ0CrlcG -XH0WBAjMkl6TLj//3uR03PdocJlOJhfTwYMeEiNe6rUwSNtTwbmXEUD69Oxb41vO7g== - - +XH0WBAjMkl6TLj//3uR03PdocJlOJhfTwYMeEiNe6rUwSNtTwbmXEUD69Oxb41vO7g== + + fshhJ3kCIkxn54wXK9P9MuAxLUPFaHJgwx7Y+shQpjzn7U2kpFQgeDeFhTxFydC2HcaEUp2psc6o pzeNQtWbh5JcEw5CH0F7XHcJE/NLpqTI6OzAC2YWJ09VQRfqgvoAXTDBskglU/aYrIOHSZGGM0MW 6RnLQb15uqIijhLMEqeAAim/aI/gmxYRG373SjuXkGVCMdMcfNeWIn34AXSAvv5wZsIGjXLlhb55 @@ -4630,9 +4630,9 @@ IfeMtfXwr6fJCl+eAPDATjNzrY8f/NOffY+frkVqVr36S/9jK9NQMtdJ48c7y9/nU/wPviw/PQ36 2oHuIQWLxA0muK3m3iUmOpbYsVEcZ/qfhgk0qAKqcbq4JqUFedlp0pp3Vk/4tcPZ1B0l5T74QJHb 4FYtkpRhR6zDzcmI8m1xDDlu0G0E7rBPlsdq4WMyelIO1BBIgfrfJ5UQqL6VjV7AiaEgQOyvZsrM jCU63IeU50fyCotv+b7S2ZlAI7sr3i214cDudPnzTx955R+8eq/PcOUPH/uFzbZcvKCVSpn9UAV0 -z+5B+33A7Z30GHXwsF8Xw7Ltnj4A6zHQ2BQXG9JPaithZ6UbUknpnvDb2upWSLo1tw== - - +z+5B+33A7Z30GHXwsF8Xw7Ltnj4A6zHQ2BQXG9JPaithZ6UbUknpnvDb2upWSLo1tw== + + xbkbdRSdUhD+HrIX63voiJTS+CqnqPOQbrHHAtSwxRRjGQViHq6FZE/txyEE9kpU3Qf5SCcTuH9L +oj37/s7foixFd1YkvXlzV/y0531pFfWqnLF2BtYX43VUsW+nB1sg2wbyNK/5Qw+Z1HAzP2T0fzs 6G4tqpz80i6pCcw61pSi0cu2kVxhxGV0eYvXu7Z6g/ccoDiFHSKHLKfAj/XMAmvtc1YOl7hcLebj @@ -4704,9 +4704,9 @@ OzYP5yebfLx3b25fd3VzrA+zPriIxespijM0epIIX4avhbf9Vh82ppGRZXijXjdozZoaJzc402yO ynlOF3jhWUaFEgXYDCtpqKKuDVd2RZua8SLI2B66tHK+1kiJ3c339w9XAXcyxHE9ZNiyX+G1bnRc LJmkraEHiB41ZZJZmIojItysCddCqbP1QJjhH7vSSwwUY7/ovjdZFie4Uqq2LEvXXPPEviKUmThu CsFT4D38NeCF0lEA56fXddpbrjMMvs1PfCRM3g+04kRKG9dR1fTmSkBuqGWlTjiTW/LZJwt6+Ppq -1IzzRtY2YvNg7g2NvmqvO8mKc9gA7jlgrw0G1eR3BXJkJd6SzM7VaC8ugpnjJOmy3g== - - +1IzzRtY2YvNg7g2NvmqvO8mKc9gA7jlgrw0G1eR3BXJkJd6SzM7VaC8ugpnjJOmy3g== + + y7WYmFgCJ0xaTDDuebS0FX0bm9PBcW1Zv2MzJ+PVbB7NO36dPJX+sxfy4b4ZY/vVIZjWalifRlCB 6Yp3SYxznUM2/NDMBz2Vz7CeQ+cO5cfO04usvCboqZiy3pgPcCpRZI5Mi2vJT5t9ZXljYZomb443 ynZdd3J7uyhorspJZn7z++X0/vEq4/IDBQ8/UfVU8Yua+Tlr3LGRJBa+xixenqFZiqUR28gQJQjW @@ -4778,9 +4778,9 @@ wSI8HCB9ufBYYo7CuovsnHEwGCmwfsQl4DRO7ltUd2adx1NelE/ZzDCLWq1WyxuV0cGBRUy74v3r XsrxNkY4ndzJSmjT3F7zedYpIzXCawXK0knDQK1Yg0Lv2nkzd2tKrYK6g290KCSuIfpZWcFmrKTe eHkkXKyVKfccEAWjG2k7Cx8p9Abphr2RsDs4vrWIKs34kVT3lCi4hVfi/I+zRHgSU6ZmUnBkh5Do e19Wf9AMM1GXcxTI1KgmynGOnVwt2iAG2C6G/2Dmmci48T3yMML9RuPi8XDZLw1RgsmDWY+N3WMT -lOiSUhqMLWuPMYwcV6cRLz47wK2IcMOoB7g6U1OtEcISovOvIXab3Vx646iLmqeObQ== - - +lOiSUhqMLWuPMYwcV6cRLz47wK2IcMOoB7g6U1OtEcISovOvIXab3Vx646iLmqeObQ== + + UyP6Rs7q2nIvV0iJx35ue/S1mSgWDddKHQCF1whIN8e7TQcQWqP7W+bdHIMKbWZs5Jy0OFsVd+re RUenC1mWjwOI+ODVQTOFV9UZFAEn1/sYgcm3URYYD42JnyYvh+yV+yaWqSQH1VZwl5sCh/tl6yhy u0bXRJameAt2NWscx9a4FrwYgG6uPiKeIiYXsxkqVE1jUe5ZBXqrW8duGlKTw1R2m1FHeFJn3dqv @@ -4852,9 +4852,9 @@ zb+Mq9Ft8G7g+G1H6ZR0N+eGIYKFrVrHqkjB+dp5r4x3Kanc7ZXR+ITwQO4qnmi+FynF1YJw+dqL /VXgMVw3BnvgHoaGUoT8VCs5fyYgQa5oW6VIEs9GGOncC33GEDXungdAh+Ob4Lge59g7SJ9TPYew dwSB+W3NkBVveMfmQgCr4jmgtogFcwRI4cykaMxe+oDGo4ztLaYyRFo8kuQOzSpa41EDb0jXq/oR f4Fzekt80PNMqk+6NgdSDsvnzsgKi4f4dioQ8WXU4nEP1z4nGpaFbyy0uRZY3rCWQdkS/Lunijbb -ltk/hSSCQAJyE+s7MrHUCA54F3OEZ3XjBTzn3uGoEnR0r+5wooPGbYHZ2EKZrCMYZQ== - - +ltk/hSSCQAJyE+s7MrHUCA54F3OEZ3XjBTzn3uGoEnR0r+5wooPGbYHZ2EKZrCMYZQ== + + FPLM8L0rndF97BzC2M0PZ1vH0UUiw1SgNc6sRiVTsyd7TUqkLpxWcd4NTKUcOfBaSCAVSgWhagLe fSCO1t9fHjIXk2HV360Ox+PCvG9RMiBtuH+l+LymWCbvV9o5hQ4dpd23fDFW/kne9bynbuAXHiR0 t/DlDqadZP86F9P7mboasyp6CDzWhQvkcHabVPUGvtwzf26v7vTiAd45WWmMAz4VHtgUs8pGlUQf @@ -4926,9 +4926,9 @@ OaiMdIqolrpnbz/2mzsTxenEmr4E+qIYWTU2drBisGOIDB9bf++SMa9x9j8up3z74dQnzfOOCkSH 61+hYwNWwOv1FFPvO7es/a58ETNs2x94laxFexZYCB6xs+bBoTvO/SdYCIOOvTpnCACPQ0FKeqeZ WnIjNtsWEVEcCPrutpEQEu1nOMSKaK4cuNUy+c4wvYR5uZvVFW3MY6X7jHLdTn1eeSrWeNDn3cOU VjGlsQXggXvmqmBoDPlnesxpuWZ4hvOgyyzaMAs5H3wGHZttWp0c0qiC12FEVnUGYT6+x/QFM1YV -lnGpstHqqtYQrEXuI/gHUNY6C6+2egk2ch+kVs86h62Tomi/rVFuftCr9P2guZ9Xuw== - - +lnGpstHqqtYQrEXuI/gHUNY6C6+2egk2ch+kVs86h62Tomi/rVFuftCr9P2guZ9Xuw== + + Uph2FD51sedtMOGm7sGmvc/OvgwYTnauVWE+3CET2Geitxd2cbp2kO8hm5+L0BL3kBzklBYXyty1 Rw5vTycVaLKvEodO9NkRMfV3W0fETkgU1bPgd+YRLM57YMSPog6Gu2z3LXJDmE20wMjBO7mp2MaW rPDEIRc/RNTMarrLB2NUNK6x26whlDWoIbxgXnXj2xNSF2+hKI31KoJjWS1drd8b6dD7P+RUXz5r @@ -5000,9 +5000,9 @@ XxtP322n4dyuZzRCEzOQiHv6W53Ns8TPHnxw6jxbvNfUMAtZOqlSalr8w+ByNimcikQUpRCymBkv h8+9Pn/Xk3VbFRzV8/QAF4Aj+Ng1h5hTOhNBtVU0+W40BqMxFUxfrnWLAZLx6Faj5LscZ/9YKAbH Sq5InDpkGI1+lLt220gVp8BonjQEfrenuPzO6jwb7nDQYQcVGiNgq/FoQuLcNM+0aEOgqeSCf8ml //zK0SerZQ2Y9l4vnJXtM9wH+Mfm7+dzCd6tRiyT1HQHr7/5h38uU3CibOy0T3v4rb7wIxTDKNU8 -AkSZEuWC7IPBw/+W9tiFwWrOAf9BctIQAzX1CM6kxoBSRYLOq1Hd8rk88rV2JamCEA== - - +AkSZEuWC7IPBw/+W9tiFwWrOAf9BctIQAzX1CM6kxoBSRYLOq1Hd8rk88rV2JamCEA== + + +rCgBWKMVJ0qwWl9Zqe20+vuyU4eZw3MaLGEFxYo8iPJzZYRzXnOFEx7Wbl8SqA40VDW/u8zFoYG oJnYOpo/QZbOQ8r+5WzRUE7YIqOm+4V3VV3J0Oe8x6wqhEJEzofA7yi+Ohzo+OC7mCl58v9k+w+/ aHttLoqDr08iJM1eACRjpgnPI+ZvU4GofBqcIv0dXdM/4/Rlz0jR21zoeeDTSW01i30Xq9JMgBZg @@ -5074,9 +5074,9 @@ YC4h/WD+2BJEzODzhRwrD8xfhPvXF+dkCeTmE+TkHlAVuZkKuTkNOfkPcrDKzZYoyqvIzcGgp8jN gvOWwMi3PJ3oHgRi+Vty7o7JZodCWFRLVRURCcKHiq8Dq6BtKfSVLQeFREOaNCsy6SJ8IB+J6GrR 34PMPCJmC12d9+sRmJiiDHBy0FVYZDOFtiJjhxMfCfhCEE7YWXLctqqjikARQsrmUYopTX6OeNmB SN0B4xUDUQA5S1PZ4rxpvby5xMkOJ13xAvuKbRPuF3C17OsCYn+DCspWowS2P84WhfUR9yyYnCyq -VdQKaeHfeF5gj16dajTv1LdLUldxWmCxC9zmolMm/UEAlLfOwMBLh57g+MHTxn0XOg== - - +VdQKaeHfeF5gj16dajTv1LdLUldxWmCxC9zmolMm/UEAlLfOwMBLh57g+MHTxn0XOg== + + QisBJwCOXMNIIUp+SHeNbAH8wHofMSLNYTHmACBWsZyaxInsqysDurKUI2EeKe+FCt4PcvFE5AhO QbIrYHaLUhZg/hnmBglAHlFHhDbxqDTGYrUjBbEA/EM4CZKEd6gXKcVUhMa3bXPWgCUMVRAvIfF4 2qWYDMWNdKTeksd19amN0G04hB3K3ChlhJUmAhJFYpiv1DWGojW8BUtRKqr+ChW/LQi/coABPABO @@ -5148,9 +5148,9 @@ WWJLW2ku5CQGYbFNB0rHlvDEigUIHELMfqttRTeizMgiy9KFRcmL03YoAHF9Twh02WIFLD5LYKft W/CR+io9na1hFxCrYlCL3QzAZUrUz1jZcLUtYQo0ubjeQNiKJfULnsIWexx9NmYVYn47Cigtoplg 6gfCKYQvDAtNhgtXmCgUQS4V2rHnShWe8/3tgKsDdTWdLbDeQBEiC+mBbNbpE0vyhfSyPt+4gM8R SkI5CbmxWmzS5ybx10TmKQsSja0oI5oIvnC2DNKnN88yjoty1gPOTt9mMlk5FYI315dEdvMM6Znq -eHLi9CxKc4zobEqxCw9FRUX8MtRUD9nyxqpc1Ob0adizBeNinJs9CJX4Oads5HiskQ== - - +eHLi9CxKc4zobEqxCw9FRUX8MtRUD9nyxqpc1Ob0adizBeNinJs9CJX4Oads5HiskQ== + + OpF7NqXqpc7unuJBzpz0wUFOMUrDLwDOcTqyGB4EKAy8HH8DeM1JhFL5JqAochh7Ij4McKS7QkJg ejzgC07J1v4RiKU4opsrnhQoDDx2r5h+FwjJWI4AktlL49mUzZjy50AhF5m+H0/JeRt+Io9T/FIe JSjkFN20/wm/EK+uLLweU+ul/FrpK4204jwfdLZuLyVlSPXb9AVzXxj39IhTLv3YHnPBqwq4jVqb @@ -5222,9 +5222,9 @@ lRlV+IyEt4ycRE9B2O1MWmMxWp3PEGlsO582sIpYcPTpZhSfIH1JWEX5B2Uo4ZHWZtCXExFiQx9d kbwoEHiyHfmCfTNi2C4+NYODEYtHhQGJJCL4TQ66+QBnn3ic+Bk8QVmzbBig39hMLWpFruND4H3a 8RGSlohnK1469EPIQ4uSCHotBMVn5maRg4LxhOiLKDEdKrJklHwf/jmNlvYDVYXGVYcahZ1qiOmM VC71TCs140Ua8miCI/1TQilDcnkYDcKAQeynm47hBXlu3HN0FeyAM7o1XQW/gOKGmFE9FSPhkaJD -PSzVjKPKlZhMYDuujD9PojcRid1kRquOyRhjGwNAUiizAMNFkSODTUf/WA40NTIzNQ== - - +PSzVjKPKlZhMYDuujD9PojcRid1kRquOyRhjGwNAUiizAMNFkSODTUf/WA40NTIzNQ== + + eBL/STejOKal4oOCHtTxu+Soq7CGjBwIWbyUUImBoBI9JlN0SVq1zKjCUrkctmK6sXxegcShqEOM meyM4i90EJUjlWkcI8c004jHTAtzw9Pp5VeHgY1Frio0ZJXYScsRvnvVel/0K/WajCFuOy5ewDEg LsBHRwfEmWnD2BiKmlG0/Oowv0AjdSDeIuZvIw8L4QMxF0rGFgI01UZjxml9ApEzFlOTOwWcTebY @@ -5296,9 +5296,9 @@ cE3D+r5hX1w3fOnGb6lhX66Y1IxLL+45H+cxfw5uXjWjt1qL6t774uZk4n27dnYrXc8/nfNfZ2Xv 580hc67lX5o5H/3mitbde5U1MQZQ48S2xdF9Yueaud3RbP9TZ57jumUHt723ZEIZ3uz6+17bntzr xK41D3fTq+F5YWltJ2Ns12rRs1/fTtfrTaek1yNrvoGdvnL/J0uH4kLg9H54zc4TlanP4a8/eG5y F4vvBQ9y6POXxzbRHXZV0+aNwvT56MKmtw4a0q/TtXp81B+ZrPZQ3dGtr01C2yO4bV7RvSqP7Nzw -/KTOyXbQYMJr0IfJC/5g0aBAteualh3b3xinjqa/K+06eOTd/VprG+Pizg/+FSf0yQ== - - +/KTOyXbQYMJr0IfJC/5g0aBAteualh3b3xinjqa/K+06eOTd/VprG+Pizg/+FSf0yQ== + + Pe893A2mmNVj9ptfH8vcq/Lozg3Pjr/lwkLD+15Fi6fyyNerHy4XW/4/49Y9ene9sVaqYV77waPH 39PH8Id7/Z9YvxdG+P6NT1XApP3jLfe/8sWh7L0qj+x474kh9ZKD0itbjvA0eW16D1mXL2/Ve2BF twaprfOSlv3G3D9hePe6um8bjV+Bvz60adnQa6GgzpBF63dnOzH5/otVM/s26zRelsqTsMt24ZXt @@ -5370,9 +5370,9 @@ oK1GHrWY+uJz46/FP612/brkp/TYnW5X467hg+98+vpd/I+w823ts1g6umrwcDXlBryxZ/86+UXy k165+U03jR0viMVGC7dVVn40VH3VqHenvJt0euCB9vxnj5UHKys/Gaa+crv2zKHhqNFnzpwu/Pft q49VVn46XH/ZoncRAC/5dJ/36O38Z8+/Hqms3HS3/q75wD45q133R5dN5AHR9Ok9lZWf3aO/az1q RE6GXJfHVszvxH+P+ayy8otR+rtOD0xuW/yLdvNXLRvAf/d773jl11P0d30XPoyIu1+lflFn4sq/ -zmc0xw1L91UeXKagjY1mvbqkF/xxTjqRoPeydW9Orkd/37el8uQ7feWbga99/Cr+4w== - - +zmc0xw1L91UeXKagjY1mvbqkF/xxTjqRoPeydW9Orkd/37el8uQ7feWbga99/Cr+4w== + + TzVSv2j00NpPn7+D/h7wQdK94/mLNs9u3bsGH/hCPekx02To6q8+fIjSH1qtOFL57TPUPw3nfHbi xPrB8OfF2of9n5ATf+vyHdtfvpUKFu6vPLaG3k+fvx6qrFyH96ipN7r/gHSFhou27Xt3IP679Sp4 68Pw79FJVx9bjYv2ZUYwA7fiCZ8f/Ije2+hPKysrt02CP5s++21l5bdPY8Te1Viw3+HKN2rTsa33 @@ -5444,9 +5444,9 @@ fB1ZROLFVXcnH5zv6dALZEVZ7EARMwNCO5YkBVmeym+wRag7Wf9QXbuEwzQue3z5hIexI3wrgU0n zNKz0sWQpUZJZBCbYcdO8irYIgGfuCc5ezib5AGCxGqnh1XbWbKQOTGnM8aQ9USFEZ2cwV1kyXbo y3kc3GXkrYI63YD128X3gHX67KoxBoArOReezkHzwHNGAtGhks72PNniJW9SclREpzvQ27knPnMP Tin0ezhL4+II36rNCI8ZIc9ulc6iLFXw39hcpcdLQ7KThCrJB/wJ2FWQLwTHR+oAXnDgV5J0YquE -Q5+8WmLOsAWf3DSWJB+wEVwewLjXlrCoO3k2LVJaJoMKkllwHUqKA/YnwOpLMcGktw== - - +Q5+8WmLOsAWf3DSWJB+wEVwewLjXlrCoO3k2LVJaJoMKkllwHUqKA/YnwOpLMcGktw== + + LU9J2HvkGoTEG9ijJfzn2/IEmG3DtZJLJHlayVaDsCNlq3lsa8sTsO0AR1HfVoMwkkK1NBRFQMuq kcviWH+BdBUrTAYdaLGDdxWcVslmDEel5NlggfUkVwQFl4PkTAE+T0cpQCfDK9lB7RoY0klmKhzs k46Ah4XEIIqWJZPEddi8tuC8d5oa0Kd6rv/dySvV6Nr//2SvBJYkpIQeJ6QkCzXk5eRkr+RcDN/R @@ -5518,9 +5518,9 @@ qQ2a5MnOzl74uYer42a87+41cFJyRcDdWeK9NhGbPudApyD/Ur1AJ0hy4XQ0GGXXqxTWTGBWdjZi gnxFngN5BTiq7Lo231LwayysW0DKHrqV+nfnkDuTFkrHI8uZFD3ryZnUDsCS0bEzqazMnEnZC/Rv 56HQVdM+Qp1Jsz4DO6/SyWfE8QW2lM+1cOjwyePzPMr6DMpTPubkosnTvQX5vRjzDNkYdWqRXu5N q5jfX7bYv3jsbKdowUpPIOnjxnofZxD6+OOKfD/lG9dtDXtco06a7oWR8dbYPG60ixLnnNPscVs7 -QfPG9c6IEDx6mj+M5enz0mu9/malngy8E5yMgNzTg35hw9W10a1r9YySCvHa1JmLKg== - - +QfPG9c6IEDx6mj+M5enz0mu9/malngy8E5yMgNzTg35hw9W10a1r9YySCvHa1JmLKg== + + S72PZixdwHxXR4/ygC2vqV00L6NakVa7mqhrrN1UbWbkO5xQXYeOieM8OemMTS2n5zjnTtqQbMaK enh7WCsKZAzQ/I0rJxWdNH+ZHMEZDed9fHU2hKKilZ+89GOLi4rWXHRZGB06yzw0tDdstItOWbS2 UhQs/PhVn/UJNlh98R13XVpXtOOur2D8xfJlisuxk+rPgPGftXmD6PuKz9xy1aZcEM559/5g3wM3 @@ -5592,9 +5592,9 @@ geuv5dbAnc8Ke8WLt6PjyrH9OYTUE9w88sGfX3njle9RVuLK655+/h4WA2jnffeIVK8/FxBYYuxR ch6mnvQYWN57lkdBuejnb7z49Y/XFm2592dP76LBPF8G7vjlhfDnZOmRlHjcayV8kadfvuzF//7n jWcevmPfn9756w8p7+oXZFCI338R/pxVJaZV47e9NtE372PWkNoH0Rj933ffRBq9ugcZYsu3ZcSO t/dFiuaFNwlZteg2b+yLD35yPhZ+8lmPtfa9n3waKHqPp9ob37n8is/E5wo0zv+Z17b714eB9I17 -M4I2vf30Ddc++orXiPTmz/ZeE5W52KMPZ1T/y6PXXL8vK/TL+39+Pcs499q+S6T/VA== - - +M4I2vf30Ddc++orXiPTmz/ZeE5W52KMPZ1T/y6PXXL8vK/TL+39+Pcs499q+S6T/VA== + + 0YIvPZdhL333z693bod76d5ml6WK1tzd5Sggf/3+RZUeCEXbH+/IRJ37+c9ffvj5TAPW0queKjBB Mvv848WHL822ANbc8GyhpuEP3vr947vacqMqrL7yO7//e+dhc/7zzktPf/um9qU57+OApHZ977nX 3u7A6g+c9dovvrv7/K1L/N5nvBn71J2P/N9zL//9Pd/4Fv/++8s/3HNBtMMcugCkefuFezKDW/z8 @@ -5666,9 +5666,9 @@ sjCRrGtLhnZGkp76kh4IG10O63a2NiRi/G92n4qXlKyNNJQuD0VjU4qVQDn69O0obi/GgLUwHegq VscOgN6bY9n3xsStsczgsLC7DzBTjcnugEE7Jr8w1mE9fEB16V8ngFflVNt7Wcx7VUzVYfnBu2IF evQe/Rz99OTjdf491H3p0acbzs6Husv+nwPkyX3o0TzgiBwSHA9UD3t5v71yvgcfxwOPiKf/vd1v rz69M769e/NHnWL6IWPUCSIeFPrCt0+vfvzbu39f/u2HX17e14MsoemL6cFArZuICCwG9Os9EL79 -ew/q3+cY+A7ocyz7HkPf/n0G9ccKAwhliWme0Twg2Hlx6SYirPPHDuwzeGDf4kF9hw== - - +ew/q3+cY+A7ocyz7HkPf/n0G9ccKAwhliWme0Twg2Hlx6SYirPPHDuwzeGDf4kF9hw== + + DOo79Ji+w47tdxx9B/MvlEA5PC0e2BdQhhcBgkTTF8eeYCfxAsg9RWRwv+GD+40o7j9ySP9RQ/qP Hjrg+GEDTjgOvgPHii/8CYXwCOoMZ8gOOabv4IEIkKHpj2P3sCPUXLwQnV4Sly4hMoYhMnb4wBNH DDxpxKBTRg46ddSgcaOPGX/8MRPGHHsa+8IP+BMK4dHJIwedOJwhKzAdytAEvnVx7AGCXtQAGowU @@ -5740,9 +5740,9 @@ eHP7xVfv/spXvwGkePyHT/yfL4h33n33X++99/7777/3zzdefPL+K85cZY0b7gHVu9/g4yfPXpO4 cuqYwZJHAdSwU/QVrZd95Ye/+cs/3/u3hNBRqpb/vP/26y987/ZPRxaWjnV5lIOK/797n3jxr+9+ 0CEEF8MP/vnnXz+25zMtS5WThmSBqolfft+Tv/vru/8uCBKAeueN3/7w7ku3VWseHkVQpxo1CQT1 5r8KBfXvd//64hP3/L/4Cv2UYVLMdBfUm7978r7Pt9WaAZfduwnqX2/+/v+++oVkne1h9+6C+tsf -c9i9e6B82b27oHzYvVug/Nm9u6B82L17oCS7L5nhsnt3Qb3zxm8Yu3tEcjdBIbv/6A== - - +c9i9e6B82b27oHzYvVug/Nm9u6B82L17oCS7L5nhsnt3Qb3zxm8Yu3tEcjdBIbv/6A== + + HhDJHnbvPihg98sTNcapPQf15u9+fP8VbSs9M6e7oNjMuTLlnTndBpU7c7oJym/mdBtU7szhUpRA FSpFARTMnF9kzRwpkEm2izWisw/MnNde+N5tFzZ6Zo5cce750W9hxcF1q5DPB//6x2sv7Lvj4ubF M04c4gWlLd926Zcf++Wrf/snrMeFfN595+03X37u0TsublkCaw6fObg6n6wsbblo9yPPvvjqX/76 @@ -5814,9 +5814,9 @@ CGzmUH57UUgzCT38DDuzLsspT93CNd4ysgpt4l0hTXgxKFx0/YZNZZ2JQxAAQkaahpizoOTohsMx QOazLJ7Jnklh6pXO87w7pEcSVFNR+eUcx1I4DTETvMqkEQo24UmJ9GY0xB7wZQJ+2rrCNV5LjAH0 xrJs7patMZ+/DKxAteKp1T0UCJLKm0UBGHAhNgAWIBAk1mBqEkl003AcT2GYq+egHTuZdfF6l02K hwvVU+jtgVuMzSJpEapG05LRGySYyvVrMTLARjpQqFLq12xRM3ApVFSuSlsGuzBm4loezC70ChNP -sSm83bExxWKjCJIvGNSF2g/6FRN8QRh5m48CsDrsSzQqtiySRlDI/flN3NdxANCAzQ== - - +sSm83bExxWKjCJIvGNSF2g/6FRN8QRh5m48CsDrsSzQqtiySRlDI/flN3NdxANCAzQ== + + 9i0oZA2JAAhttr+COaPxHQ5S02adMuT0hAmsW0x/FYViWefKsrcudMqgXRgUBoMGL4RVntc0gLup BxouSSq/fOFYhs7HiysWQEKLTyS3EL2dLbGmeYqBDx1yHtZgVeUXC9gVvFK2lTQsLegpFHoNcLGT WVdVhYTzwPQUett3ixEB0xBKFIeKdNVpk+j2QBSGxR5Xp8XHUxfGgKS8aclxxe0KLKW8EJGu5AD4 @@ -5888,9 +5888,9 @@ s6mkZWtjeAFTlCWAzhkLZVsomsx4S2hspntCCiI5o0oDqAWHZnk9VMvS0gg77Tv0C9KB20DUNDWl Imm8QNDiI6MSqXSItsPpZCgchkmZX1gtTzRGm6LhkFu10BlUGpR82ZRKcx5jzLw1nm7jp6v8cDIW bS2Q5z6EVXoV84OhKa1z8y1eamWrEv7UYc0y0TjEPWv5oVS+XbdkYjOgBwrfd39oR56HBbOYR5nl IDJLl9TDDgngR/UjybM0KOxrUt9Uhb6Jp8mq5TlkLtMU2zFwhTdwYLt1y6Pbu/kjau96ZLEA3oQI -emytjDx4j8fAyasJW4NFo/9hDnrOEU5lS6wyRyjzX4tCsVgkubOMqvoK5EWgzEfSIA== - - +emytjDx4j8fAyasJW4NFo/9hDnrOEU5lS6wyRyjzX4tCsVgkubOMqvoK5EWgzEfSIA== + + uyMB2HQ0JOKghxfuZ6p15yDHWl9dPe3syugcnZ3hTIO/Z050/z5tVlPrxHr37/GZZzzdodGqdDh3 J1Y4jRY0NTESJSNpQK0rJ13dJFD7kslNLgFKrblryqa6f9fNKYltrPYQrOcEqkymclf2wglE+ydY 0tPpSHNzlHXkYBIIOWSVS4BJsyJrtK3ev+F5q/v3hE4J9D91yLYikogfLj61h0QdwwUcBbc8XOdO @@ -5962,9 +5962,9 @@ CCPKwsRh6TmyhIUWAFnTgYDwCmZWtxJleCWX4avyyXBWtYbL47p8wjuj1mpfqc2qkBSYUU/iusIr rjMEDdVeJEJgYXRekjwdyRp6Ca8wB8qT9BJbYLNfUrM6VZO16BUqnBfU1hVKcKpcGMWpbqckz6zm T3OqUzDRqXpXqU5vdYnsvO/ZdAcSNkaaovEoLJg8NnPVwrKtiYZEW5polcnwSxMNgRp65KF7J7NO 0meGu+eYUbhWofq/rUFPN7MYRpWJOOCFUqk2EYuGudQoyT0o9INAiyVKnXiaS0EXsQJhIGOBlrWz -yy9S43jvOeoZNZdDMt8pSBdQOqDW6mSorU2sSR2RlRNiSTwca8+ma0fvCcedzmtWRQ== - - +yy9S43jvOeoZNZdDMt8pSBdQOqDW6mSorU2sSR2RlRNiSTwca8+ma0fvCcedzmtWRQ== + + UixXdxbwPL3vWFPN006nunAB7+XXurs3wktg05KONkUjyc5JlIczu8HjHmJnqK9+Tas0/rQ7KQ8n Ew2hdHVoJ8wv+Zofb9J7FbFIpBHP2wutW8FO6DukhQcwc6UrDPAq15zD1KS8kF1lielKndOGrz+r PQpxoZ1anWjrHFUpoz3SIG9lJv+qEjvidK6SLQyMDl9enogn3HeXtMImt7wBVCKuh2p5xLZfwzkv @@ -6036,9 +6036,9 @@ NLFhKcHGMmpvxWblKfvyCUJmP1d5aJ4dF06ffbEoTlBOk/trl2RzSNlSrmqlw9IFT/Ruw6NojOwl 8QGIoc8DT5a2AGHV6/Lz84ngA09xez0b/ynXjj4ukL/qTlS5sxuFl7d2GX0MBrWhiDaeWO7luhNB gF4utj621zd/ysDC1rTKTbt1w4xVUBbmgYa6L9vqkLusFV4PJOBj8dTHre9L2uvaVYk//xqkN/Zu bPXsVv8oVBoFVT99AWFUey/sXxYPXA0Aqizc4sIfFL+ONmWH1uczV7NtQ81ztvMEdoegcbK8DiLy -ePXDXKad7PbF/tUbcJCXO0BS8SuWQIduiW1i8/cLCO0lvv271e46Ol3+K2itnxeb2g== - - +ePXDXKad7PbF/tUbcJCXO0BS8SuWQIduiW1i8/cLCO0lvv271e46Ol3+K2itnxeb2g== + + CLmq/YOkVktUVkQG+Bv7YoLbva2tWzsjlvef7PIccp+Pm0tnG/31zPV6Rn+9W/gp7+89f+xs3EmC bakZQzpJvhWObzfvCmd/jT9DUVNOuEq7vckXP987H/b+y4ZWOPvczheO9BetdJC7BcGUfJS8CHuT QdLMEF6KzUpu8hH+hsvb6xsfDcD9LU1ZnM8n9Pff5im1K5/QtOkSj3FluLQbN5t90gtH5zvVwmlv @@ -6110,9 +6110,9 @@ scRhpxlPp0cbyd+HytU2dLrRd3WaXu1dZ4xOP/QVu1Pgydht4vl2nopyoXjN7zoZxClXObytYadZ r0w9zC5+i2vH0Glp6AZvpfKeI53iuiQrGRcrXO6kDa4kLq6W9p2ssJve0A5vsdO8t1MlMb9xvbMD ne7F7U4xdQ81KaF49ErnurV6knMB+L23UfmgnW6d1+tO8MLCvr/2iEwFFeq4xD4Vhl9xYfW7ZWgX 3ud/S3Gx8/Xj/1RKAdFsyt2gp31AhoM3+6mTW0rXx1xl/ahCn3t0gZsNrr4tCuSpl8HfbHH10y3J -7ynB5JsCV+/sK0Ffl7iD+KUW9LTCHbV3T4OePnJnpY+hATHv89sMd3axEA96muMa2w== - - +7ynB5JsCV+/sK0Ffl7iD+KUW9LTCHbV3T4OePnJnpY+hATHv89sMd3axEA96muMa2w== + + B8mgpzJ3Hv/N2U9d8iXO9f/iqvHcy6l2uIvz+AZ96iYz6XaPu3jJbvk9JRC7rXOXi3oh6OtD7lKp lIKeHnM3C+p90NN37v7qZsWEmOf5ncrdvz9ngp7q3MP5mhj0dJt7VB51+6kLxx77fG5lXw74upnk 9SfhIOBpa4EvLj1UAyHWOuP3T+b3Ar5u9/jDD+Et4GknxV+/7y/5P5Ufvhtr68ObIIgJg+P4cmrv @@ -6184,9 +6184,9 @@ L2eXkXo5m4zUu9+ZZKTy89mZZKRCOzPISMVWZpGRiu3MIiMV89eiHQPtn73mXDDbvvbbFR0dseQm w8e+J7gP6ywiDDrVPBoZRk2Fc0qxwGydKVPhnN5RzF/7F6lwoefAzywVLtJO4tSpcKxd6Q0kmVUq HNPLWMfUj5cKF4tyYslkqXCMYkis10DVsDUIsc/GOBGeSuRr94HC0+XVfbhPQvTsvkWMqsLGfsO3 fxj3sekbD3AgY2PDCOZaJB3m2n3I8ISbCzSFzbuB43OaVtjpvMjM8yEiL0A4BJ6mBYNynfU9Xl6d -IRzYnPciOdvDpz/2svDk6aJKbgfHu8Hr8ayWfYyv7K/x8Uz59DKeuXg4i2ceO434Sg== - - +IRzYnPciOdvDpz/2svDk6aJKbgfHu8Hr8ayWfYyv7K/x8Uz59DKeuXg4i2ceO434Sg== + + o6Dgr2N8rxTP7j/KaCVdfaiGONrofbBDNvdanMluyZBkt+M8x8LYzDoz7uIcLC/22AtQncluydbi 6UdA3lnqLuy6uIesU+67kt2KylFAp8qCIy3Knez2EJphV4vLfnM17kKu9a+tTt25WCE3t63H7505 Vq4UsJPtU6ZTV7Lb2uf5YUCn8uvK9uXKT1CGnXR9HZbs9sIFdspV73eCM+wSH/mLVnCGXTOk0xq3 @@ -6258,9 +6258,9 @@ mDWKdcloALjAsNL++NWxF3mXK3z16oPC/uXlPXCBoW4MdFNN2Q/YGWxupJkHzcXShvmglLUfCMWb /Q8enfKkKG6dx6F4vG23/UhURKirZvCVFdCxu0XCTZARasBL6xqwoyNY2OOjPHqWM0RW/i5CxTlp doUuTv74VswfnH2I8HUDwL+wvoBP09BB7ovLX9dtwDyZvTzBwis32XK+ub60+vK9fF5dr0jvrKZk sNTa1QlruJrWqyl967rJMkNa9GsvFtyiyVdJi6k97UTXatXt5W6jvNsxLqeEWV3xJv42hHQ5k/ir -Jnd2d4XU5+MCQS94pSnFEtbUmyx6tY6yCKIMgFX9huJ5niA+/Lri+FZ9NwW/bnmq8w== - - +Jnd2d4XU5+MCQS94pSnFEtbUmyx6tY6yCKIMgFX9huJ5niA+/Lri+FZ9NwW/bnmq8w== + + 5lsPwqa+K8BatZoi+eWUeyVnBgRgEUv2FlWOS/bZeLr2W6cEnpu/BFsMGeUVXqNbiWcL4o6ddM9Z KffGkDeuKZHCcheSBFUMowKI3Xil+Yv0ed2HiUtJLj9M5qD4CNzSBOvOMgZv/iKdpw06xzs2GTq/ 7uWw7WVheTt+X31M3e6jwpMhx86AvbS+m3+7GuaoH+Yts5omSh7QX2WPzX+xnZLi1sXhPl0I6w8+ @@ -6332,9 +6332,9 @@ KUoMf5AM/iAASUjIHzQcngQrxetEp4ZRwbcsf+AkXiY1Bn9QNYW8YfIHWQaKk2z+AMBQNZ60iTVQ BsNQVMJSFIsZEN3MrpBgBZmPJLuKVCigTJoV13QmsLKkSlXsCQALUTSNKdssxKhhWQhTRWCHnEmX eMq0wASkKgpyUFIjyETYoDhHtoiyV9ElRA1kGbwokipNh8ahApRbwlRsHiI4eIhg8xBG5NPZAx2h 7oKT/SKTFTi0RGRU3VSqj+DkFERe3i4zk9Xck7VGgQV7FKQEklng6DPgCBavAkIQ7AqGV+keXmXX -cCDl8FswMJFVyYJOeAJMSaKmuAacCntEAaIjJSuEXmEZsQicTKYUpaq0LBMCFynJ6w== - - +cCDl8FswMJFVyYJOeAJMSaKmuAacCntEAaIjJSuEXmEZsQicTKYUpaq0LBMCFynJ6w== + + Bm7X2RogQ5mZFFNjTMyssYaJVp9uz43hb7qHv+kWfwOSVebMNjXexeB4i8EZIzNr7LECt5ElwRwq oBBWIH+iQ0UUJDWqvQ4K0J+qiHbZZlC6h0HpJoPSDE5MRipbY5QZDoXwgd86qQYGpYB9NocCWAE8 RvuDA/SX0ewQ0WzDGmScssGy6qig6KqOvVGWVEeWBFxYhRoZiIcwIg5oBto3WZLMsiTZYEk86sqy @@ -6406,9 +6406,9 @@ s4YISlXlZPsbnqadIrx13D/jCWVgp+h9aKMcFZH2mYHJaGFqjoXFZmiwn6oRH45RYUGKhYgNKAXV KolQLEltI8odUZU1jcZogXpHnNjIoTSFZobLkllsowLCSaL1GFUwnfSjKwAZGRO8MBrf4ggyJoxx lMOJxNGlgZQnDEESqFaAgAKASWhiEu1DFzAGTMe8Q7LhSHKCcfKgAJJsVxEhaVUQ1Y4THe/olPMR iInoYEMTlqc8UcBIAPKRAmDFjniObL2jhoighxoBRRdJg9dIGdZIIj0L1B9Gym1UzwCJFPsNtLuI -R19A1moWQXXVCTs3KzgkQjI3BUNLTHBZ0LbBh3xfdrxB9lChrPPGcqk6LaOOTr4gNQ== - - +R19A1moWQXXVCTs3KzgkQjI3BUNLTHBZ0LbBh3xfdrxB9lChrPPGcqk6LaOOTr4gNQ== + + DGqoMDiB96tBXkqyUk3E8NaYqMIgkUIMa8w5ExGFcDcfTCGzom5V4KBksguKaUS4Hj41BsKCbq1L FmnbZQbn4RNDWfJUIfw5ovpYg/HWyJgOKdGvyAQ8FXQCzEwxEd/iyl9WmR2BTg1Jpgp3t3WJQFdH 9kBqSCQMya2VSbQL9eEZ8gBPYwHhQvBCIIqCimGXumzVkA1xtPlJqKpGsrJJIA5u8iq0SVpWCIa1 @@ -6426,7 +6426,7 @@ ikqIStRBnSqmgkgx1qxRqdcSe5FU4x2ibthcBt9BFzRTg5m7HImT4wRNpDV0+JYNYVbYH8kYQyT4 1WD0luT4yltDwRDEj/1ZMR6AhZODCYjUpsa0c0RWo+YzRtzdKmWDsOifno+wR93Y6sXNJXTnkf0y cgoaijtN4MnOE+KxJFgv1T2fBTtPJOo88d/bJG5iUPjoPxo5IsP+V8cTiKj8Ap3K2Nbk0TuAVoX1 y/2ZDDoihozIGJokGHsDuKs5Vm/FiL1pKNBJhhHRMG13S71Ij06sfHfIwYnZLN6Q23zpNvrNt89u -P/YyaP6v7lzz+7s3bA67P/AEwNYdDHv97tzgtfdfWAOfmK8nEpWjauz/AiYGbwI= - - - +P/YyaP6v7lzz+7s3bA67P/AEwNYdDHv97tzgtfdfWAOfmK8nEpWjauz/AiYGbwI= + ]]> + + diff --git a/imgsrc/view.svg b/imgsrc/view.svg index f0b0e1ef6c..e2bf205189 100644 --- a/imgsrc/view.svg +++ b/imgsrc/view.svg @@ -1,32 +1,32 @@ - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/recipes/autosport.recipe b/recipes/autosport.recipe index df98125f25..7b298c47e4 100644 --- a/recipes/autosport.recipe +++ b/recipes/autosport.recipe @@ -1,30 +1,30 @@ -#!/usr/bin/env python - -__license__ = 'GPL v3' -__author__ = 'MrStefan ' - -''' -www.autosport.com -''' - -from calibre.web.feeds.news import BasicNewsRecipe - -class autosport(BasicNewsRecipe): - title = u'Autosport' - __author__ = 'MrStefan ' - language = 'en_GB' - description =u'Daily Formula 1 and motorsport news from the leading weekly motor racing magazine. The authority on Formula 1, F1, MotoGP, GP2, Champ Car, Le Mans...' - masthead_url='http://cdn.images.autosport.com/asdotcom.gif' - remove_empty_feeds= True - oldest_article = 1 - max_articles_per_feed = 100 - remove_javascript=True - no_stylesheets=True - - keep_only_tags =[] - keep_only_tags.append(dict(name = 'h1', attrs = {'class' : 'news_headline'})) - keep_only_tags.append(dict(name = 'td', attrs = {'class' : 'news_article_author'})) - keep_only_tags.append(dict(name = 'td', attrs = {'class' : 'news_article_date'})) - keep_only_tags.append(dict(name = 'p')) - - feeds = [(u'ALL NEWS', u'http://www.autosport.com/rss/allnews.xml')] +#!/usr/bin/env python + +__license__ = 'GPL v3' +__author__ = 'MrStefan ' + +''' +www.autosport.com +''' + +from calibre.web.feeds.news import BasicNewsRecipe + +class autosport(BasicNewsRecipe): + title = u'Autosport' + __author__ = 'MrStefan ' + language = 'en_GB' + description =u'Daily Formula 1 and motorsport news from the leading weekly motor racing magazine. The authority on Formula 1, F1, MotoGP, GP2, Champ Car, Le Mans...' + masthead_url='http://cdn.images.autosport.com/asdotcom.gif' + remove_empty_feeds= True + oldest_article = 1 + max_articles_per_feed = 100 + remove_javascript=True + no_stylesheets=True + + keep_only_tags =[] + keep_only_tags.append(dict(name = 'h1', attrs = {'class' : 'news_headline'})) + keep_only_tags.append(dict(name = 'td', attrs = {'class' : 'news_article_author'})) + keep_only_tags.append(dict(name = 'td', attrs = {'class' : 'news_article_date'})) + keep_only_tags.append(dict(name = 'p')) + + feeds = [(u'ALL NEWS', u'http://www.autosport.com/rss/allnews.xml')] diff --git a/recipes/buchreport.recipe b/recipes/buchreport.recipe index 5ed34d1ee8..52ec6c4b26 100644 --- a/recipes/buchreport.recipe +++ b/recipes/buchreport.recipe @@ -1,45 +1,45 @@ -from calibre.web.feeds.recipes import BasicNewsRecipe - -'''Calibre recipe to convert the RSS feeds of the Buchreport to an ebook.''' - -class Buchreport(BasicNewsRecipe) : - __author__ = 'a.peter' - __copyright__ = 'a.peter' - __license__ = 'GPL v3' - description = 'Buchreport' - version = 4 - title = u'Buchreport' - timefmt = ' [%d.%m.%Y]' - encoding = 'cp1252' - language = 'de' - - - extra_css = 'body { margin-left: 0.00em; margin-right: 0.00em; } \ - article, articledate, articledescription { text-align: left; } \ - h1 { text-align: left; font-size: 140%; font-weight: bold; } \ - h2 { text-align: left; font-size: 100%; font-weight: bold; font-style: italic; } \ - h3 { text-align: left; font-size: 100%; font-weight: regular; font-style: italic; } \ - h4, h5, h6 { text-align: left; font-size: 100%; font-weight: bold; }' - - oldest_article = 7.0 - no_stylesheets = True - remove_javascript = True - use_embedded_content = False - publication_type = 'newspaper' - - remove_tags_before = dict(name='h2') - remove_tags_after = [ - dict(name='div', attrs={'style':["padding-top:10px;clear:both"]}) - ] - remove_tags = [ - dict(name='div', attrs={'style':["padding-top:10px;clear:both"]}), - dict(name='iframe'), - dict(name='img') - ] - - feeds = [ - (u'Buchreport', u'http://www.buchreport.de/index.php?id=5&type=100') - ] - - def get_masthead_url(self): - return 'http://www.buchreport.de/fileadmin/template/img/buchreport_logo.jpg' +from calibre.web.feeds.recipes import BasicNewsRecipe + +'''Calibre recipe to convert the RSS feeds of the Buchreport to an ebook.''' + +class Buchreport(BasicNewsRecipe) : + __author__ = 'a.peter' + __copyright__ = 'a.peter' + __license__ = 'GPL v3' + description = 'Buchreport' + version = 4 + title = u'Buchreport' + timefmt = ' [%d.%m.%Y]' + encoding = 'cp1252' + language = 'de' + + + extra_css = 'body { margin-left: 0.00em; margin-right: 0.00em; } \ + article, articledate, articledescription { text-align: left; } \ + h1 { text-align: left; font-size: 140%; font-weight: bold; } \ + h2 { text-align: left; font-size: 100%; font-weight: bold; font-style: italic; } \ + h3 { text-align: left; font-size: 100%; font-weight: regular; font-style: italic; } \ + h4, h5, h6 { text-align: left; font-size: 100%; font-weight: bold; }' + + oldest_article = 7.0 + no_stylesheets = True + remove_javascript = True + use_embedded_content = False + publication_type = 'newspaper' + + remove_tags_before = dict(name='h2') + remove_tags_after = [ + dict(name='div', attrs={'style':["padding-top:10px;clear:both"]}) + ] + remove_tags = [ + dict(name='div', attrs={'style':["padding-top:10px;clear:both"]}), + dict(name='iframe'), + dict(name='img') + ] + + feeds = [ + (u'Buchreport', u'http://www.buchreport.de/index.php?id=5&type=100') + ] + + def get_masthead_url(self): + return 'http://www.buchreport.de/fileadmin/template/img/buchreport_logo.jpg' diff --git a/recipes/diario_la_republica.recipe b/recipes/diario_la_republica.recipe index 1f0e0d565b..65bb3cd116 100644 --- a/recipes/diario_la_republica.recipe +++ b/recipes/diario_la_republica.recipe @@ -1,11 +1,11 @@ -from calibre.web.feeds.news import BasicNewsRecipe - -class AdvancedUserRecipe1317341449(BasicNewsRecipe): - title = u'Diario La Republica' - __author__ = 'CAVALENCIA' - oldest_article = 7 - max_articles_per_feed = 100 - auto_cleanup = True - language = 'es_CO' - - feeds = [(u'Diario La Republica', u'http://www.larepublica.com.co/rss/larepublica.xml')] +from calibre.web.feeds.news import BasicNewsRecipe + +class AdvancedUserRecipe1317341449(BasicNewsRecipe): + title = u'Diario La Republica' + __author__ = 'CAVALENCIA' + oldest_article = 7 + max_articles_per_feed = 100 + auto_cleanup = True + language = 'es_CO' + + feeds = [(u'Diario La Republica', u'http://www.larepublica.com.co/rss/larepublica.xml')] diff --git a/recipes/dnevnik_mk.recipe b/recipes/dnevnik_mk.recipe index ce8656339f..3648078b1e 100644 --- a/recipes/dnevnik_mk.recipe +++ b/recipes/dnevnik_mk.recipe @@ -1,98 +1,98 @@ -#!/usr/bin/env python - -__author__ = 'Darko Spasovski' -__license__ = 'GPL v3' -__copyright__ = '2011, Darko Spasovski ' -''' -dnevnik.com.mk -''' - -import re -import datetime -from calibre.web.feeds.news import BasicNewsRecipe -from calibre import browser -from calibre.ebooks.BeautifulSoup import BeautifulSoup - -class Dnevnik(BasicNewsRecipe): - - INDEX = 'http://www.dnevnik.com.mk' - __author__ = 'Darko Spasovski' - title = 'Dnevnik - mk' - description = 'Daily Macedonian newspaper' - masthead_url = 'http://www.dnevnik.com.mk/images/re-logo.gif' - language = 'mk' - publication_type = 'newspaper' - category = 'news, Macedonia' - max_articles_per_feed = 100 - remove_javascript = True - no_stylesheets = True - use_embedded_content = False - - preprocess_regexps = [(re.compile(i[0], re.IGNORECASE | re.DOTALL), i[1]) for i in - [ - ## Remove anything before the start of the article. - (r'', lambda match: ''), - - ## Remove anything after the end of the article. - (r'', lambda match: ''), + + ## Remove anything after the end of the article. + (r'Get your at http://www.thumbalizr.com/ and put here - LANGUAGE = 'pt_br' - language = 'pt' - LANGHTM = 'pt-br' - ENCODING = 'utf' - ENCHTM = 'utf-8' - directionhtm = 'ltr' - requires_version = (0,7,47) - news = True - - title = u'Estad\xe3o' - __author__ = 'Euler Alves' - description = u'Brazilian news from Estad\xe3o' - publisher = u'Estad\xe3o' - category = 'news, rss' - - oldest_article = 4 - max_articles_per_feed = 100 - summary_length = 1000 - - remove_javascript = True - no_stylesheets = True - use_embedded_content = False - remove_empty_feeds = True - timefmt = ' [%d %b %Y (%a)]' - - hoje = datetime.now()-timedelta(days=2) - pubdate = hoje.strftime('%a, %d %b') - if hoje.hour<10: - hoje = hoje-timedelta(days=1) - CAPA = 'http://www.estadao.com.br/estadaodehoje/'+hoje.strftime('%Y%m%d')+'/img/capadodia.jpg' - SCREENSHOT = 'http://estadao.com.br/' - cover_margins = (0,0,'white') - masthead_url = 'http://www.estadao.com.br/estadao/novo/img/logo.png' - - keep_only_tags = [dict(name='div', attrs={'class':['bb-md-noticia','corpo']})] - remove_tags = [ - dict(name='div', - attrs={'id':[ - 'bb-md-noticia-tabs' - ]}) - ,dict(name='div', - attrs={'class':[ - 'tags' - ,'discussion' - ,'bb-gg adsense_container' - ]}) - - ,dict(name='a') - ,dict(name='iframe') - ,dict(name='link') - ,dict(name='script') - ] - - - feeds = [ - (u'\xDAltimas Not\xEDcias', u'http://www.estadao.com.br/rss/ultimas.xml') - ,(u'Manchetes', u'http://www.estadao.com.br/rss/manchetes.xml') - ,(u'Brasil', u'http://www.estadao.com.br/rss/brasil.xml') - ,(u'Internacional', u'http://www.estadao.com.br/rss/internacional.xml') - ,(u'Cinema', u'http://blogs.estadao.com.br/cinema/feed/') - ,(u'Planeta', u'http://www.estadao.com.br/rss/planeta.xml') - ,(u'Ci\xEAncia', u'http://www.estadao.com.br/rss/ciencia.xml') - ,(u'Sa\xFAde', u'http://www.estadao.com.br/rss/saude.xml') - ,(u'Pol\xEDtica', u'http://www.estadao.com.br/rss/politica.xml') - ] - - conversion_options = { - 'title' : title - ,'comments' : description - ,'publisher' : publisher - ,'tags' : category - ,'language' : LANGUAGE - ,'linearize_tables': True - } - - def preprocess_html(self, soup): - for item in soup.findAll(style=True): - del item['style'] - if not soup.find(attrs={'http-equiv':'Content-Language'}): - meta0 = Tag(soup,'meta',[("http-equiv","Content-Language"),("content",self.LANGHTM)]) - soup.head.insert(0,meta0) - if not soup.find(attrs={'http-equiv':'Content-Type'}): - meta1 = Tag(soup,'meta',[("http-equiv","Content-Type"),("content","text/html; charset="+self.ENCHTM)]) - soup.head.insert(0,meta1) - return soup - - def postprocess_html(self, soup, first): - #process all the images. assumes that the new html has the correct path - for tag in soup.findAll(lambda tag: tag.name.lower()=='img' and tag.has_key('src')): - iurl = tag['src'] - img = Image() - img.open(iurl) - width, height = img.size - print 'img is: ', iurl, 'width is: ', width, 'height is: ', height - if img < 0: - raise RuntimeError('Out of memory') - pw = PixelWand() - if( width > height and width > 590) : - print 'Rotate image' - img.rotate(pw, -90) - img.save(iurl) - return soup - - def get_cover_url(self): - if self.THUMBALIZR_API: - cover_url = self.CAPA - pedido = Request(self.CAPA) - pedido.add_header('User-agent','Mozilla/5.0 (Windows; U; Windows NT 5.1; '+self.LANGHTM+'; userid='+self.THUMBALIZR_API+') Calibre/0.8.47 (like Gecko)') - pedido.add_header('Accept-Charset',self.ENCHTM) - pedido.add_header('Referer',self.SCREENSHOT) - try: - resposta = urlopen(pedido) - soup = BeautifulSoup(resposta) - cover_item = soup.find('body') - if cover_item: - cover_url='http://api.thumbalizr.com/?api_key='+self.THUMBALIZR_API+'&url='+self.SCREENSHOT+'&width=600&quality=90' - return cover_url - except URLError: - cover_url='http://api.thumbalizr.com/?api_key='+self.THUMBALIZR_API+'&url='+self.SCREENSHOT+'&width=600&quality=90' - return cover_url - +from calibre.web.feeds.news import BasicNewsRecipe +from datetime import datetime, timedelta +from calibre.ebooks.BeautifulSoup import Tag,BeautifulSoup +from calibre.utils.magick import Image, PixelWand +from urllib2 import Request, urlopen, URLError + +class Estadao(BasicNewsRecipe): + THUMBALIZR_API = '' # ---->Get your at http://www.thumbalizr.com/ and put here + LANGUAGE = 'pt_br' + language = 'pt' + LANGHTM = 'pt-br' + ENCODING = 'utf' + ENCHTM = 'utf-8' + directionhtm = 'ltr' + requires_version = (0,7,47) + news = True + + title = u'Estad\xe3o' + __author__ = 'Euler Alves' + description = u'Brazilian news from Estad\xe3o' + publisher = u'Estad\xe3o' + category = 'news, rss' + + oldest_article = 4 + max_articles_per_feed = 100 + summary_length = 1000 + + remove_javascript = True + no_stylesheets = True + use_embedded_content = False + remove_empty_feeds = True + timefmt = ' [%d %b %Y (%a)]' + + hoje = datetime.now()-timedelta(days=2) + pubdate = hoje.strftime('%a, %d %b') + if hoje.hour<10: + hoje = hoje-timedelta(days=1) + CAPA = 'http://www.estadao.com.br/estadaodehoje/'+hoje.strftime('%Y%m%d')+'/img/capadodia.jpg' + SCREENSHOT = 'http://estadao.com.br/' + cover_margins = (0,0,'white') + masthead_url = 'http://www.estadao.com.br/estadao/novo/img/logo.png' + + keep_only_tags = [dict(name='div', attrs={'class':['bb-md-noticia','corpo']})] + remove_tags = [ + dict(name='div', + attrs={'id':[ + 'bb-md-noticia-tabs' + ]}) + ,dict(name='div', + attrs={'class':[ + 'tags' + ,'discussion' + ,'bb-gg adsense_container' + ]}) + + ,dict(name='a') + ,dict(name='iframe') + ,dict(name='link') + ,dict(name='script') + ] + + + feeds = [ + (u'\xDAltimas Not\xEDcias', u'http://www.estadao.com.br/rss/ultimas.xml') + ,(u'Manchetes', u'http://www.estadao.com.br/rss/manchetes.xml') + ,(u'Brasil', u'http://www.estadao.com.br/rss/brasil.xml') + ,(u'Internacional', u'http://www.estadao.com.br/rss/internacional.xml') + ,(u'Cinema', u'http://blogs.estadao.com.br/cinema/feed/') + ,(u'Planeta', u'http://www.estadao.com.br/rss/planeta.xml') + ,(u'Ci\xEAncia', u'http://www.estadao.com.br/rss/ciencia.xml') + ,(u'Sa\xFAde', u'http://www.estadao.com.br/rss/saude.xml') + ,(u'Pol\xEDtica', u'http://www.estadao.com.br/rss/politica.xml') + ] + + conversion_options = { + 'title' : title + ,'comments' : description + ,'publisher' : publisher + ,'tags' : category + ,'language' : LANGUAGE + ,'linearize_tables': True + } + + def preprocess_html(self, soup): + for item in soup.findAll(style=True): + del item['style'] + if not soup.find(attrs={'http-equiv':'Content-Language'}): + meta0 = Tag(soup,'meta',[("http-equiv","Content-Language"),("content",self.LANGHTM)]) + soup.head.insert(0,meta0) + if not soup.find(attrs={'http-equiv':'Content-Type'}): + meta1 = Tag(soup,'meta',[("http-equiv","Content-Type"),("content","text/html; charset="+self.ENCHTM)]) + soup.head.insert(0,meta1) + return soup + + def postprocess_html(self, soup, first): + #process all the images. assumes that the new html has the correct path + for tag in soup.findAll(lambda tag: tag.name.lower()=='img' and tag.has_key('src')): + iurl = tag['src'] + img = Image() + img.open(iurl) + width, height = img.size + print 'img is: ', iurl, 'width is: ', width, 'height is: ', height + if img < 0: + raise RuntimeError('Out of memory') + pw = PixelWand() + if( width > height and width > 590) : + print 'Rotate image' + img.rotate(pw, -90) + img.save(iurl) + return soup + + def get_cover_url(self): + if self.THUMBALIZR_API: + cover_url = self.CAPA + pedido = Request(self.CAPA) + pedido.add_header('User-agent','Mozilla/5.0 (Windows; U; Windows NT 5.1; '+self.LANGHTM+'; userid='+self.THUMBALIZR_API+') Calibre/0.8.47 (like Gecko)') + pedido.add_header('Accept-Charset',self.ENCHTM) + pedido.add_header('Referer',self.SCREENSHOT) + try: + resposta = urlopen(pedido) + soup = BeautifulSoup(resposta) + cover_item = soup.find('body') + if cover_item: + cover_url='http://api.thumbalizr.com/?api_key='+self.THUMBALIZR_API+'&url='+self.SCREENSHOT+'&width=600&quality=90' + return cover_url + except URLError: + cover_url='http://api.thumbalizr.com/?api_key='+self.THUMBALIZR_API+'&url='+self.SCREENSHOT+'&width=600&quality=90' + return cover_url + diff --git a/recipes/folhadesaopaulo.recipe b/recipes/folhadesaopaulo.recipe index 50e55a2990..3f63e80291 100644 --- a/recipes/folhadesaopaulo.recipe +++ b/recipes/folhadesaopaulo.recipe @@ -1,165 +1,165 @@ -# -*- coding: utf-8 -*- -from calibre.web.feeds.news import BasicNewsRecipe -from datetime import datetime, timedelta -from calibre.ebooks.BeautifulSoup import Tag,BeautifulSoup -from calibre.utils.magick import Image, PixelWand -from urllib2 import Request, urlopen, URLError - -class FolhaOnline(BasicNewsRecipe): - THUMBALIZR_API = '' # ---->Get your at http://www.thumbalizr.com/ and put here - LANGUAGE = 'pt_br' - language = 'pt_BR' - LANGHTM = 'pt-br' - ENCODING = 'cp1252' - ENCHTM = 'iso-8859-1' - directionhtm = 'ltr' - requires_version = (0,7,47) - news = True - - title = u'Folha de S\xE3o Paulo' - __author__ = 'Euler Alves and Alex Mitrani' - description = u'Brazilian news from Folha de S\xE3o Paulo' - publisher = u'Folha de S\xE3o Paulo' - category = 'news, rss' - - oldest_article = 4 - max_articles_per_feed = 100 - summary_length = 1000 - - remove_javascript = True - no_stylesheets = True - use_embedded_content = False - remove_empty_feeds = True - timefmt = ' [%d %b %Y (%a)]' - - html2lrf_options = [ - '--comment', description - ,'--category', category - ,'--publisher', publisher - ] - - html2epub_options = 'publisher="' + publisher + '"\ncomments="' + description + '"\ntags="' + category + '"' - - hoje = datetime.now() - pubdate = hoje.strftime('%a, %d %b') - if hoje.hour<6: - hoje = hoje-timedelta(days=1) - CAPA = 'http://www1.folha.uol.com.br/fsp/images/cp'+hoje.strftime('%d%m%Y')+'.jpg' - SCREENSHOT = 'http://www1.folha.uol.com.br/' - cover_margins = (0,0,'white') - masthead_url = 'http://f.i.uol.com.br/fsp/furniture/images/lgo-fsp-430x50-ffffff.gif' - - keep_only_tags = [dict(name='div', attrs={'id':'articleNew'})] - remove_tags = [ - dict(name='div', - attrs={'id':[ - 'articleButton' - ,'bookmarklets' - ,'ad-180x150-1' - ,'contextualAdsArticle' - ,'articleEnd' - ,'articleComments' - ]}) - ,dict(name='div', - attrs={'class':[ - 'openBox adslibraryArticle' - ,'toolbar' - ]}) - - ,dict(name='a') - ,dict(name='iframe') - ,dict(name='link') - ,dict(name='script') - ,dict(name='li') - ] - remove_tags_after = dict(name='div',attrs={'id':'articleEnd'}) - - feeds = [ - (u'Em cima da hora', u'http://feeds.folha.uol.com.br/emcimadahora/rss091.xml') - ,(u'Cotidiano', u'http://feeds.folha.uol.com.br/folha/cotidiano/rss091.xml') - ,(u'Brasil', u'http://feeds.folha.uol.com.br/folha/brasil/rss091.xml') - ,(u'Mundo', u'http://feeds.folha.uol.com.br/mundo/rss091.xml') - ,(u'Poder', u'http://feeds.folha.uol.com.br/poder/rss091.xml') - ,(u'Mercado', u'http://feeds.folha.uol.com.br/folha/dinheiro/rss091.xml') - ,(u'Saber', u'http://feeds.folha.uol.com.br/folha/educacao/rss091.xml') - ,(u'Tec', u'http://feeds.folha.uol.com.br/folha/informatica/rss091.xml') - ,(u'Ilustrada', u'http://feeds.folha.uol.com.br/folha/ilustrada/rss091.xml') - ,(u'Ambiente', u'http://feeds.folha.uol.com.br/ambiente/rss091.xml') - ,(u'Bichos', u'http://feeds.folha.uol.com.br/bichos/rss091.xml') - ,(u'Ci\xEAncia', u'http://feeds.folha.uol.com.br/ciencia/rss091.xml') - ,(u'Equil\xEDbrio e Sa\xFAde', u'http://feeds.folha.uol.com.br/equilibrioesaude/rss091.xml') - ,(u'Turismo', u'http://feeds.folha.uol.com.br/folha/turismo/rss091.xml') - ,(u'Esporte', u'http://feeds.folha.uol.com.br/folha/esporte/rss091.xml') - ,(u'Zapping', u'http://feeds.folha.uol.com.br/colunas/zapping/rss091.xml') - ,(u'Cida Santos', u'http://feeds.folha.uol.com.br/colunas/cidasantos/rss091.xml') - ,(u'Clóvis Rossi', u'http://feeds.folha.uol.com.br/colunas/clovisrossi/rss091.xml') - ,(u'Eliane Cantanhêde', u'http://feeds.folha.uol.com.br/colunas/elianecantanhede/rss091.xml') - ,(u'Fernando Canzian', u'http://feeds.folha.uol.com.br/colunas/fernandocanzian/rss091.xml') - ,(u'Gilberto Dimenstein', u'http://feeds.folha.uol.com.br/colunas/gilbertodimenstein/rss091.xml') - ,(u'Hélio Schwartsman', u'http://feeds.folha.uol.com.br/colunas/helioschwartsman/rss091.xml') - ,(u'Humberto Luiz Peron', u'http://feeds.folha.uol.com.br/colunas/futebolnarede/rss091.xml') - ,(u'João Pereira Coutinho', u'http://feeds.folha.uol.com.br/colunas/joaopereiracoutinho/rss091.xml') - ,(u'José Antonio Ramalho', u'http://feeds.folha.uol.com.br/colunas/canalaberto/rss091.xml') - ,(u'Kennedy Alencar', u'http://feeds.folha.uol.com.br/colunas/kennedyalencar/rss091.xml') - ,(u'Luiz Caversan', u'http://feeds.folha.uol.com.br/colunas/luizcaversan/rss091.xml') - ,(u'Luiz Rivoiro', u'http://feeds.folha.uol.com.br/colunas/paiepai/rss091.xml') - ,(u'Marcelo Leite', u'http://feeds.folha.uol.com.br/colunas/marceloleite/rss091.xml') - ,(u'Sérgio Malbergier', u'http://feeds.folha.uol.com.br/colunas/sergiomalbergier/rss091.xml') - ,(u'Sylvia Colombo', u'http://feeds.folha.uol.com.br/colunas/sylviacolombo/rss091.xml') - ,(u'Valdo Cruz', u'http://feeds.folha.uol.com.br/colunas/valdocruz/rss091.xml') - ] - - - conversion_options = { - 'title' : title - ,'comments' : description - ,'publisher' : publisher - ,'tags' : category - ,'language' : LANGUAGE - ,'linearize_tables': True - } - - def preprocess_html(self, soup): - for item in soup.findAll(style=True): - del item['style'] - if not soup.find(attrs={'http-equiv':'Content-Language'}): - meta0 = Tag(soup,'meta',[("http-equiv","Content-Language"),("content",self.LANGHTM)]) - soup.head.insert(0,meta0) - if not soup.find(attrs={'http-equiv':'Content-Type'}): - meta1 = Tag(soup,'meta',[("http-equiv","Content-Type"),("content","text/html; charset="+self.ENCHTM)]) - soup.head.insert(0,meta1) - return soup - - def postprocess_html(self, soup, first): - #process all the images. assumes that the new html has the correct path - for tag in soup.findAll(lambda tag: tag.name.lower()=='img' and tag.has_key('src')): - iurl = tag['src'] - img = Image() - img.open(iurl) - width, height = img.size - print 'img is: ', iurl, 'width is: ', width, 'height is: ', height - if img < 0: - raise RuntimeError('Out of memory') - pw = PixelWand() - if( width > height and width > 590) : - print 'Rotate image' - img.rotate(pw, -90) - img.save(iurl) - return soup - - def get_cover_url(self): - cover_url = self.CAPA - pedido = Request(self.CAPA) - pedido.add_header('User-agent','Mozilla/5.0 (Windows; U; Windows NT 5.1; '+self.LANGHTM+'; userid='+self.THUMBALIZR_API+') Calibre/0.8.47 (like Gecko)') - pedido.add_header('Accept-Charset',self.ENCHTM) - pedido.add_header('Referer',self.SCREENSHOT) - try: - resposta = urlopen(pedido) - soup = BeautifulSoup(resposta) - cover_item = soup.find('body') - if cover_item: - cover_url='http://api.thumbalizr.com/?api_key='+self.THUMBALIZR_API+'&url='+self.SCREENSHOT+'&width=600&quality=90' - return cover_url - except URLError: - cover_url='http://api.thumbalizr.com/?api_key='+self.THUMBALIZR_API+'&url='+self.SCREENSHOT+'&width=600&quality=90' - return cover_url +# -*- coding: utf-8 -*- +from calibre.web.feeds.news import BasicNewsRecipe +from datetime import datetime, timedelta +from calibre.ebooks.BeautifulSoup import Tag,BeautifulSoup +from calibre.utils.magick import Image, PixelWand +from urllib2 import Request, urlopen, URLError + +class FolhaOnline(BasicNewsRecipe): + THUMBALIZR_API = '' # ---->Get your at http://www.thumbalizr.com/ and put here + LANGUAGE = 'pt_br' + language = 'pt_BR' + LANGHTM = 'pt-br' + ENCODING = 'cp1252' + ENCHTM = 'iso-8859-1' + directionhtm = 'ltr' + requires_version = (0,7,47) + news = True + + title = u'Folha de S\xE3o Paulo' + __author__ = 'Euler Alves and Alex Mitrani' + description = u'Brazilian news from Folha de S\xE3o Paulo' + publisher = u'Folha de S\xE3o Paulo' + category = 'news, rss' + + oldest_article = 4 + max_articles_per_feed = 100 + summary_length = 1000 + + remove_javascript = True + no_stylesheets = True + use_embedded_content = False + remove_empty_feeds = True + timefmt = ' [%d %b %Y (%a)]' + + html2lrf_options = [ + '--comment', description + ,'--category', category + ,'--publisher', publisher + ] + + html2epub_options = 'publisher="' + publisher + '"\ncomments="' + description + '"\ntags="' + category + '"' + + hoje = datetime.now() + pubdate = hoje.strftime('%a, %d %b') + if hoje.hour<6: + hoje = hoje-timedelta(days=1) + CAPA = 'http://www1.folha.uol.com.br/fsp/images/cp'+hoje.strftime('%d%m%Y')+'.jpg' + SCREENSHOT = 'http://www1.folha.uol.com.br/' + cover_margins = (0,0,'white') + masthead_url = 'http://f.i.uol.com.br/fsp/furniture/images/lgo-fsp-430x50-ffffff.gif' + + keep_only_tags = [dict(name='div', attrs={'id':'articleNew'})] + remove_tags = [ + dict(name='div', + attrs={'id':[ + 'articleButton' + ,'bookmarklets' + ,'ad-180x150-1' + ,'contextualAdsArticle' + ,'articleEnd' + ,'articleComments' + ]}) + ,dict(name='div', + attrs={'class':[ + 'openBox adslibraryArticle' + ,'toolbar' + ]}) + + ,dict(name='a') + ,dict(name='iframe') + ,dict(name='link') + ,dict(name='script') + ,dict(name='li') + ] + remove_tags_after = dict(name='div',attrs={'id':'articleEnd'}) + + feeds = [ + (u'Em cima da hora', u'http://feeds.folha.uol.com.br/emcimadahora/rss091.xml') + ,(u'Cotidiano', u'http://feeds.folha.uol.com.br/folha/cotidiano/rss091.xml') + ,(u'Brasil', u'http://feeds.folha.uol.com.br/folha/brasil/rss091.xml') + ,(u'Mundo', u'http://feeds.folha.uol.com.br/mundo/rss091.xml') + ,(u'Poder', u'http://feeds.folha.uol.com.br/poder/rss091.xml') + ,(u'Mercado', u'http://feeds.folha.uol.com.br/folha/dinheiro/rss091.xml') + ,(u'Saber', u'http://feeds.folha.uol.com.br/folha/educacao/rss091.xml') + ,(u'Tec', u'http://feeds.folha.uol.com.br/folha/informatica/rss091.xml') + ,(u'Ilustrada', u'http://feeds.folha.uol.com.br/folha/ilustrada/rss091.xml') + ,(u'Ambiente', u'http://feeds.folha.uol.com.br/ambiente/rss091.xml') + ,(u'Bichos', u'http://feeds.folha.uol.com.br/bichos/rss091.xml') + ,(u'Ci\xEAncia', u'http://feeds.folha.uol.com.br/ciencia/rss091.xml') + ,(u'Equil\xEDbrio e Sa\xFAde', u'http://feeds.folha.uol.com.br/equilibrioesaude/rss091.xml') + ,(u'Turismo', u'http://feeds.folha.uol.com.br/folha/turismo/rss091.xml') + ,(u'Esporte', u'http://feeds.folha.uol.com.br/folha/esporte/rss091.xml') + ,(u'Zapping', u'http://feeds.folha.uol.com.br/colunas/zapping/rss091.xml') + ,(u'Cida Santos', u'http://feeds.folha.uol.com.br/colunas/cidasantos/rss091.xml') + ,(u'Clóvis Rossi', u'http://feeds.folha.uol.com.br/colunas/clovisrossi/rss091.xml') + ,(u'Eliane Cantanhêde', u'http://feeds.folha.uol.com.br/colunas/elianecantanhede/rss091.xml') + ,(u'Fernando Canzian', u'http://feeds.folha.uol.com.br/colunas/fernandocanzian/rss091.xml') + ,(u'Gilberto Dimenstein', u'http://feeds.folha.uol.com.br/colunas/gilbertodimenstein/rss091.xml') + ,(u'Hélio Schwartsman', u'http://feeds.folha.uol.com.br/colunas/helioschwartsman/rss091.xml') + ,(u'Humberto Luiz Peron', u'http://feeds.folha.uol.com.br/colunas/futebolnarede/rss091.xml') + ,(u'João Pereira Coutinho', u'http://feeds.folha.uol.com.br/colunas/joaopereiracoutinho/rss091.xml') + ,(u'José Antonio Ramalho', u'http://feeds.folha.uol.com.br/colunas/canalaberto/rss091.xml') + ,(u'Kennedy Alencar', u'http://feeds.folha.uol.com.br/colunas/kennedyalencar/rss091.xml') + ,(u'Luiz Caversan', u'http://feeds.folha.uol.com.br/colunas/luizcaversan/rss091.xml') + ,(u'Luiz Rivoiro', u'http://feeds.folha.uol.com.br/colunas/paiepai/rss091.xml') + ,(u'Marcelo Leite', u'http://feeds.folha.uol.com.br/colunas/marceloleite/rss091.xml') + ,(u'Sérgio Malbergier', u'http://feeds.folha.uol.com.br/colunas/sergiomalbergier/rss091.xml') + ,(u'Sylvia Colombo', u'http://feeds.folha.uol.com.br/colunas/sylviacolombo/rss091.xml') + ,(u'Valdo Cruz', u'http://feeds.folha.uol.com.br/colunas/valdocruz/rss091.xml') + ] + + + conversion_options = { + 'title' : title + ,'comments' : description + ,'publisher' : publisher + ,'tags' : category + ,'language' : LANGUAGE + ,'linearize_tables': True + } + + def preprocess_html(self, soup): + for item in soup.findAll(style=True): + del item['style'] + if not soup.find(attrs={'http-equiv':'Content-Language'}): + meta0 = Tag(soup,'meta',[("http-equiv","Content-Language"),("content",self.LANGHTM)]) + soup.head.insert(0,meta0) + if not soup.find(attrs={'http-equiv':'Content-Type'}): + meta1 = Tag(soup,'meta',[("http-equiv","Content-Type"),("content","text/html; charset="+self.ENCHTM)]) + soup.head.insert(0,meta1) + return soup + + def postprocess_html(self, soup, first): + #process all the images. assumes that the new html has the correct path + for tag in soup.findAll(lambda tag: tag.name.lower()=='img' and tag.has_key('src')): + iurl = tag['src'] + img = Image() + img.open(iurl) + width, height = img.size + print 'img is: ', iurl, 'width is: ', width, 'height is: ', height + if img < 0: + raise RuntimeError('Out of memory') + pw = PixelWand() + if( width > height and width > 590) : + print 'Rotate image' + img.rotate(pw, -90) + img.save(iurl) + return soup + + def get_cover_url(self): + cover_url = self.CAPA + pedido = Request(self.CAPA) + pedido.add_header('User-agent','Mozilla/5.0 (Windows; U; Windows NT 5.1; '+self.LANGHTM+'; userid='+self.THUMBALIZR_API+') Calibre/0.8.47 (like Gecko)') + pedido.add_header('Accept-Charset',self.ENCHTM) + pedido.add_header('Referer',self.SCREENSHOT) + try: + resposta = urlopen(pedido) + soup = BeautifulSoup(resposta) + cover_item = soup.find('body') + if cover_item: + cover_url='http://api.thumbalizr.com/?api_key='+self.THUMBALIZR_API+'&url='+self.SCREENSHOT+'&width=600&quality=90' + return cover_url + except URLError: + cover_url='http://api.thumbalizr.com/?api_key='+self.THUMBALIZR_API+'&url='+self.SCREENSHOT+'&width=600&quality=90' + return cover_url diff --git a/recipes/gazeta_pl_szczecin.recipe b/recipes/gazeta_pl_szczecin.recipe index 501b25dfe5..c0c83fd109 100644 --- a/recipes/gazeta_pl_szczecin.recipe +++ b/recipes/gazeta_pl_szczecin.recipe @@ -1,35 +1,35 @@ -# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai - -import re -import string -from calibre.web.feeds.news import BasicNewsRecipe - -class GazetaPlSzczecin(BasicNewsRecipe): - title = u'Gazeta Wyborcza Szczecin' - description = u'Wiadomości ze Szczecina na portalu Gazeta.pl.' - __author__ = u'Michał Szkutnik' - __license__ = u'GPL v3' - language = 'pl' - publisher = 'Agora S.A.' - category = 'news, szczecin' - oldest_article = 2 - max_articles_per_feed = 100 - auto_cleanup = True - remove_tags = [ { "name" : "a", "attrs" : { "href" : "http://szczecin.gazeta.pl/szczecin/www.gazeta.pl" }}] - cover_url = "http://bi.gazeta.pl/i/hp/hp2009/logo.gif" - feeds = [(u'Wszystkie', u'http://rss.feedsportal.com/c/32739/f/530434/index.rss')] - - def get_article_url(self, article): - s = re.search("""/0L(szczecin.*)/story01.htm""", article.link) - s = s.group(1) - replacements = { "0B" : ".", "0C" : "/", "0H" : ",", "0I" : "_"} - for (a, b) in replacements.iteritems(): - s = string.replace(s, a, b) - s = string.replace(s, "0A", "0") - return "http://"+s - - def print_version(self, url): - s = re.search("""/(\d*),(\d*),(\d*),.*\.html""", url) - no1 = s.group(2) - no2 = s.group(3) - return """http://szczecin.gazeta.pl/szczecin/2029020,%s,%s.html""" % (no1, no2) +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai + +import re +import string +from calibre.web.feeds.news import BasicNewsRecipe + +class GazetaPlSzczecin(BasicNewsRecipe): + title = u'Gazeta Wyborcza Szczecin' + description = u'Wiadomości ze Szczecina na portalu Gazeta.pl.' + __author__ = u'Michał Szkutnik' + __license__ = u'GPL v3' + language = 'pl' + publisher = 'Agora S.A.' + category = 'news, szczecin' + oldest_article = 2 + max_articles_per_feed = 100 + auto_cleanup = True + remove_tags = [ { "name" : "a", "attrs" : { "href" : "http://szczecin.gazeta.pl/szczecin/www.gazeta.pl" }}] + cover_url = "http://bi.gazeta.pl/i/hp/hp2009/logo.gif" + feeds = [(u'Wszystkie', u'http://rss.feedsportal.com/c/32739/f/530434/index.rss')] + + def get_article_url(self, article): + s = re.search("""/0L(szczecin.*)/story01.htm""", article.link) + s = s.group(1) + replacements = { "0B" : ".", "0C" : "/", "0H" : ",", "0I" : "_"} + for (a, b) in replacements.iteritems(): + s = string.replace(s, a, b) + s = string.replace(s, "0A", "0") + return "http://"+s + + def print_version(self, url): + s = re.search("""/(\d*),(\d*),(\d*),.*\.html""", url) + no1 = s.group(2) + no2 = s.group(3) + return """http://szczecin.gazeta.pl/szczecin/2029020,%s,%s.html""" % (no1, no2) diff --git a/recipes/gs24_pl.recipe b/recipes/gs24_pl.recipe index db7125b116..2a16f80453 100644 --- a/recipes/gs24_pl.recipe +++ b/recipes/gs24_pl.recipe @@ -1,43 +1,43 @@ -# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai - -import re -import string -from calibre.web.feeds.news import BasicNewsRecipe - -class AdvancedUserRecipe1322322819(BasicNewsRecipe): - title = u'GS24.pl (Głos Szczeciński)' - description = u'Internetowy serwis Głosu Szczecińskiego' - __author__ = u'Michał Szkutnik' - __license__ = u'GPL v3' - language = 'pl' - publisher = 'Media Regionalne sp. z o.o.' - category = 'news, szczecin' - oldest_article = 2 - max_articles_per_feed = 100 - auto_cleanup = True - cover_url = "http://www.gs24.pl/images/top_logo.png" - - feeds = [ - # (u'Wszystko', u'http://www.gs24.pl/rss.xml'), - (u'Szczecin', u'http://www.gs24.pl/szczecin.xml'), - (u'Stargard', u'http://www.gs24.pl/stargard.xml'), - (u'Świnoujście', u'http://www.gs24.pl/swinoujscie.xml'), - (u'Goleniów', u'http://www.gs24.pl/goleniow.xml'), - (u'Gryfice', u'http://www.gs24.pl/gryfice.xml'), - (u'Kamień Pomorski', u'http://www.gs24.pl/kamienpomorski.xml'), - (u'Police', u'http://www.gs24.pl/police.xml'), - (u'Region', u'http://www.gs24.pl/region.xml'), - (u'Sport', u'http://www.gs24.pl/sport.xml'), - ] - - def get_article_url(self, article): - s = re.search("""/0L0S(gs24.*)/story01.htm""", article.link) - s = s.group(1) - replacements = { "0B" : ".", "0C" : "/", "0H" : ",", "0I" : "_", "0D" : "?", "0F" : "="} - for (a, b) in replacements.iteritems(): - s = string.replace(s, a, b) - s = string.replace(s, "0A", "0") - return "http://"+s - - def print_version(self, url): - return url + "&Template=printpicart" +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai + +import re +import string +from calibre.web.feeds.news import BasicNewsRecipe + +class AdvancedUserRecipe1322322819(BasicNewsRecipe): + title = u'GS24.pl (Głos Szczeciński)' + description = u'Internetowy serwis Głosu Szczecińskiego' + __author__ = u'Michał Szkutnik' + __license__ = u'GPL v3' + language = 'pl' + publisher = 'Media Regionalne sp. z o.o.' + category = 'news, szczecin' + oldest_article = 2 + max_articles_per_feed = 100 + auto_cleanup = True + cover_url = "http://www.gs24.pl/images/top_logo.png" + + feeds = [ + # (u'Wszystko', u'http://www.gs24.pl/rss.xml'), + (u'Szczecin', u'http://www.gs24.pl/szczecin.xml'), + (u'Stargard', u'http://www.gs24.pl/stargard.xml'), + (u'Świnoujście', u'http://www.gs24.pl/swinoujscie.xml'), + (u'Goleniów', u'http://www.gs24.pl/goleniow.xml'), + (u'Gryfice', u'http://www.gs24.pl/gryfice.xml'), + (u'Kamień Pomorski', u'http://www.gs24.pl/kamienpomorski.xml'), + (u'Police', u'http://www.gs24.pl/police.xml'), + (u'Region', u'http://www.gs24.pl/region.xml'), + (u'Sport', u'http://www.gs24.pl/sport.xml'), + ] + + def get_article_url(self, article): + s = re.search("""/0L0S(gs24.*)/story01.htm""", article.link) + s = s.group(1) + replacements = { "0B" : ".", "0C" : "/", "0H" : ",", "0I" : "_", "0D" : "?", "0F" : "="} + for (a, b) in replacements.iteritems(): + s = string.replace(s, a, b) + s = string.replace(s, "0A", "0") + return "http://"+s + + def print_version(self, url): + return url + "&Template=printpicart" diff --git a/recipes/hankyoreh.recipe b/recipes/hankyoreh.recipe index 8212765b66..7da23fa0db 100644 --- a/recipes/hankyoreh.recipe +++ b/recipes/hankyoreh.recipe @@ -1,47 +1,47 @@ -__license__ = 'GPL v3' -__copyright__ = '2011, Seongkyoun Yoo ' -''' -Profile to download The Hankyoreh -''' -from calibre.web.feeds.news import BasicNewsRecipe - -class Hankyoreh(BasicNewsRecipe): - title = u'Hankyoreh' - language = 'ko' - description = u'The Hankyoreh News articles' - __author__ = 'Seongkyoun Yoo' - oldest_article = 5 - recursions = 1 - max_articles_per_feed = 5 - no_stylesheets = True - keep_only_tags = [ - dict(name='tr', attrs={'height':['60px']}), - dict(id=['fontSzArea']) - ] - remove_tags = [ - dict(target='_blank'), - dict(name='td', attrs={'style':['padding: 10px 8px 5px 8px;']}), - dict(name='iframe', attrs={'width':['590']}), - ] - remove_tags_after = [ - dict(target='_top') - ] - feeds = [ - ('All News','http://www.hani.co.kr/rss/'), - ('Politics','http://www.hani.co.kr/rss/politics/'), - ('Economy','http://www.hani.co.kr/rss/economy/'), - ('Society','http://www.hani.co.kr/rss/society/'), - ('International','http://www.hani.co.kr/rss/international/'), - ('Culture','http://www.hani.co.kr/rss/culture/'), - ('Sports','http://www.hani.co.kr/rss/sports/'), - ('Science','http://www.hani.co.kr/rss/science/'), - ('Opinion','http://www.hani.co.kr/rss/opinion/'), - ('Cartoon','http://www.hani.co.kr/rss/cartoon/'), - ('English Edition','http://www.hani.co.kr/rss/english_edition/'), - ('Specialsection','http://www.hani.co.kr/rss/specialsection/'), - ('Hanionly','http://www.hani.co.kr/rss/hanionly/'), - ('Hkronly','http://www.hani.co.kr/rss/hkronly/'), - ('Multihani','http://www.hani.co.kr/rss/multihani/'), - ('Lead','http://www.hani.co.kr/rss/lead/'), - ('Newsrank','http://www.hani.co.kr/rss/newsrank/'), - ] +__license__ = 'GPL v3' +__copyright__ = '2011, Seongkyoun Yoo ' +''' +Profile to download The Hankyoreh +''' +from calibre.web.feeds.news import BasicNewsRecipe + +class Hankyoreh(BasicNewsRecipe): + title = u'Hankyoreh' + language = 'ko' + description = u'The Hankyoreh News articles' + __author__ = 'Seongkyoun Yoo' + oldest_article = 5 + recursions = 1 + max_articles_per_feed = 5 + no_stylesheets = True + keep_only_tags = [ + dict(name='tr', attrs={'height':['60px']}), + dict(id=['fontSzArea']) + ] + remove_tags = [ + dict(target='_blank'), + dict(name='td', attrs={'style':['padding: 10px 8px 5px 8px;']}), + dict(name='iframe', attrs={'width':['590']}), + ] + remove_tags_after = [ + dict(target='_top') + ] + feeds = [ + ('All News','http://www.hani.co.kr/rss/'), + ('Politics','http://www.hani.co.kr/rss/politics/'), + ('Economy','http://www.hani.co.kr/rss/economy/'), + ('Society','http://www.hani.co.kr/rss/society/'), + ('International','http://www.hani.co.kr/rss/international/'), + ('Culture','http://www.hani.co.kr/rss/culture/'), + ('Sports','http://www.hani.co.kr/rss/sports/'), + ('Science','http://www.hani.co.kr/rss/science/'), + ('Opinion','http://www.hani.co.kr/rss/opinion/'), + ('Cartoon','http://www.hani.co.kr/rss/cartoon/'), + ('English Edition','http://www.hani.co.kr/rss/english_edition/'), + ('Specialsection','http://www.hani.co.kr/rss/specialsection/'), + ('Hanionly','http://www.hani.co.kr/rss/hanionly/'), + ('Hkronly','http://www.hani.co.kr/rss/hkronly/'), + ('Multihani','http://www.hani.co.kr/rss/multihani/'), + ('Lead','http://www.hani.co.kr/rss/lead/'), + ('Newsrank','http://www.hani.co.kr/rss/newsrank/'), + ] diff --git a/recipes/hankyoreh21.recipe b/recipes/hankyoreh21.recipe index f49b4cc1ab..8e633b4ebe 100644 --- a/recipes/hankyoreh21.recipe +++ b/recipes/hankyoreh21.recipe @@ -1,25 +1,25 @@ -__license__ = 'GPL v3' -__copyright__ = '2011, Seongkyoun Yoo ' -''' -Profile to download The Hankyoreh -''' -from calibre.web.feeds.news import BasicNewsRecipe - -class Hankyoreh21(BasicNewsRecipe): - title = u'Hankyoreh21' - language = 'ko' - description = u'The Hankyoreh21 Magazine articles' - __author__ = 'Seongkyoun Yoo' - oldest_article = 20 - recursions = 1 - max_articles_per_feed = 120 - no_stylesheets = True - remove_javascript = True - keep_only_tags = [ - dict(name='font', attrs={'class':'t18bk'}), - dict(id=['fontSzArea']) - ] - - feeds = [ - ('Hani21','http://h21.hani.co.kr/rss/ '), - ] +__license__ = 'GPL v3' +__copyright__ = '2011, Seongkyoun Yoo ' +''' +Profile to download The Hankyoreh +''' +from calibre.web.feeds.news import BasicNewsRecipe + +class Hankyoreh21(BasicNewsRecipe): + title = u'Hankyoreh21' + language = 'ko' + description = u'The Hankyoreh21 Magazine articles' + __author__ = 'Seongkyoun Yoo' + oldest_article = 20 + recursions = 1 + max_articles_per_feed = 120 + no_stylesheets = True + remove_javascript = True + keep_only_tags = [ + dict(name='font', attrs={'class':'t18bk'}), + dict(id=['fontSzArea']) + ] + + feeds = [ + ('Hani21','http://h21.hani.co.kr/rss/ '), + ] diff --git a/recipes/huffingtonpost_uk.recipe b/recipes/huffingtonpost_uk.recipe index 92e941de5e..e57d302c19 100644 --- a/recipes/huffingtonpost_uk.recipe +++ b/recipes/huffingtonpost_uk.recipe @@ -1,47 +1,47 @@ -from calibre.web.feeds.news import BasicNewsRecipe - -class HindustanTimes(BasicNewsRecipe): - title = u'Huffington Post UK' - language = 'en_GB' - __author__ = 'Krittika Goyal' - oldest_article = 2 #days - max_articles_per_feed = 25 - #encoding = 'cp1252' - use_embedded_content = False - - no_stylesheets = True - auto_cleanup = True - auto_cleanup_keep = '//div[@class="articleBody"]' - - feeds = [ -('UK Politics', - 'http://www.huffingtonpost.com/feeds/verticals/uk-politics/news.xml'), -('UK Entertainment', - 'http://www.huffingtonpost.com/feeds/verticals/uk-entertainment/news.xml'), -('UK Style', - 'http://www.huffingtonpost.com/feeds/verticals/uk-style/news.xml'), -('UK Fashion:', - 'http://www.huffingtonpost.com/feeds/verticals/uk-fashion/news.xml'), -('UK Universities:', - 'http://www.huffingtonpost.com/feeds/verticals/uk-universities-education/news.xml'), -('UK World', - 'http://www.huffingtonpost.com/feeds/verticals/uk-world/news.xml'), -('UK Lifestyle', - 'http://www.huffingtonpost.com/feeds/verticals/uk-lifestyle/news.xml'), -('UK Comedy', - 'http://www.huffingtonpost.com/feeds/verticals/uk-comedy/news.xml'), -('UK Celebrity', - 'http://www.huffingtonpost.com/feeds/verticals/uk-celebrity/news.xml'), -('UK Culture', - 'http://www.huffingtonpost.com/feeds/verticals/uk-culture/news.xml'), -('UK News', - 'http://www.huffingtonpost.com/feeds/verticals/uk/news.xml'), -('UK Tech', - 'http://www.huffingtonpost.com/feeds/verticals/uk-tech/news.xml'), -('UK Sport', - 'http://www.huffingtonpost.com/feeds/verticals/uk-sport/news.xml'), - ] - def get_article_url(self, entry): - if entry.links: - return entry.links[0]['href'] - return BasicNewsRecipe.get_article_url(self, entry) +from calibre.web.feeds.news import BasicNewsRecipe + +class HindustanTimes(BasicNewsRecipe): + title = u'Huffington Post UK' + language = 'en_GB' + __author__ = 'Krittika Goyal' + oldest_article = 2 #days + max_articles_per_feed = 25 + #encoding = 'cp1252' + use_embedded_content = False + + no_stylesheets = True + auto_cleanup = True + auto_cleanup_keep = '//div[@class="articleBody"]' + + feeds = [ +('UK Politics', + 'http://www.huffingtonpost.com/feeds/verticals/uk-politics/news.xml'), +('UK Entertainment', + 'http://www.huffingtonpost.com/feeds/verticals/uk-entertainment/news.xml'), +('UK Style', + 'http://www.huffingtonpost.com/feeds/verticals/uk-style/news.xml'), +('UK Fashion:', + 'http://www.huffingtonpost.com/feeds/verticals/uk-fashion/news.xml'), +('UK Universities:', + 'http://www.huffingtonpost.com/feeds/verticals/uk-universities-education/news.xml'), +('UK World', + 'http://www.huffingtonpost.com/feeds/verticals/uk-world/news.xml'), +('UK Lifestyle', + 'http://www.huffingtonpost.com/feeds/verticals/uk-lifestyle/news.xml'), +('UK Comedy', + 'http://www.huffingtonpost.com/feeds/verticals/uk-comedy/news.xml'), +('UK Celebrity', + 'http://www.huffingtonpost.com/feeds/verticals/uk-celebrity/news.xml'), +('UK Culture', + 'http://www.huffingtonpost.com/feeds/verticals/uk-culture/news.xml'), +('UK News', + 'http://www.huffingtonpost.com/feeds/verticals/uk/news.xml'), +('UK Tech', + 'http://www.huffingtonpost.com/feeds/verticals/uk-tech/news.xml'), +('UK Sport', + 'http://www.huffingtonpost.com/feeds/verticals/uk-sport/news.xml'), + ] + def get_article_url(self, entry): + if entry.links: + return entry.links[0]['href'] + return BasicNewsRecipe.get_article_url(self, entry) diff --git a/recipes/ilmanifesto.recipe b/recipes/ilmanifesto.recipe index d7428cebb2..cd503dfbde 100644 --- a/recipes/ilmanifesto.recipe +++ b/recipes/ilmanifesto.recipe @@ -1,110 +1,110 @@ -from calibre import strftime -from calibre.web.feeds.recipes import BasicNewsRecipe -from calibre.ebooks.BeautifulSoup import BeautifulSoup - -MANIFESTO_BASEURL = 'http://www.ilmanifesto.it/' - -class IlManifesto(BasicNewsRecipe): - title = 'Il Manifesto' - __author__ = 'Giacomo Lacava' - description = 'quotidiano comunista - ultima edizione html disponibile' - publication_type = 'newspaper' - publisher = 'il manifesto coop. editrice a r.l.' - language = 'it' - - oldest_article = 2 - max_articles_per_feed = 100 - delay = 1 - no_stylesheets = True - simultaneous_downloads = 5 - timeout = 30 - auto_cleanup = True - remove_tags = [dict(name='div', attrs={'class':'column_1 float_left'})] - remove_tags_before = dict(name='div',attrs={'class':'column_2 float_right'}) - remove_tags_after = dict(id='myPrintArea') - - manifesto_index = None - manifesto_datestr = None - - def _set_manifesto_index(self): - if self.manifesto_index == None: - startUrl = MANIFESTO_BASEURL + 'area-abbonati/in-edicola/' - startSoup = self.index_to_soup(startUrl) - lastEdition = startSoup.findAll('div',id='accordion_inedicola')[1].find('a')['href'] - del(startSoup) - self.manifesto_index = MANIFESTO_BASEURL + lastEdition - urlsplit = lastEdition.split('/') - self.manifesto_datestr = urlsplit[-1] - if urlsplit[-1] == '': - self.manifesto_datestr = urlsplit[-2] - - - - def get_cover_url(self): - self._set_manifesto_index() - url = MANIFESTO_BASEURL + 'fileadmin/archivi/in_edicola/%sprimapagina.gif' % self.manifesto_datestr - return url - - def parse_index(self): - self._set_manifesto_index() - soup = self.index_to_soup(self.manifesto_index) - feedLinks = soup.find('div',id='accordion_inedicola').findAll('a') - result = [] - for feed in feedLinks: - articles = [] - feedName = feed.find('h2').string - feedUrl = MANIFESTO_BASEURL + feed['href'] - feedSoup = self.index_to_soup(feedUrl) - indexRoot = feedSoup.find('div',attrs={'class':'column1'}) - for div in indexRoot.findAll('div',attrs={'class':'strumenti1_inedicola'}): - artLink = div.find('a') - if artLink is None: continue # empty div - title = artLink.string - url = MANIFESTO_BASEURL + artLink['href'] - - description = '' - descNode = div.find('div',attrs={'class':'text_12'}) - if descNode is not None: - description = descNode.string - - author = '' - authNode = div.find('div',attrs={'class':'firma'}) - if authNode is not None: - author = authNode.string - - articleText = '' - article = { - 'title':title, - 'url':url, - 'date': strftime('%d %B %Y'), - 'description': description, - 'content': articleText, - 'author': author - } - articles.append(article) - result.append((feedName,articles)) - return result - - - def extract_readable_article(self, html, url): - - bs = BeautifulSoup(html) - col1 = bs.find('div',attrs={'class':'column1'}) - - content = col1.find('div',attrs={'class':'bodytext'}) - title = bs.find(id='titolo_articolo').string - author = col1.find('span',attrs={'class':'firma'}) - subtitle = '' - subNode = col1.findPrevious('div',attrs={'class':'occhiello_rosso'}) - if subNode is not None: - subtitle = subNode - summary = '' - sommNode = bs.find('div',attrs={'class':'sommario'}) - if sommNode is not None: - summary = sommNode - - template = "%(title)s

%(title)s

%(subtitle)s

%(author)s

%(summary)s
%(content)s
" - del(bs) - return template % dict(title=title,subtitle=subtitle,author=author,summary=summary,content=content) - - +from calibre import strftime +from calibre.web.feeds.recipes import BasicNewsRecipe +from calibre.ebooks.BeautifulSoup import BeautifulSoup + +MANIFESTO_BASEURL = 'http://www.ilmanifesto.it/' + +class IlManifesto(BasicNewsRecipe): + title = 'Il Manifesto' + __author__ = 'Giacomo Lacava' + description = 'quotidiano comunista - ultima edizione html disponibile' + publication_type = 'newspaper' + publisher = 'il manifesto coop. editrice a r.l.' + language = 'it' + + oldest_article = 2 + max_articles_per_feed = 100 + delay = 1 + no_stylesheets = True + simultaneous_downloads = 5 + timeout = 30 + auto_cleanup = True + remove_tags = [dict(name='div', attrs={'class':'column_1 float_left'})] + remove_tags_before = dict(name='div',attrs={'class':'column_2 float_right'}) + remove_tags_after = dict(id='myPrintArea') + + manifesto_index = None + manifesto_datestr = None + + def _set_manifesto_index(self): + if self.manifesto_index == None: + startUrl = MANIFESTO_BASEURL + 'area-abbonati/in-edicola/' + startSoup = self.index_to_soup(startUrl) + lastEdition = startSoup.findAll('div',id='accordion_inedicola')[1].find('a')['href'] + del(startSoup) + self.manifesto_index = MANIFESTO_BASEURL + lastEdition + urlsplit = lastEdition.split('/') + self.manifesto_datestr = urlsplit[-1] + if urlsplit[-1] == '': + self.manifesto_datestr = urlsplit[-2] + + + + def get_cover_url(self): + self._set_manifesto_index() + url = MANIFESTO_BASEURL + 'fileadmin/archivi/in_edicola/%sprimapagina.gif' % self.manifesto_datestr + return url + + def parse_index(self): + self._set_manifesto_index() + soup = self.index_to_soup(self.manifesto_index) + feedLinks = soup.find('div',id='accordion_inedicola').findAll('a') + result = [] + for feed in feedLinks: + articles = [] + feedName = feed.find('h2').string + feedUrl = MANIFESTO_BASEURL + feed['href'] + feedSoup = self.index_to_soup(feedUrl) + indexRoot = feedSoup.find('div',attrs={'class':'column1'}) + for div in indexRoot.findAll('div',attrs={'class':'strumenti1_inedicola'}): + artLink = div.find('a') + if artLink is None: continue # empty div + title = artLink.string + url = MANIFESTO_BASEURL + artLink['href'] + + description = '' + descNode = div.find('div',attrs={'class':'text_12'}) + if descNode is not None: + description = descNode.string + + author = '' + authNode = div.find('div',attrs={'class':'firma'}) + if authNode is not None: + author = authNode.string + + articleText = '' + article = { + 'title':title, + 'url':url, + 'date': strftime('%d %B %Y'), + 'description': description, + 'content': articleText, + 'author': author + } + articles.append(article) + result.append((feedName,articles)) + return result + + + def extract_readable_article(self, html, url): + + bs = BeautifulSoup(html) + col1 = bs.find('div',attrs={'class':'column1'}) + + content = col1.find('div',attrs={'class':'bodytext'}) + title = bs.find(id='titolo_articolo').string + author = col1.find('span',attrs={'class':'firma'}) + subtitle = '' + subNode = col1.findPrevious('div',attrs={'class':'occhiello_rosso'}) + if subNode is not None: + subtitle = subNode + summary = '' + sommNode = bs.find('div',attrs={'class':'sommario'}) + if sommNode is not None: + summary = sommNode + + template = "%(title)s

%(title)s

%(subtitle)s

%(author)s

%(summary)s
%(content)s
" + del(bs) + return template % dict(title=title,subtitle=subtitle,author=author,summary=summary,content=content) + + diff --git a/recipes/jakarta_globe.recipe b/recipes/jakarta_globe.recipe index 1414ac6e5b..f6f1715268 100644 --- a/recipes/jakarta_globe.recipe +++ b/recipes/jakarta_globe.recipe @@ -1,34 +1,34 @@ -from calibre.web.feeds.news import BasicNewsRecipe - -class JakartaGlobe(BasicNewsRecipe): - title = u'Jakarta Globe' - oldest_article = 3 - max_articles_per_feed = 100 - - feeds = [ - (u'News', u'http://www.thejakartaglobe.com/pages/getrss/getrss-news.php'), - (u'Business', u'http://www.thejakartaglobe.com/pages/getrss/getrss-business.php'), - (u'Technology', u'http://www.thejakartaglobe.com/pages/getrss/getrss-tech.php'), - (u'My Jakarta', u'http://www.thejakartaglobe.com/pages/getrss/getrss-myjakarta.php'), - (u'International', u'http://www.thejakartaglobe.com/pages/getrss/getrss-international.php'), - (u'Life and Times', u'http://www.thejakartaglobe.com/pages/getrss/getrss-lifeandtimes.php'), - ] - __author__ = 'rty' - pubisher = 'JakartaGlobe.com' - description = 'JakartaGlobe, Indonesia, Newspaper' - category = 'News, Indonesia' - - - remove_javascript = True - use_embedded_content = False - no_stylesheets = True - language = 'en_ID' - encoding = 'utf-8' - conversion_options = {'linearize_tables':True} - masthead_url = 'http://www.thejakartaglobe.com/pages/2010/images/jak-globe-logo.jpg' - keep_only_tags = [ - dict(name='div', attrs={'class':'story'}), - dict(name='span', attrs={'class':'headline'}), - dict(name='div', attrs={'class':'story'}), - dict(name='p', attrs={'id':'bodytext'}) - ] +from calibre.web.feeds.news import BasicNewsRecipe + +class JakartaGlobe(BasicNewsRecipe): + title = u'Jakarta Globe' + oldest_article = 3 + max_articles_per_feed = 100 + + feeds = [ + (u'News', u'http://www.thejakartaglobe.com/pages/getrss/getrss-news.php'), + (u'Business', u'http://www.thejakartaglobe.com/pages/getrss/getrss-business.php'), + (u'Technology', u'http://www.thejakartaglobe.com/pages/getrss/getrss-tech.php'), + (u'My Jakarta', u'http://www.thejakartaglobe.com/pages/getrss/getrss-myjakarta.php'), + (u'International', u'http://www.thejakartaglobe.com/pages/getrss/getrss-international.php'), + (u'Life and Times', u'http://www.thejakartaglobe.com/pages/getrss/getrss-lifeandtimes.php'), + ] + __author__ = 'rty' + pubisher = 'JakartaGlobe.com' + description = 'JakartaGlobe, Indonesia, Newspaper' + category = 'News, Indonesia' + + + remove_javascript = True + use_embedded_content = False + no_stylesheets = True + language = 'en_ID' + encoding = 'utf-8' + conversion_options = {'linearize_tables':True} + masthead_url = 'http://www.thejakartaglobe.com/pages/2010/images/jak-globe-logo.jpg' + keep_only_tags = [ + dict(name='div', attrs={'class':'story'}), + dict(name='span', attrs={'class':'headline'}), + dict(name='div', attrs={'class':'story'}), + dict(name='p', attrs={'id':'bodytext'}) + ] diff --git a/recipes/kompiutierra.recipe b/recipes/kompiutierra.recipe index a82db9aced..3b65845c9a 100644 --- a/recipes/kompiutierra.recipe +++ b/recipes/kompiutierra.recipe @@ -1,37 +1,37 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -__license__ = 'GPL v3' -__copyright__ = '2010, Vadim Dyadkin, dyadkin@gmail.com' -__author__ = 'Vadim Dyadkin' - -from calibre.web.feeds.news import BasicNewsRecipe - -class Computerra(BasicNewsRecipe): - title = u'\u041a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0440\u0430' - oldest_article = 100 - __author__ = 'Vadim Dyadkin (edited by A. Chewi)' - max_articles_per_feed = 50 - use_embedded_content = False - remove_javascript = True - no_stylesheets = True - conversion_options = {'linearize_tables' : True} - simultaneous_downloads = 5 - language = 'ru' - description = u'Компьютерра: все новости про компьютеры, железо, новые технологии, информационные технологии' - - keep_only_tags = [dict(name='div', attrs={'id': 'content'}),] - - feeds = [(u'Компьютерра-Онлайн', 'http://feeds.feedburner.com/ct_news/'),] - - remove_tags = [ - dict(name='div', attrs={'id': ['fin', 'idc-container', 'idc-noscript',]}), - dict(name='ul', attrs={'class': "related_post"}), - dict(name='p', attrs={'class': 'info'}), - dict(name='a', attrs={'class': 'twitter-share-button'}), - dict(name='a', attrs={'type': 'button_count'}), - dict(name='h2', attrs={}) - ] - - def print_version(self, url): - return url + '?print=true' +#!/usr/bin/python +# -*- coding: utf-8 -*- + +__license__ = 'GPL v3' +__copyright__ = '2010, Vadim Dyadkin, dyadkin@gmail.com' +__author__ = 'Vadim Dyadkin' + +from calibre.web.feeds.news import BasicNewsRecipe + +class Computerra(BasicNewsRecipe): + title = u'\u041a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0440\u0430' + oldest_article = 100 + __author__ = 'Vadim Dyadkin (edited by A. Chewi)' + max_articles_per_feed = 50 + use_embedded_content = False + remove_javascript = True + no_stylesheets = True + conversion_options = {'linearize_tables' : True} + simultaneous_downloads = 5 + language = 'ru' + description = u'Компьютерра: все новости про компьютеры, железо, новые технологии, информационные технологии' + + keep_only_tags = [dict(name='div', attrs={'id': 'content'}),] + + feeds = [(u'Компьютерра-Онлайн', 'http://feeds.feedburner.com/ct_news/'),] + + remove_tags = [ + dict(name='div', attrs={'id': ['fin', 'idc-container', 'idc-noscript',]}), + dict(name='ul', attrs={'class': "related_post"}), + dict(name='p', attrs={'class': 'info'}), + dict(name='a', attrs={'class': 'twitter-share-button'}), + dict(name='a', attrs={'type': 'button_count'}), + dict(name='h2', attrs={}) + ] + + def print_version(self, url): + return url + '?print=true' diff --git a/recipes/leipzer_volkszeitung.recipe b/recipes/leipzer_volkszeitung.recipe index 807ec5282e..b0b8fd64a4 100644 --- a/recipes/leipzer_volkszeitung.recipe +++ b/recipes/leipzer_volkszeitung.recipe @@ -1,34 +1,34 @@ -from calibre.web.feeds.recipes import BasicNewsRecipe - -'''Calibre recipe to convert the RSS feeds of the Leipziger Volkszeitung to an ebook.''' - -class SportsIllustratedRecipe(BasicNewsRecipe) : - __author__ = 'a.peter' - __copyright__ = 'a.peter' - __license__ = 'GPL v3' - language = 'de' - description = 'Leipziger Volkszeitung Online RSS' - version = 1 - title = u'Leipziger Volkszeitung Online RSS' - timefmt = ' [%d.%m.%Y]' - - no_stylesheets = True - remove_javascript = True - use_embedded_content = False - publication_type = 'newspaper' - - keep_only_tags = [dict(name='div', attrs={'class':'article'})] - remove_tags = [dict(name='div', attrs={'class':['ARTICLE_MORE', 'clearfloat']})] - - feeds = [(u'Leipzig', u'http://nachrichten.lvz-online.de/rss/leipzig-rss.xml'), - (u'Mitteldeutschland', u'http://nachrichten.lvz-online.de/rss/mitteldeutschland-rss.xml'), - (u'Brennpunkte', u'http://nachrichten.lvz-online.de/rss/brennpunkte-rss.xml'), - (u'Polizeiticker', u'http://nachrichten.lvz-online.de/rss/polizeiticker-rss.xml'), - (u'Boulevard', u'http://nachrichten.lvz-online.de/rss/boulevard-rss.xml'), - (u'Kultur', u'http://nachrichten.lvz-online.de/rss/kultur-rss.xml'), - (u'Sport', u'http://nachrichten.lvz-online.de/rss/sport-rss.xml'), - (u'Regionalsport', u'http://nachrichten.lvz-online.de/rss/regionalsport-rss.xml'), - (u'Knipser', u'http://nachrichten.lvz-online.de/rss/knipser-rss.xml')] - - def get_masthead_url(self): - return 'http://www.lvz-online.de/resources/themes/standard/images/global/logo.gif' +from calibre.web.feeds.recipes import BasicNewsRecipe + +'''Calibre recipe to convert the RSS feeds of the Leipziger Volkszeitung to an ebook.''' + +class SportsIllustratedRecipe(BasicNewsRecipe) : + __author__ = 'a.peter' + __copyright__ = 'a.peter' + __license__ = 'GPL v3' + language = 'de' + description = 'Leipziger Volkszeitung Online RSS' + version = 1 + title = u'Leipziger Volkszeitung Online RSS' + timefmt = ' [%d.%m.%Y]' + + no_stylesheets = True + remove_javascript = True + use_embedded_content = False + publication_type = 'newspaper' + + keep_only_tags = [dict(name='div', attrs={'class':'article'})] + remove_tags = [dict(name='div', attrs={'class':['ARTICLE_MORE', 'clearfloat']})] + + feeds = [(u'Leipzig', u'http://nachrichten.lvz-online.de/rss/leipzig-rss.xml'), + (u'Mitteldeutschland', u'http://nachrichten.lvz-online.de/rss/mitteldeutschland-rss.xml'), + (u'Brennpunkte', u'http://nachrichten.lvz-online.de/rss/brennpunkte-rss.xml'), + (u'Polizeiticker', u'http://nachrichten.lvz-online.de/rss/polizeiticker-rss.xml'), + (u'Boulevard', u'http://nachrichten.lvz-online.de/rss/boulevard-rss.xml'), + (u'Kultur', u'http://nachrichten.lvz-online.de/rss/kultur-rss.xml'), + (u'Sport', u'http://nachrichten.lvz-online.de/rss/sport-rss.xml'), + (u'Regionalsport', u'http://nachrichten.lvz-online.de/rss/regionalsport-rss.xml'), + (u'Knipser', u'http://nachrichten.lvz-online.de/rss/knipser-rss.xml')] + + def get_masthead_url(self): + return 'http://www.lvz-online.de/resources/themes/standard/images/global/logo.gif' diff --git a/recipes/lifehacker.recipe b/recipes/lifehacker.recipe index e96b031dab..375820d4b0 100644 --- a/recipes/lifehacker.recipe +++ b/recipes/lifehacker.recipe @@ -1,100 +1,100 @@ -from calibre.web.feeds.news import BasicNewsRecipe -from datetime import datetime -from calibre.ebooks.BeautifulSoup import Tag -from calibre.utils.magick import Image, PixelWand - -class LifeHacker(BasicNewsRecipe): - THUMBALIZR_API = '' # ---->Get your at http://www.thumbalizr.com/ and put here - LANGUAGE = 'en' - LANGHTM = 'en' - language = 'en' - ENCODING = 'utf' - ENCHTM = 'utf-8' - requires_version = (0,7,47) - news = True - - title = u'LifeHacker' - __author__ = 'Euler Alves' - description = u'Tips, tricks, and downloads for getting things done.' - publisher = u'lifehacker.com' - author = u'Adam Pash & Kevin Purdy & Adam Dachis & Whitson Gordon & Gina Trapani' - category = 'news, rss' - - oldest_article = 4 - max_articles_per_feed = 20 - summary_length = 1000 - - remove_javascript = True - no_stylesheets = True - use_embedded_content = True - remove_empty_feeds = True - timefmt = ' [%d %b %Y (%a)]' - - hoje = datetime.now() - pubdate = hoje.strftime('%a, %d %b') - cover_url = 'http://api.thumbalizr.com/?api_key='+THUMBALIZR_API+'&url=http://lifehacker.com&width=600&quality=90' - cover_margins = (0,0,'white') - masthead_url = 'http://cache.gawkerassets.com/assets/lifehacker.com/img/logo.png' - - remove_tags = [ - {'class': 'feedflare'}, - dict(name='div', - attrs={'class':[ - 'ad_container' - ,'ad_300x250' - ,'ad_interstitial' - ,'share-wrap' - ,'ad_300x600' - ,'ad_perma-footer-adsense' - ,'ad_perma-panorama' - ,'ad panorama' - ,'ad_container' - ]}) - ,dict(name='div', - attrs={'id':[ - 'agegate_container' - ,'agegate_container_rejected' - ,'sharemenu-wrap' - ]}) - ] - - feeds = [(u'Articles', u'http://feeds.gawker.com/lifehacker/vip?format=xml')] - - conversion_options = { - 'title' : title - ,'comments' : description - ,'publisher' : publisher - ,'tags' : category - ,'language' : LANGUAGE - ,'linearize_tables': True - } - - def preprocess_html(self, soup): - for item in soup.findAll(style=True): - del item['style'] - if not soup.find(attrs={'http-equiv':'Content-Language'}): - meta0 = Tag(soup,'meta',[("http-equiv","Content-Language"),("content",self.LANGHTM)]) - soup.head.insert(0,meta0) - if not soup.find(attrs={'http-equiv':'Content-Type'}): - meta1 = Tag(soup,'meta',[("http-equiv","Content-Type"),("content","text/html; charset="+self.ENCHTM)]) - soup.head.insert(0,meta1) - return soup - - def postprocess_html(self, soup, first): - #process all the images. assumes that the new html has the correct path - for tag in soup.findAll(lambda tag: tag.name.lower()=='img' and tag.has_key('src')): - iurl = tag['src'] - img = Image() - img.open(iurl) - width, height = img.size - print 'img is: ', iurl, 'width is: ', width, 'height is: ', height - if img < 0: - raise RuntimeError('Out of memory') - pw = PixelWand() - if( width > height and width > 590) : - print 'Rotate image' - img.rotate(pw, -90) - img.save(iurl) - return soup - - +from calibre.web.feeds.news import BasicNewsRecipe +from datetime import datetime +from calibre.ebooks.BeautifulSoup import Tag +from calibre.utils.magick import Image, PixelWand + +class LifeHacker(BasicNewsRecipe): + THUMBALIZR_API = '' # ---->Get your at http://www.thumbalizr.com/ and put here + LANGUAGE = 'en' + LANGHTM = 'en' + language = 'en' + ENCODING = 'utf' + ENCHTM = 'utf-8' + requires_version = (0,7,47) + news = True + + title = u'LifeHacker' + __author__ = 'Euler Alves' + description = u'Tips, tricks, and downloads for getting things done.' + publisher = u'lifehacker.com' + author = u'Adam Pash & Kevin Purdy & Adam Dachis & Whitson Gordon & Gina Trapani' + category = 'news, rss' + + oldest_article = 4 + max_articles_per_feed = 20 + summary_length = 1000 + + remove_javascript = True + no_stylesheets = True + use_embedded_content = True + remove_empty_feeds = True + timefmt = ' [%d %b %Y (%a)]' + + hoje = datetime.now() + pubdate = hoje.strftime('%a, %d %b') + cover_url = 'http://api.thumbalizr.com/?api_key='+THUMBALIZR_API+'&url=http://lifehacker.com&width=600&quality=90' + cover_margins = (0,0,'white') + masthead_url = 'http://cache.gawkerassets.com/assets/lifehacker.com/img/logo.png' + + remove_tags = [ + {'class': 'feedflare'}, + dict(name='div', + attrs={'class':[ + 'ad_container' + ,'ad_300x250' + ,'ad_interstitial' + ,'share-wrap' + ,'ad_300x600' + ,'ad_perma-footer-adsense' + ,'ad_perma-panorama' + ,'ad panorama' + ,'ad_container' + ]}) + ,dict(name='div', + attrs={'id':[ + 'agegate_container' + ,'agegate_container_rejected' + ,'sharemenu-wrap' + ]}) + ] + + feeds = [(u'Articles', u'http://feeds.gawker.com/lifehacker/vip?format=xml')] + + conversion_options = { + 'title' : title + ,'comments' : description + ,'publisher' : publisher + ,'tags' : category + ,'language' : LANGUAGE + ,'linearize_tables': True + } + + def preprocess_html(self, soup): + for item in soup.findAll(style=True): + del item['style'] + if not soup.find(attrs={'http-equiv':'Content-Language'}): + meta0 = Tag(soup,'meta',[("http-equiv","Content-Language"),("content",self.LANGHTM)]) + soup.head.insert(0,meta0) + if not soup.find(attrs={'http-equiv':'Content-Type'}): + meta1 = Tag(soup,'meta',[("http-equiv","Content-Type"),("content","text/html; charset="+self.ENCHTM)]) + soup.head.insert(0,meta1) + return soup + + def postprocess_html(self, soup, first): + #process all the images. assumes that the new html has the correct path + for tag in soup.findAll(lambda tag: tag.name.lower()=='img' and tag.has_key('src')): + iurl = tag['src'] + img = Image() + img.open(iurl) + width, height = img.size + print 'img is: ', iurl, 'width is: ', width, 'height is: ', height + if img < 0: + raise RuntimeError('Out of memory') + pw = PixelWand() + if( width > height and width > 590) : + print 'Rotate image' + img.rotate(pw, -90) + img.save(iurl) + return soup + + diff --git a/recipes/melbourne_herald_sun.recipe b/recipes/melbourne_herald_sun.recipe index c24a4563af..23b1e2c726 100644 --- a/recipes/melbourne_herald_sun.recipe +++ b/recipes/melbourne_herald_sun.recipe @@ -1,85 +1,85 @@ -#!/usr/bin/env python -__license__ = 'GPL v3' -__copyright__ = '2009, Matthew Briggs' -__docformat__ = 'restructuredtext en' - -''' -http://www.herald sun.com.au/ -''' - -from calibre.web.feeds.news import BasicNewsRecipe - -class DailyTelegraph(BasicNewsRecipe): - title = u'Melbourne Herald Sun' - __author__ = u'Ray Hartley' - description = (u'Victorian and National News' - '. You will need to have a subscription to ' - 'http://www.heraldsun.com.au to get full articles.') - language = 'en_AU' - - oldest_article = 2 - needs_subscription = 'optional' - max_articles_per_feed = 30 - remove_javascript = True - no_stylesheets = True - encoding = 'utf8' - use_embedded_content = False - language = 'en_AU' - remove_empty_feeds = True - publication_type = 'newspaper' - masthead_url = 'http://resources2.news.com.au/cs/heraldsun/images/header-and-footer/logo.gif' - extra_css = """ - body{font-family: Arial,Helvetica,sans-serif } - img{margin-bottom: 0.4em; display:block} - .caption{display: inline; font-size: x-small} - """ - - conversion_options = { - 'comment' : description - , 'language' : language - } - - keep_only_tags = [dict(attrs={'id':'story'})] - remove_tags_before=dict(attrs={'class':'story-header'}) - remove_tags_after=dict(attrs={'class':'story-footer'}) - remove_tags = [ - dict(name=['meta','link','base','iframe','embed','object','media-metadata','media-reference','media-producer']) - ,dict(attrs={'class':['story-header-tools','story-sidebar','story-footer','story-summary-list']}) - ] - remove_attributes=['lang'] - - - feeds = [(u'Breaking News' , u'http://feeds.news.com.au/public/rss/2.0/heraldsun_breakingnews_206.xml' ) - ,(u'Business' , u'http://feeds.news.com.au/public/rss/2.0/heraldsun_business_207.xml' ) - ,(u'Entertainment' , u'http://feeds.news.com.au/public/rss/2.0/heraldsun_entertainment_208.xml' ) - ,(u'Health Science' , u'http://feeds.news.com.au/public/rss/2.0/heraldsun_health_212.xml' ) - ,(u'Music' , u'http://feeds.news.com.au/public/rss/2.0/heraldsun_music_449.xml' ) - ,(u'National News' , u'http://feeds.news.com.au/public/rss/2.0/heraldsun_national_209.xml' ) - ,(u'Sport News' , u'http://feeds.news.com.au/public/rss/2.0/heraldsun_sport_213.xml' ) - ,(u'AFL News' , u'http://feeds.news.com.au/public/rss/2.0/heraldsun_afl_205.xml' ) - ,(u'State News' , u'http://feeds.news.com.au/public/rss/2.0/heraldsun_vic_214.xml' ) - ,(u'Technology' , u'http://feeds.news.com.au/public/rss/2.0/heraldsun_tech_215.xml' ) - ,(u'World News' , u'http://feeds.news.com.au/public/rss/2.0/heraldsun_world_216.xml' ) - ,(u'Opinion', u'http://feeds.news.com.au/public/rss/2.0/heraldsun_opinion_210.xml' ) - ,(u'Andrew Bolt' , u'http://blogs.news.com.au/heraldsun/andrewbolt/index.php/xml/rss_2.0/heraldsun/hs_andrewbolt/') - ,(u'Afl - St Kilda' , u'http://feeds.news.com.au/public/rss/2.0/heraldsun_afl_stkilda_565.xml') - ,(u'Terry McCrann' ,u'http://feeds.news.com.au/public/rss/2.0/heraldsun_tmccrann_224.xml' ) - ,(u'The Other side' ,u'http://feeds.news.com.au/public/rss/2.0/heraldsun_otherside_211.xml')] - - def get_browser(self): - br = BasicNewsRecipe.get_browser(self) - if self.username and self.password: - br.open('http://www.heraldsun.com.au') - br.select_form(nr=0) - br['username'] = self.username - br['password'] = self.password - raw = br.submit().read() - if '>log out' not in raw.lower(): - raise ValueError('Failed to log in to www.heralsun' - ' are your username and password correct?') - return br - - def get_article_url(self, article): - return article.id - - +#!/usr/bin/env python +__license__ = 'GPL v3' +__copyright__ = '2009, Matthew Briggs' +__docformat__ = 'restructuredtext en' + +''' +http://www.herald sun.com.au/ +''' + +from calibre.web.feeds.news import BasicNewsRecipe + +class DailyTelegraph(BasicNewsRecipe): + title = u'Melbourne Herald Sun' + __author__ = u'Ray Hartley' + description = (u'Victorian and National News' + '. You will need to have a subscription to ' + 'http://www.heraldsun.com.au to get full articles.') + language = 'en_AU' + + oldest_article = 2 + needs_subscription = 'optional' + max_articles_per_feed = 30 + remove_javascript = True + no_stylesheets = True + encoding = 'utf8' + use_embedded_content = False + language = 'en_AU' + remove_empty_feeds = True + publication_type = 'newspaper' + masthead_url = 'http://resources2.news.com.au/cs/heraldsun/images/header-and-footer/logo.gif' + extra_css = """ + body{font-family: Arial,Helvetica,sans-serif } + img{margin-bottom: 0.4em; display:block} + .caption{display: inline; font-size: x-small} + """ + + conversion_options = { + 'comment' : description + , 'language' : language + } + + keep_only_tags = [dict(attrs={'id':'story'})] + remove_tags_before=dict(attrs={'class':'story-header'}) + remove_tags_after=dict(attrs={'class':'story-footer'}) + remove_tags = [ + dict(name=['meta','link','base','iframe','embed','object','media-metadata','media-reference','media-producer']) + ,dict(attrs={'class':['story-header-tools','story-sidebar','story-footer','story-summary-list']}) + ] + remove_attributes=['lang'] + + + feeds = [(u'Breaking News' , u'http://feeds.news.com.au/public/rss/2.0/heraldsun_breakingnews_206.xml' ) + ,(u'Business' , u'http://feeds.news.com.au/public/rss/2.0/heraldsun_business_207.xml' ) + ,(u'Entertainment' , u'http://feeds.news.com.au/public/rss/2.0/heraldsun_entertainment_208.xml' ) + ,(u'Health Science' , u'http://feeds.news.com.au/public/rss/2.0/heraldsun_health_212.xml' ) + ,(u'Music' , u'http://feeds.news.com.au/public/rss/2.0/heraldsun_music_449.xml' ) + ,(u'National News' , u'http://feeds.news.com.au/public/rss/2.0/heraldsun_national_209.xml' ) + ,(u'Sport News' , u'http://feeds.news.com.au/public/rss/2.0/heraldsun_sport_213.xml' ) + ,(u'AFL News' , u'http://feeds.news.com.au/public/rss/2.0/heraldsun_afl_205.xml' ) + ,(u'State News' , u'http://feeds.news.com.au/public/rss/2.0/heraldsun_vic_214.xml' ) + ,(u'Technology' , u'http://feeds.news.com.au/public/rss/2.0/heraldsun_tech_215.xml' ) + ,(u'World News' , u'http://feeds.news.com.au/public/rss/2.0/heraldsun_world_216.xml' ) + ,(u'Opinion', u'http://feeds.news.com.au/public/rss/2.0/heraldsun_opinion_210.xml' ) + ,(u'Andrew Bolt' , u'http://blogs.news.com.au/heraldsun/andrewbolt/index.php/xml/rss_2.0/heraldsun/hs_andrewbolt/') + ,(u'Afl - St Kilda' , u'http://feeds.news.com.au/public/rss/2.0/heraldsun_afl_stkilda_565.xml') + ,(u'Terry McCrann' ,u'http://feeds.news.com.au/public/rss/2.0/heraldsun_tmccrann_224.xml' ) + ,(u'The Other side' ,u'http://feeds.news.com.au/public/rss/2.0/heraldsun_otherside_211.xml')] + + def get_browser(self): + br = BasicNewsRecipe.get_browser(self) + if self.username and self.password: + br.open('http://www.heraldsun.com.au') + br.select_form(nr=0) + br['username'] = self.username + br['password'] = self.password + raw = br.submit().read() + if '>log out' not in raw.lower(): + raise ValueError('Failed to log in to www.heralsun' + ' are your username and password correct?') + return br + + def get_article_url(self, article): + return article.id + + diff --git a/recipes/menorca.recipe b/recipes/menorca.recipe index 9a5afa665a..33f7741571 100644 --- a/recipes/menorca.recipe +++ b/recipes/menorca.recipe @@ -1,138 +1,138 @@ -# -*- coding: utf-8 -*- - -import re -from calibre.web.feeds.recipes import BasicNewsRecipe -from calibre.web.feeds import Feed - -class Menorca(BasicNewsRecipe): - - title = 'Menorca' - publisher = 'Editorial Menorca S.A. ' - __author__ = 'M. Sintes' - description = u'Peri\xf3dico con informaci\xf3n de Menorca, Espa\xf1a' - category = 'news, politics, economy, culture, Menorca, Spain ' - language = 'es' - enconding = 'cp1252' - - no_stylesheets = True - oldest_article = 5 - max_articles_per_feed = 25 - - - feeds = [ (u'Principal',u'http://www.menorca.info/rss'), - (u'Opini\xf3n',u'http://www.menorca.info/rss?seccion=opinion'), - (u'Menorca',u'http://www.menorca.info/rss?seccion=menorca'), - (u'Alaior',u'http://www.menorca.info/rss?seccion=pueblos/alaior'), - (u'Ciutadella', u'http://www.menorca.info/rss?seccion=pueblos/ciutadella'), - (u'Es Castell', u'http://www.menorca.info/rss?seccion=pueblos/escastell'), - (u'Es Mercadal', u'http://www.menorca.info/rss?seccion=pueblos/esmercadal'), - (u'Es Migjorn', u'http://www.menorca.info/rss?seccion=pueblos/esmigjorn'), - (u'Ferreries', u'http://www.menorca.info/rss?seccion=pueblos/ferreries'), - (u'Fornells', u'http://www.menorca.info/rss?seccion=pueblos/fornells'), - (u'Llucma\xe7anes', u'http://www.menorca.info/rss?seccion=pueblos/llucmaanes'), - (u'Ma\xf3', u'http://www.menorca.info/rss?seccion=pueblos/mao'), - (u'Sant Climent', u'http://www.menorca.info/rss?seccion=pueblos/santcliment'), - (u'Sant Llu\xeds', u'http://www.menorca.info/rss?seccion=pueblos/santlluis'), - (u'Deportes',u'http://www.menorca.info/rss?seccion=deportes'), - (u'Balears', u'http://www.menorca.info/rss?seccion=balears')] - - #Seccions amb link rss erroni. Es recupera directament de la pagina web - seccions_web = [(u'Mundo',u'http://www.menorca.info/actualidad/mundo'), - (u'Econom\xeda',u'http://www.menorca.info/actualidad/economia'), - (u'Espa\xf1a',u'http://www.menorca.info/actualidad/espana')] - - remove_tags_before = dict(name='div', attrs={'class':'bloqueTitulosNoticia'}) - remove_tags_after = dict(name='div', attrs={'class':'compartir'}) - remove_tags = [dict(id = 'utilidades'), - dict(name='div', attrs={'class': 'totalComentarios'}), - dict(name='div', attrs={'class': 'compartir'}), - dict(name='div', attrs={'class': re.compile("img_noticia*")}) - ] - - def print_version(self, url): - url_imprimir = url + '?d=print' - return url.replace(url, url_imprimir) - - def feed_to_index_append(self, feedObject, masterFeed): - - # Loop thru the feed object and build the correct type of article list - for feed in feedObject: - newArticles = [] - for article in feed.articles: - newArt = { - 'title' : article.title, - 'url' : article.url, - 'date' : article.date, - 'description' : article.text_summary - } - - newArticles.append(newArt) - - # append the newly-built list object to the index object # passed in as masterFeed. - masterFeed.append((feed.title,newArticles)) - - - def parse_index(self): - - rssFeeds = Feed() - rssFeeds = BasicNewsRecipe.parse_feeds(self) - - articles = [] - feeds = [] - - self.feed_to_index_append(rssFeeds,feeds) - - - - for (nom_seccio, url_seccio) in self.seccions_web: - - - articles = [] - - soup = self.index_to_soup(url_seccio) - for article in soup.findAll('div', attrs={'class':re.compile("articulo noticia|cajaNoticiaPortada")}): - h = article.find(['h2','h3']) - titol = self.tag_to_string(h) - a = article.find('a', href=True) - url = 'http://www.menorca.info' + a['href'] - - desc = None - autor = '' - dt = '' - - soup_art = self.index_to_soup(url) - aut = soup_art.find('div', attrs={'class':'autor'}) - tx = self.tag_to_string(aut) - ls = re.split('[,;]',tx) - - t = len(ls) - if t >= 1: - autor = ls[0] - - if t > 1: - d = ls[t-1] - - if len(d) >= 10: - lt = len(d) - 10 - dt = d[lt:] - - - - self.log('\tTrobat article: ', titol, 'a', url, 'Seccio: ', nom_seccio, 'Autor: ', autor, 'Data: ', dt) - - articles.append({'title': titol, 'url': url, 'description': desc, 'date':dt, 'author': autor}) - - - - - - if articles: - feeds.append((nom_seccio, articles)) - - - - - return feeds - - - +# -*- coding: utf-8 -*- + +import re +from calibre.web.feeds.recipes import BasicNewsRecipe +from calibre.web.feeds import Feed + +class Menorca(BasicNewsRecipe): + + title = 'Menorca' + publisher = 'Editorial Menorca S.A. ' + __author__ = 'M. Sintes' + description = u'Peri\xf3dico con informaci\xf3n de Menorca, Espa\xf1a' + category = 'news, politics, economy, culture, Menorca, Spain ' + language = 'es' + enconding = 'cp1252' + + no_stylesheets = True + oldest_article = 5 + max_articles_per_feed = 25 + + + feeds = [ (u'Principal',u'http://www.menorca.info/rss'), + (u'Opini\xf3n',u'http://www.menorca.info/rss?seccion=opinion'), + (u'Menorca',u'http://www.menorca.info/rss?seccion=menorca'), + (u'Alaior',u'http://www.menorca.info/rss?seccion=pueblos/alaior'), + (u'Ciutadella', u'http://www.menorca.info/rss?seccion=pueblos/ciutadella'), + (u'Es Castell', u'http://www.menorca.info/rss?seccion=pueblos/escastell'), + (u'Es Mercadal', u'http://www.menorca.info/rss?seccion=pueblos/esmercadal'), + (u'Es Migjorn', u'http://www.menorca.info/rss?seccion=pueblos/esmigjorn'), + (u'Ferreries', u'http://www.menorca.info/rss?seccion=pueblos/ferreries'), + (u'Fornells', u'http://www.menorca.info/rss?seccion=pueblos/fornells'), + (u'Llucma\xe7anes', u'http://www.menorca.info/rss?seccion=pueblos/llucmaanes'), + (u'Ma\xf3', u'http://www.menorca.info/rss?seccion=pueblos/mao'), + (u'Sant Climent', u'http://www.menorca.info/rss?seccion=pueblos/santcliment'), + (u'Sant Llu\xeds', u'http://www.menorca.info/rss?seccion=pueblos/santlluis'), + (u'Deportes',u'http://www.menorca.info/rss?seccion=deportes'), + (u'Balears', u'http://www.menorca.info/rss?seccion=balears')] + + #Seccions amb link rss erroni. Es recupera directament de la pagina web + seccions_web = [(u'Mundo',u'http://www.menorca.info/actualidad/mundo'), + (u'Econom\xeda',u'http://www.menorca.info/actualidad/economia'), + (u'Espa\xf1a',u'http://www.menorca.info/actualidad/espana')] + + remove_tags_before = dict(name='div', attrs={'class':'bloqueTitulosNoticia'}) + remove_tags_after = dict(name='div', attrs={'class':'compartir'}) + remove_tags = [dict(id = 'utilidades'), + dict(name='div', attrs={'class': 'totalComentarios'}), + dict(name='div', attrs={'class': 'compartir'}), + dict(name='div', attrs={'class': re.compile("img_noticia*")}) + ] + + def print_version(self, url): + url_imprimir = url + '?d=print' + return url.replace(url, url_imprimir) + + def feed_to_index_append(self, feedObject, masterFeed): + + # Loop thru the feed object and build the correct type of article list + for feed in feedObject: + newArticles = [] + for article in feed.articles: + newArt = { + 'title' : article.title, + 'url' : article.url, + 'date' : article.date, + 'description' : article.text_summary + } + + newArticles.append(newArt) + + # append the newly-built list object to the index object # passed in as masterFeed. + masterFeed.append((feed.title,newArticles)) + + + def parse_index(self): + + rssFeeds = Feed() + rssFeeds = BasicNewsRecipe.parse_feeds(self) + + articles = [] + feeds = [] + + self.feed_to_index_append(rssFeeds,feeds) + + + + for (nom_seccio, url_seccio) in self.seccions_web: + + + articles = [] + + soup = self.index_to_soup(url_seccio) + for article in soup.findAll('div', attrs={'class':re.compile("articulo noticia|cajaNoticiaPortada")}): + h = article.find(['h2','h3']) + titol = self.tag_to_string(h) + a = article.find('a', href=True) + url = 'http://www.menorca.info' + a['href'] + + desc = None + autor = '' + dt = '' + + soup_art = self.index_to_soup(url) + aut = soup_art.find('div', attrs={'class':'autor'}) + tx = self.tag_to_string(aut) + ls = re.split('[,;]',tx) + + t = len(ls) + if t >= 1: + autor = ls[0] + + if t > 1: + d = ls[t-1] + + if len(d) >= 10: + lt = len(d) - 10 + dt = d[lt:] + + + + self.log('\tTrobat article: ', titol, 'a', url, 'Seccio: ', nom_seccio, 'Autor: ', autor, 'Data: ', dt) + + articles.append({'title': titol, 'url': url, 'description': desc, 'date':dt, 'author': autor}) + + + + + + if articles: + feeds.append((nom_seccio, articles)) + + + + + return feeds + + + diff --git a/recipes/mobile_bulgaria.recipe b/recipes/mobile_bulgaria.recipe index 85440cf376..9c5db1a51a 100644 --- a/recipes/mobile_bulgaria.recipe +++ b/recipes/mobile_bulgaria.recipe @@ -1,27 +1,27 @@ -from calibre.web.feeds.news import BasicNewsRecipe - -class AdvancedUserRecipe1329123365(BasicNewsRecipe): - title = u'Mobilebulgaria.com' - __author__ = 'M3 Web' - description = 'The biggest Bulgarian site covering mobile consumer electronics. Offers detailed reviews, popular discussion forum, shop and platform for selling new and second hand phones and gadgets.' - category = 'News, Reviews, Offers, Forum' - oldest_article = 45 - max_articles_per_feed = 10 - language = 'bg' - encoding = 'windows-1251' - no_stylesheets = False - remove_javascript = True - keep_only_tags = [dict(name='div', attrs={'class':'bigblock'}), -dict(name='div', attrs={'class':'verybigblock'}), -dict(name='table', attrs={'class':'obiaviresults'}), -dict(name='div', attrs={'class':'forumblock'}), -dict(name='div', attrs={'class':'forumblock_b1'}), -dict(name='div', attrs={'class':'block2_2colswrap'})] - - feeds = [(u'News', u'http://www.mobilebulgaria.com/rss_full.php'), -(u'Reviews', u'http://www.mobilebulgaria.com/rss_reviews.php'), -(u'Offers', u'http://www.mobilebulgaria.com/obiavi/rss.php'), -(u'Forum', u'http://www.mobilebulgaria.com/rss_forum_last10.php')] - - extra_css = ''' - #gallery1 div{display: block; float: left; margin: 0 10px 10px 0;} ''' +from calibre.web.feeds.news import BasicNewsRecipe + +class AdvancedUserRecipe1329123365(BasicNewsRecipe): + title = u'Mobilebulgaria.com' + __author__ = 'M3 Web' + description = 'The biggest Bulgarian site covering mobile consumer electronics. Offers detailed reviews, popular discussion forum, shop and platform for selling new and second hand phones and gadgets.' + category = 'News, Reviews, Offers, Forum' + oldest_article = 45 + max_articles_per_feed = 10 + language = 'bg' + encoding = 'windows-1251' + no_stylesheets = False + remove_javascript = True + keep_only_tags = [dict(name='div', attrs={'class':'bigblock'}), +dict(name='div', attrs={'class':'verybigblock'}), +dict(name='table', attrs={'class':'obiaviresults'}), +dict(name='div', attrs={'class':'forumblock'}), +dict(name='div', attrs={'class':'forumblock_b1'}), +dict(name='div', attrs={'class':'block2_2colswrap'})] + + feeds = [(u'News', u'http://www.mobilebulgaria.com/rss_full.php'), +(u'Reviews', u'http://www.mobilebulgaria.com/rss_reviews.php'), +(u'Offers', u'http://www.mobilebulgaria.com/obiavi/rss.php'), +(u'Forum', u'http://www.mobilebulgaria.com/rss_forum_last10.php')] + + extra_css = ''' + #gallery1 div{display: block; float: left; margin: 0 10px 10px 0;} ''' diff --git a/recipes/mojegotowanie.recipe b/recipes/mojegotowanie.recipe index 4b0de4a0e1..1ac9aefcdc 100644 --- a/recipes/mojegotowanie.recipe +++ b/recipes/mojegotowanie.recipe @@ -15,7 +15,7 @@ class mojegotowanie(BasicNewsRecipe): language = 'pl' description =u'Gotowanie to Twoja pasja? Uwielbiasz sałatki? Lubisz grillować? Przepisy kulinarne doskonałe na wszystkie okazje znajdziesz na www.mojegotowanie.pl.' masthead_url='http://www.mojegotowanie.pl/extension/selfstart/design/self/images/top_c2.gif' - cover_url = 'http://www.mojegotowanie.pl/extension/selfstart/design/self/images/mgpl/mojegotowanie.gif' + cover_url = 'http://www.mojegotowanie.pl/extension/selfstart/design/self/images/mgpl/mojegotowanie.gif' remove_empty_feeds= True oldest_article = 7 max_articles_per_feed = 100 diff --git a/recipes/novinite.recipe b/recipes/novinite.recipe index a5af1f8aa4..281883915b 100644 --- a/recipes/novinite.recipe +++ b/recipes/novinite.recipe @@ -1,35 +1,35 @@ -from calibre.web.feeds.news import BasicNewsRecipe - -class AdvancedUserRecipe1308572538(BasicNewsRecipe): - title = u'Novinite.com' - __author__ = 'Martin Tsanchev' - description = 'Real time provider of the latest Bulgarian news in English' - category = 'Business, Politics, Society, Sports, Crime, Lifestyle, World, People' - language = 'en_BG' - encoding = 'utf-8' - oldest_article = 7 - max_articles_per_feed = 10 - keep_only_tags = [dict(name='div', attrs={'id':'content'})] - remove_tags = [dict(name='a', attrs={'class':'twitter-share-button'})] - remove_tags_after = dict(id='textsize') - no_stylesheets = True - feeds = [(u'Business', u'http://www.novinite.com/services/news_rdf.php?category_id=1'), -(u'Finance', u'http://www.novinite.com/services/news_rdf.php?category_id=15'), -(u'Energy', u'http://www.novinite.com/services/news_rdf.php?category_id=16'), -(u'Industry', u'http://www.novinite.com/services/news_rdf.php?category_id=17'), -(u'Properties', u'http://www.novinite.com/services/news_rdf.php?category_id=18'), -(u'Politics', u'http://www.novinite.com/services/news_rdf.php?category_id=2'), -(u'Diplomacy', u'http://www.novinite.com/services/news_rdf.php?category_id=20'), -(u'Defense', u'http://www.novinite.com/services/news_rdf.php?category_id=21'), -(u'Bulgaria in EU', u'http://www.novinite.com/services/news_rdf.php?category_id=22'), -(u'Domestic', u'http://www.novinite.com/services/news_rdf.php?category_id=23'), -(u'Society', u'http://www.novinite.com/services/news_rdf.php?category_id=3'), -(u'Environment', u'http://www.novinite.com/services/news_rdf.php?category_id=24'), -(u'Education', u'http://www.novinite.com/services/news_rdf.php?category_id=25'), -(u'Culture', u'http://www.novinite.com/services/news_rdf.php?category_id=26'), -(u'Archaeology', u'http://www.novinite.com/services/news_rdf.php?category_id=34'), -(u'Health', u'http://www.novinite.com/services/news_rdf.php?category_id=62'), -(u'Sports', u'http://www.novinite.com/services/news_rdf.php?category_id=4'), -(u'Crime', u'http://www.novinite.com/services/news_rdf.php?category_id=5'), -(u'Lifestyle', u'http://www.novinite.com/services/news_rdf.php?category_id=6'), -(u'World', u'http://www.novinite.com/services/news_rdf.php?category_id=30')] +from calibre.web.feeds.news import BasicNewsRecipe + +class AdvancedUserRecipe1308572538(BasicNewsRecipe): + title = u'Novinite.com' + __author__ = 'Martin Tsanchev' + description = 'Real time provider of the latest Bulgarian news in English' + category = 'Business, Politics, Society, Sports, Crime, Lifestyle, World, People' + language = 'en_BG' + encoding = 'utf-8' + oldest_article = 7 + max_articles_per_feed = 10 + keep_only_tags = [dict(name='div', attrs={'id':'content'})] + remove_tags = [dict(name='a', attrs={'class':'twitter-share-button'})] + remove_tags_after = dict(id='textsize') + no_stylesheets = True + feeds = [(u'Business', u'http://www.novinite.com/services/news_rdf.php?category_id=1'), +(u'Finance', u'http://www.novinite.com/services/news_rdf.php?category_id=15'), +(u'Energy', u'http://www.novinite.com/services/news_rdf.php?category_id=16'), +(u'Industry', u'http://www.novinite.com/services/news_rdf.php?category_id=17'), +(u'Properties', u'http://www.novinite.com/services/news_rdf.php?category_id=18'), +(u'Politics', u'http://www.novinite.com/services/news_rdf.php?category_id=2'), +(u'Diplomacy', u'http://www.novinite.com/services/news_rdf.php?category_id=20'), +(u'Defense', u'http://www.novinite.com/services/news_rdf.php?category_id=21'), +(u'Bulgaria in EU', u'http://www.novinite.com/services/news_rdf.php?category_id=22'), +(u'Domestic', u'http://www.novinite.com/services/news_rdf.php?category_id=23'), +(u'Society', u'http://www.novinite.com/services/news_rdf.php?category_id=3'), +(u'Environment', u'http://www.novinite.com/services/news_rdf.php?category_id=24'), +(u'Education', u'http://www.novinite.com/services/news_rdf.php?category_id=25'), +(u'Culture', u'http://www.novinite.com/services/news_rdf.php?category_id=26'), +(u'Archaeology', u'http://www.novinite.com/services/news_rdf.php?category_id=34'), +(u'Health', u'http://www.novinite.com/services/news_rdf.php?category_id=62'), +(u'Sports', u'http://www.novinite.com/services/news_rdf.php?category_id=4'), +(u'Crime', u'http://www.novinite.com/services/news_rdf.php?category_id=5'), +(u'Lifestyle', u'http://www.novinite.com/services/news_rdf.php?category_id=6'), +(u'World', u'http://www.novinite.com/services/news_rdf.php?category_id=30')] diff --git a/recipes/portafolio.recipe b/recipes/portafolio.recipe index 4ba0d16c46..ef07c5e391 100644 --- a/recipes/portafolio.recipe +++ b/recipes/portafolio.recipe @@ -1,36 +1,36 @@ -# -*- coding: utf-8 -*- - -from calibre.web.feeds.news import BasicNewsRecipe - -class AdvancedUserRecipe1311799898(BasicNewsRecipe): - title = u'Periódico Portafolio Colombia' - __author__ = 'BIGO-CAVA' - language = 'es_CO' - cover_url = 'http://www.portafolio.co/sites/portafolio.co/themes/portafolio_2011/logo.png' - remove_tags_before = dict(id='contenidoArt') - remove_tags_after = [dict(name='div', attrs={'class':'articulo-mas'})] - keep_only_tags = [dict(name='div', id='contenidoArt')] - oldest_article = 2 - max_articles_per_feed = 100 - remove_javascript = True - no_stylesheets = True - use_embedded_content = False - remove_empty_feeds = True - masthead_url = 'http://www.portafolio.co/sites/portafolio.co/themes/portafolio_2011/logo.png' - publication_type = 'newspaper' - - extra_css = """ - p{text-align: justify; font-size: 100%} - body{ text-align: left; font-size:100% } - h1{font-family: sans-serif; font-size:150%; font-weight:bold; text-align: justify; } - h3{font-family: sans-serif; font-size:100%; font-style: italic; text-align: justify; } - """ - - - feeds = [(u'Negocios', u'http://www.portafolio.co/negocios/feed'), - (u'Economia', u'http://www.portafolio.co/economia/feed'), - (u'Internacional', u'http://www.portafolio.co/internacional/feed'), - (u'Indicadores', u'http://www.portafolio.co/indicadores/feed'), - (u'Opinion', u'http://www.portafolio.co/opinion/feed'), - (u'Finanzas Personales', u'http://www.portafolio.co/finanzas-personales/feed'), - (u'Herramientas', u'http://www.portafolio.co/herramientas/feed')] +# -*- coding: utf-8 -*- + +from calibre.web.feeds.news import BasicNewsRecipe + +class AdvancedUserRecipe1311799898(BasicNewsRecipe): + title = u'Periódico Portafolio Colombia' + __author__ = 'BIGO-CAVA' + language = 'es_CO' + cover_url = 'http://www.portafolio.co/sites/portafolio.co/themes/portafolio_2011/logo.png' + remove_tags_before = dict(id='contenidoArt') + remove_tags_after = [dict(name='div', attrs={'class':'articulo-mas'})] + keep_only_tags = [dict(name='div', id='contenidoArt')] + oldest_article = 2 + max_articles_per_feed = 100 + remove_javascript = True + no_stylesheets = True + use_embedded_content = False + remove_empty_feeds = True + masthead_url = 'http://www.portafolio.co/sites/portafolio.co/themes/portafolio_2011/logo.png' + publication_type = 'newspaper' + + extra_css = """ + p{text-align: justify; font-size: 100%} + body{ text-align: left; font-size:100% } + h1{font-family: sans-serif; font-size:150%; font-weight:bold; text-align: justify; } + h3{font-family: sans-serif; font-size:100%; font-style: italic; text-align: justify; } + """ + + + feeds = [(u'Negocios', u'http://www.portafolio.co/negocios/feed'), + (u'Economia', u'http://www.portafolio.co/economia/feed'), + (u'Internacional', u'http://www.portafolio.co/internacional/feed'), + (u'Indicadores', u'http://www.portafolio.co/indicadores/feed'), + (u'Opinion', u'http://www.portafolio.co/opinion/feed'), + (u'Finanzas Personales', u'http://www.portafolio.co/finanzas-personales/feed'), + (u'Herramientas', u'http://www.portafolio.co/herramientas/feed')] diff --git a/recipes/revista_semana.recipe b/recipes/revista_semana.recipe index 1137764932..4471194b25 100644 --- a/recipes/revista_semana.recipe +++ b/recipes/revista_semana.recipe @@ -1,11 +1,11 @@ -from calibre.web.feeds.news import BasicNewsRecipe - - -class AdvancedUserRecipe1317341570(BasicNewsRecipe): - title = u'Revista Semana' - __author__ = 'BIGO-CAVA' - language = 'es_CO' - oldest_article = 7 - max_articles_per_feed = 100 - - feeds = [(u'Revista Semana', u'http://www.semana.com/rss/Semana_OnLine.xml')] +from calibre.web.feeds.news import BasicNewsRecipe + + +class AdvancedUserRecipe1317341570(BasicNewsRecipe): + title = u'Revista Semana' + __author__ = 'BIGO-CAVA' + language = 'es_CO' + oldest_article = 7 + max_articles_per_feed = 100 + + feeds = [(u'Revista Semana', u'http://www.semana.com/rss/Semana_OnLine.xml')] diff --git a/recipes/rushisaband.recipe b/recipes/rushisaband.recipe index f1ab83b313..65dda3d8f3 100644 --- a/recipes/rushisaband.recipe +++ b/recipes/rushisaband.recipe @@ -1,28 +1,28 @@ -#!/usr/bin/env python - -__license__ = 'GPL v3' -__author__ = 'MrStefan ' - -''' -www.rushisaband.com -''' - -from calibre.web.feeds.news import BasicNewsRecipe - -class rushisaband(BasicNewsRecipe): - title = u'Rushisaband' - __author__ = 'MrStefan ' - language = 'en_GB' - description =u'A blog devoted to the band RUSH and its members, Neil Peart, Geddy Lee and Alex Lifeson' - remove_empty_feeds= True - oldest_article = 7 - max_articles_per_feed = 100 - remove_javascript=True - no_stylesheets=True - - keep_only_tags =[] - keep_only_tags.append(dict(name = 'h4')) - keep_only_tags.append(dict(name = 'h5')) - keep_only_tags.append(dict(name = 'p')) - - feeds = [(u'Rush is a Band', u'http://feeds2.feedburner.com/rushisaband/blog')] +#!/usr/bin/env python + +__license__ = 'GPL v3' +__author__ = 'MrStefan ' + +''' +www.rushisaband.com +''' + +from calibre.web.feeds.news import BasicNewsRecipe + +class rushisaband(BasicNewsRecipe): + title = u'Rushisaband' + __author__ = 'MrStefan ' + language = 'en_GB' + description =u'A blog devoted to the band RUSH and its members, Neil Peart, Geddy Lee and Alex Lifeson' + remove_empty_feeds= True + oldest_article = 7 + max_articles_per_feed = 100 + remove_javascript=True + no_stylesheets=True + + keep_only_tags =[] + keep_only_tags.append(dict(name = 'h4')) + keep_only_tags.append(dict(name = 'h5')) + keep_only_tags.append(dict(name = 'p')) + + feeds = [(u'Rush is a Band', u'http://feeds2.feedburner.com/rushisaband/blog')] diff --git a/recipes/rybinski.recipe b/recipes/rybinski.recipe index 5597a90474..a2518f0f4a 100644 --- a/recipes/rybinski.recipe +++ b/recipes/rybinski.recipe @@ -1,29 +1,29 @@ -#!/usr/bin/env python - -__license__ = 'GPL v3' -__copyright__ = u'2012, Tomasz Dlugosz ' -''' -rybinski.eu -''' - -from calibre.web.feeds.news import BasicNewsRecipe - -class Rybinski(BasicNewsRecipe): - title = u'Rybinski.eu - economy of the XXI century' - description = u'Blog ekonomiczny dra hab. Krzysztofa Rybi\u0144skiego' - language = 'pl' - __author__ = u'Tomasz D\u0142ugosz' - oldest_article = 7 - max_articles_per_feed = 100 - no_stylesheets = True - - feeds = [(u'wpisy', u'http://www.rybinski.eu/?feed=rss2&lang=pl')] - - keep_only_tags = [dict(name='div', attrs={'class':'post'})] - - remove_tags = [ - dict(name = 'div', attrs = {'class' : 'post-meta-1'}), - dict(name = 'div', attrs = {'class' : 'post-meta-2'}), - dict(name = 'div', attrs = {'class' : 'post-comments'}) - ] - +#!/usr/bin/env python + +__license__ = 'GPL v3' +__copyright__ = u'2012, Tomasz Dlugosz ' +''' +rybinski.eu +''' + +from calibre.web.feeds.news import BasicNewsRecipe + +class Rybinski(BasicNewsRecipe): + title = u'Rybinski.eu - economy of the XXI century' + description = u'Blog ekonomiczny dra hab. Krzysztofa Rybi\u0144skiego' + language = 'pl' + __author__ = u'Tomasz D\u0142ugosz' + oldest_article = 7 + max_articles_per_feed = 100 + no_stylesheets = True + + feeds = [(u'wpisy', u'http://www.rybinski.eu/?feed=rss2&lang=pl')] + + keep_only_tags = [dict(name='div', attrs={'class':'post'})] + + remove_tags = [ + dict(name = 'div', attrs = {'class' : 'post-meta-1'}), + dict(name = 'div', attrs = {'class' : 'post-meta-2'}), + dict(name = 'div', attrs = {'class' : 'post-comments'}) + ] + diff --git a/recipes/silicon_republic.recipe b/recipes/silicon_republic.recipe index 0b5f17786e..a7c45cc316 100644 --- a/recipes/silicon_republic.recipe +++ b/recipes/silicon_republic.recipe @@ -1,22 +1,22 @@ -__license__ = 'GPL v3' -__copyright__ = '2011 Neil Grogan' -# -# Silicon Republic Recipe -# - -from calibre.web.feeds.news import BasicNewsRecipe - -class SiliconRepublic(BasicNewsRecipe): - title = u'Silicon Republic' - oldest_article = 7 - max_articles_per_feed = 100 - __author__ = u'Neil Grogan' - language = 'en_IE' - - remove_tags = [dict(attrs={'class':['thumb','txt','compactbox','icons','catlist','catlistinner','taglist','taglistinner','social','also-in','also-in-inner','also-in-footer','zonek-dfp','paneladvert','rcadvert','panel','h2b']}), - dict(id=['header','logo','header-right','sitesearch','rsslinks','topnav','topvideos','topvideos-list','topnews','topnews-list','slideshow','slides','compactheader','compactnews','compactfeatures','article-type','contactlinks-header','banner-zone-k-dfp','footer-related','directory-services','also-in-section','featuredrelated1','featuredrelated2','featuredrelated3','featuredrelated4','advert2-dfp']), - dict(name=['script', 'style'])] - - - feeds = [(u'News', u'http://www.siliconrepublic.com/feeds/')] - +__license__ = 'GPL v3' +__copyright__ = '2011 Neil Grogan' +# +# Silicon Republic Recipe +# + +from calibre.web.feeds.news import BasicNewsRecipe + +class SiliconRepublic(BasicNewsRecipe): + title = u'Silicon Republic' + oldest_article = 7 + max_articles_per_feed = 100 + __author__ = u'Neil Grogan' + language = 'en_IE' + + remove_tags = [dict(attrs={'class':['thumb','txt','compactbox','icons','catlist','catlistinner','taglist','taglistinner','social','also-in','also-in-inner','also-in-footer','zonek-dfp','paneladvert','rcadvert','panel','h2b']}), + dict(id=['header','logo','header-right','sitesearch','rsslinks','topnav','topvideos','topvideos-list','topnews','topnews-list','slideshow','slides','compactheader','compactnews','compactfeatures','article-type','contactlinks-header','banner-zone-k-dfp','footer-related','directory-services','also-in-section','featuredrelated1','featuredrelated2','featuredrelated3','featuredrelated4','advert2-dfp']), + dict(name=['script', 'style'])] + + + feeds = [(u'News', u'http://www.siliconrepublic.com/feeds/')] + diff --git a/recipes/spin_magazine.recipe b/recipes/spin_magazine.recipe index dbac216f81..59aa3fa7e0 100644 --- a/recipes/spin_magazine.recipe +++ b/recipes/spin_magazine.recipe @@ -1,15 +1,15 @@ -from calibre.web.feeds.news import BasicNewsRecipe - -class AdvancedUserRecipe1296179411(BasicNewsRecipe): - title = u'SPIN Magzine' - __author__ = 'Quistopher' - language = 'en' - oldest_article = 7 - max_articles_per_feed = 100 - - feeds = [ - (u'Daily Noise Blog | SPIN.com', u'http://www.spin.com/blog/feed'), - (u'It Happened Last Night | SPIN.com', u'http://www.spin.com/it-happened-last-night/feed'), - (u'Album Reviews | SPIN.com', u'http://www.spin.com/album-reviews/feed') - - ] +from calibre.web.feeds.news import BasicNewsRecipe + +class AdvancedUserRecipe1296179411(BasicNewsRecipe): + title = u'SPIN Magzine' + __author__ = 'Quistopher' + language = 'en' + oldest_article = 7 + max_articles_per_feed = 100 + + feeds = [ + (u'Daily Noise Blog | SPIN.com', u'http://www.spin.com/blog/feed'), + (u'It Happened Last Night | SPIN.com', u'http://www.spin.com/it-happened-last-night/feed'), + (u'Album Reviews | SPIN.com', u'http://www.spin.com/album-reviews/feed') + + ] diff --git a/recipes/thai_post_daily.recipe b/recipes/thai_post_daily.recipe index 4523a9331a..a2f9ee76ec 100644 --- a/recipes/thai_post_daily.recipe +++ b/recipes/thai_post_daily.recipe @@ -1,18 +1,18 @@ -from calibre.web.feeds.news import BasicNewsRecipe - -class AdvancedUserRecipe1299054026(BasicNewsRecipe): - title = u'Thai Post Daily' - __author__ = 'Chotechai P.' - language = 'th' - oldest_article = 7 - max_articles_per_feed = 100 - cover_url = 'http://upload.wikimedia.org/wikipedia/th/1/10/ThaiPost_Logo.png' - feeds = [(u'\u0e02\u0e48\u0e32\u0e27\u0e2b\u0e19\u0e49\u0e32\u0e2b\u0e19\u0e36\u0e48\u0e07', u'http://thaipost.net/taxonomy/term/1/all/feed'), (u'\u0e1a\u0e17\u0e1a\u0e23\u0e23\u0e13\u0e32\u0e18\u0e34\u0e01\u0e32\u0e23', u'http://thaipost.net/taxonomy/term/11/all/feed'), (u'\u0e40\u0e1b\u0e25\u0e27 \u0e2a\u0e35\u0e40\u0e07\u0e34\u0e19', u'http://thaipost.net/taxonomy/term/2/all/feed'), (u'\u0e2a\u0e20\u0e32\u0e1b\u0e23\u0e30\u0e0a\u0e32\u0e0a\u0e19', u'http://thaipost.net/taxonomy/term/3/all/feed'), (u'\u0e16\u0e39\u0e01\u0e17\u0e38\u0e01\u0e02\u0e49\u0e2d', u'http://thaipost.net/taxonomy/term/4/all/feed'), (u'\u0e01\u0e32\u0e23\u0e40\u0e21\u0e37\u0e2d\u0e07', u'http://thaipost.net/taxonomy/term/5/all/feed'), (u'\u0e17\u0e48\u0e32\u0e19\u0e02\u0e38\u0e19\u0e19\u0e49\u0e2d\u0e22', u'http://thaipost.net/taxonomy/term/12/all/feed'), (u'\u0e1a\u0e17\u0e04\u0e27\u0e32\u0e21\u0e1e\u0e34\u0e40\u0e28\u0e29', u'http://thaipost.net/taxonomy/term/66/all/feed'), (u'\u0e23\u0e32\u0e22\u0e07\u0e32\u0e19\u0e1e\u0e34\u0e40\u0e28\u0e29', u'http://thaipost.net/taxonomy/term/67/all/feed'), (u'\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01\u0e2b\u0e19\u0e49\u0e32 4', u'http://thaipost.net/taxonomy/term/13/all/feed'), (u'\u0e40\u0e2a\u0e35\u0e22\u0e1a\u0e0b\u0e36\u0e48\u0e07\u0e2b\u0e19\u0e49\u0e32', u'http://thaipost.net/taxonomy/term/64/all/feed'), (u'\u0e04\u0e31\u0e19\u0e1b\u0e32\u0e01\u0e2d\u0e22\u0e32\u0e01\u0e40\u0e25\u0e48\u0e32', u'http://thaipost.net/taxonomy/term/65/all/feed'), (u'\u0e40\u0e28\u0e23\u0e29\u0e10\u0e01\u0e34\u0e08', u'http://thaipost.net/taxonomy/term/6/all/feed'), (u'\u0e01\u0e23\u0e30\u0e08\u0e01\u0e44\u0e23\u0e49\u0e40\u0e07\u0e32', u'http://thaipost.net/taxonomy/term/14/all/feed'), (u'\u0e01\u0e23\u0e30\u0e08\u0e01\u0e2b\u0e31\u0e01\u0e21\u0e38\u0e21', u'http://thaipost.net/taxonomy/term/71/all/feed'), (u'\u0e04\u0e34\u0e14\u0e40\u0e2b\u0e19\u0e37\u0e2d\u0e01\u0e23\u0e30\u0e41\u0e2a', u'http://thaipost.net/taxonomy/term/69/all/feed'), (u'\u0e23\u0e32\u0e22\u0e07\u0e32\u0e19', u'http://thaipost.net/taxonomy/term/68/all/feed'), (u'\u0e2d\u0e34\u0e42\u0e04\u0e42\u0e1f\u0e01\u0e31\u0e2a', u'http://thaipost.net/taxonomy/term/10/all/feed'), (u'\u0e01\u0e32\u0e23\u0e28\u0e36\u0e01\u0e29\u0e32-\u0e2a\u0e32\u0e18\u0e32\u0e23\u0e13\u0e2a\u0e38\u0e02', u'http://thaipost.net/taxonomy/term/7/all/feed'), (u'\u0e15\u0e48\u0e32\u0e07\u0e1b\u0e23\u0e30\u0e40\u0e17\u0e28', u'http://thaipost.net/taxonomy/term/8/all/feed'), (u'\u0e01\u0e35\u0e2c\u0e32', u'http://thaipost.net/taxonomy/term/9/all/feed')] - - def print_version(self, url): - return url.replace(url, 'http://www.thaipost.net/print/' + url [32:]) - - remove_tags = [] - remove_tags.append(dict(name = 'div', attrs = {'class' : 'print-logo'})) - remove_tags.append(dict(name = 'div', attrs = {'class' : 'print-site_name'})) - remove_tags.append(dict(name = 'div', attrs = {'class' : 'print-breadcrumb'})) +from calibre.web.feeds.news import BasicNewsRecipe + +class AdvancedUserRecipe1299054026(BasicNewsRecipe): + title = u'Thai Post Daily' + __author__ = 'Chotechai P.' + language = 'th' + oldest_article = 7 + max_articles_per_feed = 100 + cover_url = 'http://upload.wikimedia.org/wikipedia/th/1/10/ThaiPost_Logo.png' + feeds = [(u'\u0e02\u0e48\u0e32\u0e27\u0e2b\u0e19\u0e49\u0e32\u0e2b\u0e19\u0e36\u0e48\u0e07', u'http://thaipost.net/taxonomy/term/1/all/feed'), (u'\u0e1a\u0e17\u0e1a\u0e23\u0e23\u0e13\u0e32\u0e18\u0e34\u0e01\u0e32\u0e23', u'http://thaipost.net/taxonomy/term/11/all/feed'), (u'\u0e40\u0e1b\u0e25\u0e27 \u0e2a\u0e35\u0e40\u0e07\u0e34\u0e19', u'http://thaipost.net/taxonomy/term/2/all/feed'), (u'\u0e2a\u0e20\u0e32\u0e1b\u0e23\u0e30\u0e0a\u0e32\u0e0a\u0e19', u'http://thaipost.net/taxonomy/term/3/all/feed'), (u'\u0e16\u0e39\u0e01\u0e17\u0e38\u0e01\u0e02\u0e49\u0e2d', u'http://thaipost.net/taxonomy/term/4/all/feed'), (u'\u0e01\u0e32\u0e23\u0e40\u0e21\u0e37\u0e2d\u0e07', u'http://thaipost.net/taxonomy/term/5/all/feed'), (u'\u0e17\u0e48\u0e32\u0e19\u0e02\u0e38\u0e19\u0e19\u0e49\u0e2d\u0e22', u'http://thaipost.net/taxonomy/term/12/all/feed'), (u'\u0e1a\u0e17\u0e04\u0e27\u0e32\u0e21\u0e1e\u0e34\u0e40\u0e28\u0e29', u'http://thaipost.net/taxonomy/term/66/all/feed'), (u'\u0e23\u0e32\u0e22\u0e07\u0e32\u0e19\u0e1e\u0e34\u0e40\u0e28\u0e29', u'http://thaipost.net/taxonomy/term/67/all/feed'), (u'\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01\u0e2b\u0e19\u0e49\u0e32 4', u'http://thaipost.net/taxonomy/term/13/all/feed'), (u'\u0e40\u0e2a\u0e35\u0e22\u0e1a\u0e0b\u0e36\u0e48\u0e07\u0e2b\u0e19\u0e49\u0e32', u'http://thaipost.net/taxonomy/term/64/all/feed'), (u'\u0e04\u0e31\u0e19\u0e1b\u0e32\u0e01\u0e2d\u0e22\u0e32\u0e01\u0e40\u0e25\u0e48\u0e32', u'http://thaipost.net/taxonomy/term/65/all/feed'), (u'\u0e40\u0e28\u0e23\u0e29\u0e10\u0e01\u0e34\u0e08', u'http://thaipost.net/taxonomy/term/6/all/feed'), (u'\u0e01\u0e23\u0e30\u0e08\u0e01\u0e44\u0e23\u0e49\u0e40\u0e07\u0e32', u'http://thaipost.net/taxonomy/term/14/all/feed'), (u'\u0e01\u0e23\u0e30\u0e08\u0e01\u0e2b\u0e31\u0e01\u0e21\u0e38\u0e21', u'http://thaipost.net/taxonomy/term/71/all/feed'), (u'\u0e04\u0e34\u0e14\u0e40\u0e2b\u0e19\u0e37\u0e2d\u0e01\u0e23\u0e30\u0e41\u0e2a', u'http://thaipost.net/taxonomy/term/69/all/feed'), (u'\u0e23\u0e32\u0e22\u0e07\u0e32\u0e19', u'http://thaipost.net/taxonomy/term/68/all/feed'), (u'\u0e2d\u0e34\u0e42\u0e04\u0e42\u0e1f\u0e01\u0e31\u0e2a', u'http://thaipost.net/taxonomy/term/10/all/feed'), (u'\u0e01\u0e32\u0e23\u0e28\u0e36\u0e01\u0e29\u0e32-\u0e2a\u0e32\u0e18\u0e32\u0e23\u0e13\u0e2a\u0e38\u0e02', u'http://thaipost.net/taxonomy/term/7/all/feed'), (u'\u0e15\u0e48\u0e32\u0e07\u0e1b\u0e23\u0e30\u0e40\u0e17\u0e28', u'http://thaipost.net/taxonomy/term/8/all/feed'), (u'\u0e01\u0e35\u0e2c\u0e32', u'http://thaipost.net/taxonomy/term/9/all/feed')] + + def print_version(self, url): + return url.replace(url, 'http://www.thaipost.net/print/' + url [32:]) + + remove_tags = [] + remove_tags.append(dict(name = 'div', attrs = {'class' : 'print-logo'})) + remove_tags.append(dict(name = 'div', attrs = {'class' : 'print-site_name'})) + remove_tags.append(dict(name = 'div', attrs = {'class' : 'print-breadcrumb'})) diff --git a/recipes/the_clinic_online.recipe b/recipes/the_clinic_online.recipe index e25a9f3124..4bd6c3c2c8 100644 --- a/recipes/the_clinic_online.recipe +++ b/recipes/the_clinic_online.recipe @@ -1,27 +1,27 @@ -from calibre.web.feeds.news import BasicNewsRecipe - -class AdvancedUserRecipe1313555075(BasicNewsRecipe): - news = True - title = u'The Clinic' - __author__ = 'Alex Mitrani' - description = u'Online version of Chilean satirical weekly' - publisher = u'The Clinic' - category = 'news, politics, Chile, rss' - oldest_article = 7 - max_articles_per_feed = 100 - summary_length = 1000 - language = 'es_CL' - - remove_javascript = True - no_stylesheets = True - use_embedded_content = False - remove_empty_feeds = True - masthead_url = 'http://www.theclinic.cl/wp-content/themes/tc12m/css/ui/mainLogoTC-top.png' - remove_tags_before = dict(name='article', attrs={'class':'scope bordered'}) - remove_tags_after = dict(name='div', attrs={'id':'commentsSection'}) - remove_tags = [dict(name='span', attrs={'class':'relTags'}) - ,dict(name='div', attrs={'class':'articleActivity hdcol'}) - ,dict(name='div', attrs={'id':'commentsSection'}) - ] - - feeds = [(u'The Clinic Online', u'http://www.theclinic.cl/feed/')] +from calibre.web.feeds.news import BasicNewsRecipe + +class AdvancedUserRecipe1313555075(BasicNewsRecipe): + news = True + title = u'The Clinic' + __author__ = 'Alex Mitrani' + description = u'Online version of Chilean satirical weekly' + publisher = u'The Clinic' + category = 'news, politics, Chile, rss' + oldest_article = 7 + max_articles_per_feed = 100 + summary_length = 1000 + language = 'es_CL' + + remove_javascript = True + no_stylesheets = True + use_embedded_content = False + remove_empty_feeds = True + masthead_url = 'http://www.theclinic.cl/wp-content/themes/tc12m/css/ui/mainLogoTC-top.png' + remove_tags_before = dict(name='article', attrs={'class':'scope bordered'}) + remove_tags_after = dict(name='div', attrs={'id':'commentsSection'}) + remove_tags = [dict(name='span', attrs={'class':'relTags'}) + ,dict(name='div', attrs={'class':'articleActivity hdcol'}) + ,dict(name='div', attrs={'id':'commentsSection'}) + ] + + feeds = [(u'The Clinic Online', u'http://www.theclinic.cl/feed/')] diff --git a/recipes/the_new_republic.recipe b/recipes/the_new_republic.recipe index 7611ec946f..ba0e070a8a 100644 --- a/recipes/the_new_republic.recipe +++ b/recipes/the_new_republic.recipe @@ -1,63 +1,63 @@ -import re -from calibre.web.feeds.recipes import BasicNewsRecipe - - -class TNR(BasicNewsRecipe): - - title = 'The New Republic' - __author__ = 'Krittika Goyal' - - description = '''The New Republic is a journal of opinion with an emphasis - on politics and domestic and international affairs. It carries feature - articles by staff and contributing editors. The second half of each issue - is devoted to book and the arts, theater, motion pictures, music and art.''' - - language = 'en' - encoding = 'UTF-8' - needs_subscription = True - - preprocess_regexps = [ - (re.compile(r'', re.DOTALL), lambda m: ''), - (re.compile(r'', re.DOTALL), lambda m: ''), - ] - - def get_browser(self): - br = BasicNewsRecipe.get_browser(self) - br.open('http://www.newrepublic.com/user') - br.select_form(nr=1) - try: - br['user'] = self.username - except: - br['name'] = self.username - br['pass'] = self.password - self.log('Logging in...') - raw = br.submit().read() - if 'SIGN OUT' not in raw: - raise ValueError('Failed to log in to tnr.com, check your username and password') - self.log('Logged in successfully') - return br - - def parse_index(self): - raw = self.index_to_soup('http://www.newrepublic.com/current-issue', raw=True) - # raw = self.index_to_soup(open('/t/raw.html').read().decode('utf-8'), raw=True) - for pat, sub in self.preprocess_regexps: - raw = pat.sub(sub, raw) - soup = self.index_to_soup(raw) - feed_title = 'The New Republic Magazine Articles' - - articles = [] - for div in soup.findAll('div', attrs={'class':lambda x: x and 'field-item' in x.split()}): - a = div.find('a', href=True, attrs={'class':lambda x: x != 'author'}) - if a is not None: - art_title = self.tag_to_string(a) - url = a.get('href') - num = re.search(r'/(\d+)/', url) - if num is not None: - art = num.group(1) - url = 'http://www.newrepublic.com/node/%s/print'%art - self.log.info('\tFound article:', art_title, 'at', url) - article = {'title':art_title, 'url':url, 'description':'', 'date':''} - articles.append(article) - - return [(feed_title, articles)] - +import re +from calibre.web.feeds.recipes import BasicNewsRecipe + + +class TNR(BasicNewsRecipe): + + title = 'The New Republic' + __author__ = 'Krittika Goyal' + + description = '''The New Republic is a journal of opinion with an emphasis + on politics and domestic and international affairs. It carries feature + articles by staff and contributing editors. The second half of each issue + is devoted to book and the arts, theater, motion pictures, music and art.''' + + language = 'en' + encoding = 'UTF-8' + needs_subscription = True + + preprocess_regexps = [ + (re.compile(r'', re.DOTALL), lambda m: ''), + (re.compile(r'', re.DOTALL), lambda m: ''), + ] + + def get_browser(self): + br = BasicNewsRecipe.get_browser(self) + br.open('http://www.newrepublic.com/user') + br.select_form(nr=1) + try: + br['user'] = self.username + except: + br['name'] = self.username + br['pass'] = self.password + self.log('Logging in...') + raw = br.submit().read() + if 'SIGN OUT' not in raw: + raise ValueError('Failed to log in to tnr.com, check your username and password') + self.log('Logged in successfully') + return br + + def parse_index(self): + raw = self.index_to_soup('http://www.newrepublic.com/current-issue', raw=True) + # raw = self.index_to_soup(open('/t/raw.html').read().decode('utf-8'), raw=True) + for pat, sub in self.preprocess_regexps: + raw = pat.sub(sub, raw) + soup = self.index_to_soup(raw) + feed_title = 'The New Republic Magazine Articles' + + articles = [] + for div in soup.findAll('div', attrs={'class':lambda x: x and 'field-item' in x.split()}): + a = div.find('a', href=True, attrs={'class':lambda x: x != 'author'}) + if a is not None: + art_title = self.tag_to_string(a) + url = a.get('href') + num = re.search(r'/(\d+)/', url) + if num is not None: + art = num.group(1) + url = 'http://www.newrepublic.com/node/%s/print'%art + self.log.info('\tFound article:', art_title, 'at', url) + article = {'title':art_title, 'url':url, 'description':'', 'date':''} + articles.append(article) + + return [(feed_title, articles)] + diff --git a/recipes/utrinski.recipe b/recipes/utrinski.recipe index 8cc6f4f2ee..a9e8e418e2 100644 --- a/recipes/utrinski.recipe +++ b/recipes/utrinski.recipe @@ -1,76 +1,76 @@ -#!/usr/bin/env python - -__author__ = 'Darko Spasovski' -__license__ = 'GPL v3' -__copyright__ = '2011, Darko Spasovski ' -''' -utrinski.com.mk -''' - -import re -import datetime -from calibre.web.feeds.news import BasicNewsRecipe -from calibre.ebooks.BeautifulSoup import BeautifulSoup -from calibre import browser - -class UtrinskiVesnik(BasicNewsRecipe): - - INDEX = 'http://www.utrinski.com.mk/' - title = 'Utrinski Vesnik' - description = 'Daily Macedonian newspaper' - masthead_url = 'http://www.utrinski.com.mk/images/LogoTop.jpg' - language = 'mk' - remove_javascript = True - publication_type = 'newspaper' - category = 'news, Macedonia' - max_articles_per_feed = 100 - no_stylesheets = True - use_embedded_content = False - preprocess_regexps = [(re.compile(i[0], re.IGNORECASE | re.DOTALL), i[1]) for i in - [ - ## Remove anything before the start of the article. - (r'', lambda match: ''), - - ## Remove anything after the end of the article. - (r'', lambda match: ''), + + ## Remove anything after the end of the article. + (r'