Hex Artifact Content
Not logged in

Artifact 2b9f0b11bf6d604134e711be27330f404b38b4c4:

File src/zip.c part of check-in [deb6f2af4f] - Change the disk number start from 1 to 0 in generated ZIP archives. Ticket 04cba6a00145ab597dabc48ad5ee688496a57650 by drh on 2009-06-20 23:05:55.

0000: 2f 2a 0a 2a 2a 20 43 6f 70 79 72 69 67 68 74 20  /*.** Copyright 
0010: 28 63 29 20 32 30 30 37 20 44 2e 20 52 69 63 68  (c) 2007 D. Rich
0020: 61 72 64 20 48 69 70 70 0a 2a 2a 0a 2a 2a 20 54  ard Hipp.**.** T
0030: 68 69 73 20 70 72 6f 67 72 61 6d 20 69 73 20 66  his program is f
0040: 72 65 65 20 73 6f 66 74 77 61 72 65 3b 20 79 6f  ree software; yo
0050: 75 20 63 61 6e 20 72 65 64 69 73 74 72 69 62 75  u can redistribu
0060: 74 65 20 69 74 20 61 6e 64 2f 6f 72 0a 2a 2a 20  te it and/or.** 
0070: 6d 6f 64 69 66 79 20 69 74 20 75 6e 64 65 72 20  modify it under 
0080: 74 68 65 20 74 65 72 6d 73 20 6f 66 20 74 68 65  the terms of the
0090: 20 47 4e 55 20 47 65 6e 65 72 61 6c 20 50 75 62   GNU General Pub
00a0: 6c 69 63 0a 2a 2a 20 4c 69 63 65 6e 73 65 20 76  lic.** License v
00b0: 65 72 73 69 6f 6e 20 32 20 61 73 20 70 75 62 6c  ersion 2 as publ
00c0: 69 73 68 65 64 20 62 79 20 74 68 65 20 46 72 65  ished by the Fre
00d0: 65 20 53 6f 66 74 77 61 72 65 20 46 6f 75 6e 64  e Software Found
00e0: 61 74 69 6f 6e 2e 0a 2a 2a 0a 2a 2a 20 54 68 69  ation..**.** Thi
00f0: 73 20 70 72 6f 67 72 61 6d 20 69 73 20 64 69 73  s program is dis
0100: 74 72 69 62 75 74 65 64 20 69 6e 20 74 68 65 20  tributed in the 
0110: 68 6f 70 65 20 74 68 61 74 20 69 74 20 77 69 6c  hope that it wil
0120: 6c 20 62 65 20 75 73 65 66 75 6c 2c 0a 2a 2a 20  l be useful,.** 
0130: 62 75 74 20 57 49 54 48 4f 55 54 20 41 4e 59 20  but WITHOUT ANY 
0140: 57 41 52 52 41 4e 54 59 3b 20 77 69 74 68 6f 75  WARRANTY; withou
0150: 74 20 65 76 65 6e 20 74 68 65 20 69 6d 70 6c 69  t even the impli
0160: 65 64 20 77 61 72 72 61 6e 74 79 20 6f 66 0a 2a  ed warranty of.*
0170: 2a 20 4d 45 52 43 48 41 4e 54 41 42 49 4c 49 54  * MERCHANTABILIT
0180: 59 20 6f 72 20 46 49 54 4e 45 53 53 20 46 4f 52  Y or FITNESS FOR
0190: 20 41 20 50 41 52 54 49 43 55 4c 41 52 20 50 55   A PARTICULAR PU
01a0: 52 50 4f 53 45 2e 20 20 53 65 65 20 74 68 65 20  RPOSE.  See the 
01b0: 47 4e 55 0a 2a 2a 20 47 65 6e 65 72 61 6c 20 50  GNU.** General P
01c0: 75 62 6c 69 63 20 4c 69 63 65 6e 73 65 20 66 6f  ublic License fo
01d0: 72 20 6d 6f 72 65 20 64 65 74 61 69 6c 73 2e 0a  r more details..
01e0: 2a 2a 20 0a 2a 2a 20 59 6f 75 20 73 68 6f 75 6c  ** .** You shoul
01f0: 64 20 68 61 76 65 20 72 65 63 65 69 76 65 64 20  d have received 
0200: 61 20 63 6f 70 79 20 6f 66 20 74 68 65 20 47 4e  a copy of the GN
0210: 55 20 47 65 6e 65 72 61 6c 20 50 75 62 6c 69 63  U General Public
0220: 0a 2a 2a 20 4c 69 63 65 6e 73 65 20 61 6c 6f 6e  .** License alon
0230: 67 20 77 69 74 68 20 74 68 69 73 20 6c 69 62 72  g with this libr
0240: 61 72 79 3b 20 69 66 20 6e 6f 74 2c 20 77 72 69  ary; if not, wri
0250: 74 65 20 74 6f 20 74 68 65 0a 2a 2a 20 46 72 65  te to the.** Fre
0260: 65 20 53 6f 66 74 77 61 72 65 20 46 6f 75 6e 64  e Software Found
0270: 61 74 69 6f 6e 2c 20 49 6e 63 2e 2c 20 35 39 20  ation, Inc., 59 
0280: 54 65 6d 70 6c 65 20 50 6c 61 63 65 20 2d 20 53  Temple Place - S
0290: 75 69 74 65 20 33 33 30 2c 0a 2a 2a 20 42 6f 73  uite 330,.** Bos
02a0: 74 6f 6e 2c 20 4d 41 20 20 30 32 31 31 31 2d 31  ton, MA  02111-1
02b0: 33 30 37 2c 20 55 53 41 2e 0a 2a 2a 0a 2a 2a 20  307, USA..**.** 
02c0: 41 75 74 68 6f 72 20 63 6f 6e 74 61 63 74 20 69  Author contact i
02d0: 6e 66 6f 72 6d 61 74 69 6f 6e 3a 0a 2a 2a 20 20  nformation:.**  
02e0: 20 64 72 68 40 68 77 61 63 69 2e 63 6f 6d 0a 2a   drh@hwaci.com.*
02f0: 2a 20 20 20 68 74 74 70 3a 2f 2f 77 77 77 2e 68  *   http://www.h
0300: 77 61 63 69 2e 63 6f 6d 2f 64 72 68 2f 0a 2a 2a  waci.com/drh/.**
0310: 0a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  .***************
0320: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0330: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0340: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0350: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0360: 0a 2a 2a 0a 2a 2a 20 54 68 69 73 20 66 69 6c 65  .**.** This file
0370: 20 63 6f 6e 74 61 69 6e 73 20 63 6f 64 65 20 75   contains code u
0380: 73 65 64 20 74 6f 20 67 65 6e 65 72 61 74 65 20  sed to generate 
0390: 5a 49 50 20 61 72 63 68 69 76 65 73 2e 0a 2a 2f  ZIP archives..*/
03a0: 0a 23 69 6e 63 6c 75 64 65 20 3c 61 73 73 65 72  .#include <asser
03b0: 74 2e 68 3e 0a 23 69 6e 63 6c 75 64 65 20 3c 7a  t.h>.#include <z
03c0: 6c 69 62 2e 68 3e 0a 23 69 6e 63 6c 75 64 65 20  lib.h>.#include 
03d0: 22 63 6f 6e 66 69 67 2e 68 22 0a 23 69 6e 63 6c  "config.h".#incl
03e0: 75 64 65 20 22 7a 69 70 2e 68 22 0a 0a 2f 2a 0a  ude "zip.h"../*.
03f0: 2a 2a 20 57 72 69 74 65 20 61 20 31 36 2d 20 6f  ** Write a 16- o
0400: 72 20 33 32 2d 62 69 74 20 69 6e 74 65 67 65 72  r 32-bit integer
0410: 20 61 73 20 6c 69 74 74 6c 65 2d 65 6e 64 69 61   as little-endia
0420: 6e 20 69 6e 74 6f 20 74 68 65 20 67 69 76 65 6e  n into the given
0430: 20 62 75 66 66 65 72 2e 0a 2a 2f 0a 73 74 61 74   buffer..*/.stat
0440: 69 63 20 76 6f 69 64 20 70 75 74 31 36 28 63 68  ic void put16(ch
0450: 61 72 20 2a 7a 2c 20 69 6e 74 20 76 29 7b 0a 20  ar *z, int v){. 
0460: 20 7a 5b 30 5d 20 3d 20 76 20 26 20 30 78 66 66   z[0] = v & 0xff
0470: 3b 0a 20 20 7a 5b 31 5d 20 3d 20 28 76 3e 3e 38  ;.  z[1] = (v>>8
0480: 29 20 26 20 30 78 66 66 3b 0a 7d 0a 73 74 61 74  ) & 0xff;.}.stat
0490: 69 63 20 76 6f 69 64 20 70 75 74 33 32 28 63 68  ic void put32(ch
04a0: 61 72 20 2a 7a 2c 20 69 6e 74 20 76 29 7b 0a 20  ar *z, int v){. 
04b0: 20 7a 5b 30 5d 20 3d 20 76 20 26 20 30 78 66 66   z[0] = v & 0xff
04c0: 3b 0a 20 20 7a 5b 31 5d 20 3d 20 28 76 3e 3e 38  ;.  z[1] = (v>>8
04d0: 29 20 26 20 30 78 66 66 3b 0a 20 20 7a 5b 32 5d  ) & 0xff;.  z[2]
04e0: 20 3d 20 28 76 3e 3e 31 36 29 20 26 20 30 78 66   = (v>>16) & 0xf
04f0: 66 3b 0a 20 20 7a 5b 33 5d 20 3d 20 28 76 3e 3e  f;.  z[3] = (v>>
0500: 32 34 29 20 26 20 30 78 66 66 3b 0a 7d 0a 0a 2f  24) & 0xff;.}../
0510: 2a 0a 2a 2a 20 56 61 72 69 61 62 6c 65 73 20 69  *.** Variables i
0520: 6e 20 77 68 69 63 68 20 74 6f 20 61 63 63 75 6d  n which to accum
0530: 75 6c 61 74 65 20 61 20 67 72 6f 77 69 6e 67 20  ulate a growing 
0540: 5a 49 50 20 61 72 63 68 69 76 65 2e 0a 2a 2f 0a  ZIP archive..*/.
0550: 73 74 61 74 69 63 20 42 6c 6f 62 20 62 6f 64 79  static Blob body
0560: 3b 20 20 20 20 2f 2a 20 54 68 65 20 62 6f 64 79  ;    /* The body
0570: 20 6f 66 20 74 68 65 20 5a 49 50 20 61 72 63 68   of the ZIP arch
0580: 69 76 65 20 2a 2f 0a 73 74 61 74 69 63 20 42 6c  ive */.static Bl
0590: 6f 62 20 74 6f 63 3b 20 20 20 20 20 2f 2a 20 54  ob toc;     /* T
05a0: 68 65 20 74 61 62 6c 65 20 6f 66 20 63 6f 6e 74  he table of cont
05b0: 65 6e 74 73 20 2a 2f 0a 73 74 61 74 69 63 20 69  ents */.static i
05c0: 6e 74 20 6e 45 6e 74 72 79 3b 20 20 20 2f 2a 20  nt nEntry;   /* 
05d0: 4e 75 6d 62 65 72 20 6f 66 20 66 69 6c 65 73 20  Number of files 
05e0: 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 64 6f  */.static int do
05f0: 73 54 69 6d 65 3b 20 20 2f 2a 20 44 4f 53 2d 66  sTime;  /* DOS-f
0600: 6f 72 6d 61 74 20 74 69 6d 65 20 2a 2f 0a 73 74  ormat time */.st
0610: 61 74 69 63 20 69 6e 74 20 64 6f 73 44 61 74 65  atic int dosDate
0620: 3b 20 20 2f 2a 20 44 4f 53 2d 66 6f 72 6d 61 74  ;  /* DOS-format
0630: 20 64 61 74 65 20 2a 2f 0a 0a 2f 2a 0a 2a 2a 20   date */../*.** 
0640: 49 6e 69 74 69 61 6c 69 7a 65 20 61 20 6e 65 77  Initialize a new
0650: 20 5a 49 50 20 61 72 63 68 69 76 65 2e 0a 2a 2f   ZIP archive..*/
0660: 0a 76 6f 69 64 20 7a 69 70 5f 6f 70 65 6e 28 76  .void zip_open(v
0670: 6f 69 64 29 7b 0a 20 20 62 6c 6f 62 5f 7a 65 72  oid){.  blob_zer
0680: 6f 28 26 62 6f 64 79 29 3b 0a 20 20 62 6c 6f 62  o(&body);.  blob
0690: 5f 7a 65 72 6f 28 26 74 6f 63 29 3b 0a 20 20 6e  _zero(&toc);.  n
06a0: 45 6e 74 72 79 20 3d 20 30 3b 0a 20 20 64 6f 73  Entry = 0;.  dos
06b0: 54 69 6d 65 20 3d 20 30 3b 0a 20 20 64 6f 73 44  Time = 0;.  dosD
06c0: 61 74 65 20 3d 20 30 3b 0a 7d 0a 0a 2f 2a 0a 2a  ate = 0;.}../*.*
06d0: 2a 20 53 65 74 20 74 68 65 20 64 61 74 65 20 61  * Set the date a
06e0: 6e 64 20 74 69 6d 65 20 76 61 6c 75 65 73 20 66  nd time values f
06f0: 72 6f 6d 20 61 6e 20 49 53 4f 38 36 30 31 20 64  rom an ISO8601 d
0700: 61 74 65 20 73 74 72 69 6e 67 2e 0a 2a 2f 0a 76  ate string..*/.v
0710: 6f 69 64 20 7a 69 70 5f 73 65 74 5f 74 69 6d 65  oid zip_set_time
0720: 64 61 74 65 5f 66 72 6f 6d 5f 73 74 72 28 63 6f  date_from_str(co
0730: 6e 73 74 20 63 68 61 72 20 2a 7a 44 61 74 65 29  nst char *zDate)
0740: 7b 0a 20 20 69 6e 74 20 79 2c 20 6d 2c 20 64 3b  {.  int y, m, d;
0750: 0a 20 20 69 6e 74 20 48 2c 20 4d 2c 20 53 3b 0a  .  int H, M, S;.
0760: 0a 20 20 79 20 3d 20 61 74 6f 69 28 7a 44 61 74  .  y = atoi(zDat
0770: 65 29 3b 0a 20 20 6d 20 3d 20 61 74 6f 69 28 26  e);.  m = atoi(&
0780: 7a 44 61 74 65 5b 35 5d 29 3b 0a 20 20 64 20 3d  zDate[5]);.  d =
0790: 20 61 74 6f 69 28 26 7a 44 61 74 65 5b 38 5d 29   atoi(&zDate[8])
07a0: 3b 0a 20 20 48 20 3d 20 61 74 6f 69 28 26 7a 44  ;.  H = atoi(&zD
07b0: 61 74 65 5b 31 31 5d 29 3b 0a 20 20 4d 20 3d 20  ate[11]);.  M = 
07c0: 61 74 6f 69 28 26 7a 44 61 74 65 5b 31 34 5d 29  atoi(&zDate[14])
07d0: 3b 0a 20 20 53 20 3d 20 61 74 6f 69 28 26 7a 44  ;.  S = atoi(&zD
07e0: 61 74 65 5b 31 37 5d 29 3b 0a 20 20 64 6f 73 54  ate[17]);.  dosT
07f0: 69 6d 65 20 3d 20 28 48 3c 3c 31 31 29 20 2b 20  ime = (H<<11) + 
0800: 28 4d 3c 3c 35 29 20 2b 20 28 53 3e 3e 31 29 3b  (M<<5) + (S>>1);
0810: 0a 20 20 64 6f 73 44 61 74 65 20 3d 20 28 28 79  .  dosDate = ((y
0820: 2d 31 39 38 30 29 3c 3c 39 29 20 2b 20 28 6d 3c  -1980)<<9) + (m<
0830: 3c 35 29 20 2b 20 64 3b 0a 7d 0a 0a 2f 2a 0a 2a  <5) + d;.}../*.*
0840: 2a 20 53 65 74 20 74 68 65 20 64 61 74 65 20 61  * Set the date a
0850: 6e 64 20 74 69 6d 65 20 66 72 6f 6d 20 61 20 6a  nd time from a j
0860: 75 6c 69 61 6e 20 64 61 79 20 6e 75 6d 62 65 72  ulian day number
0870: 2e 0a 2a 2f 0a 76 6f 69 64 20 7a 69 70 5f 73 65  ..*/.void zip_se
0880: 74 5f 74 69 6d 65 64 61 74 65 28 64 6f 75 62 6c  t_timedate(doubl
0890: 65 20 72 44 61 74 65 29 7b 0a 20 20 63 68 61 72  e rDate){.  char
08a0: 20 2a 7a 44 61 74 65 20 3d 20 64 62 5f 74 65 78   *zDate = db_tex
08b0: 74 28 30 2c 20 22 53 45 4c 45 43 54 20 64 61 74  t(0, "SELECT dat
08c0: 65 74 69 6d 65 28 25 2e 31 37 67 29 22 2c 20 72  etime(%.17g)", r
08d0: 44 61 74 65 29 3b 0a 20 20 7a 69 70 5f 73 65 74  Date);.  zip_set
08e0: 5f 74 69 6d 65 64 61 74 65 5f 66 72 6f 6d 5f 73  _timedate_from_s
08f0: 74 72 28 7a 44 61 74 65 29 3b 0a 20 20 66 72 65  tr(zDate);.  fre
0900: 65 28 7a 44 61 74 65 29 3b 0a 7d 0a 0a 2f 2a 0a  e(zDate);.}../*.
0910: 2a 2a 20 41 70 70 65 6e 64 20 61 20 73 69 6e 67  ** Append a sing
0920: 6c 65 20 66 69 6c 65 20 74 6f 20 61 20 67 72 6f  le file to a gro
0930: 77 69 6e 67 20 5a 49 50 20 61 72 63 68 69 76 65  wing ZIP archive
0940: 2e 0a 2a 2a 0a 2a 2a 20 70 46 69 6c 65 20 69 73  ..**.** pFile is
0950: 20 74 68 65 20 66 69 6c 65 20 74 6f 20 62 65 20   the file to be 
0960: 61 70 70 65 6e 64 65 64 2e 20 20 7a 4e 61 6d 65  appended.  zName
0970: 20 69 73 20 74 68 65 20 6e 61 6d 65 0a 2a 2a 20   is the name.** 
0980: 74 68 61 74 20 74 68 65 20 66 69 6c 65 20 73 68  that the file sh
0990: 6f 75 6c 64 20 62 65 20 73 61 76 65 64 20 61 73  ould be saved as
09a0: 2e 0a 2a 2f 0a 76 6f 69 64 20 7a 69 70 5f 61 64  ..*/.void zip_ad
09b0: 64 5f 66 69 6c 65 28 63 6f 6e 73 74 20 63 68 61  d_file(const cha
09c0: 72 20 2a 7a 4e 61 6d 65 2c 20 63 6f 6e 73 74 20  r *zName, const 
09d0: 42 6c 6f 62 20 2a 70 46 69 6c 65 29 7b 0a 20 20  Blob *pFile){.  
09e0: 7a 5f 73 74 72 65 61 6d 20 73 74 72 65 61 6d 3b  z_stream stream;
09f0: 0a 20 20 69 6e 74 20 6e 61 6d 65 4c 65 6e 3b 0a  .  int nameLen;.
0a00: 20 20 69 6e 74 20 73 6b 69 70 3b 0a 20 20 69 6e    int skip;.  in
0a10: 74 20 74 6f 4f 75 74 3b 0a 20 20 69 6e 74 20 69  t toOut;.  int i
0a20: 53 74 61 72 74 3b 0a 20 20 69 6e 74 20 69 43 52  Start;.  int iCR
0a30: 43 3b 0a 20 20 69 6e 74 20 6e 42 79 74 65 3b 0a  C;.  int nByte;.
0a40: 20 20 69 6e 74 20 6e 42 79 74 65 43 6f 6d 70 72    int nByteCompr
0a50: 3b 0a 20 20 63 68 61 72 20 2a 7a 3b 0a 20 20 63  ;.  char *z;.  c
0a60: 68 61 72 20 7a 48 64 72 5b 33 30 5d 3b 0a 20 20  har zHdr[30];.  
0a70: 63 68 61 72 20 7a 42 75 66 5b 31 30 30 5d 3b 0a  char zBuf[100];.
0a80: 20 20 63 68 61 72 20 7a 4f 75 74 42 75 66 5b 31    char zOutBuf[1
0a90: 30 30 30 30 30 5d 3b 0a 0a 20 20 2f 2a 20 46 69  00000];..  /* Fi
0aa0: 6c 6c 20 69 6e 20 61 73 20 6d 75 63 68 20 6f 66  ll in as much of
0ab0: 20 74 68 65 20 68 65 61 64 65 72 20 61 73 20 77   the header as w
0ac0: 65 20 6b 6e 6f 77 2e 0a 20 20 2a 2f 0a 20 20 6e  e know..  */.  n
0ad0: 61 6d 65 4c 65 6e 20 3d 20 73 74 72 6c 65 6e 28  ameLen = strlen(
0ae0: 7a 4e 61 6d 65 29 3b 0a 20 20 70 75 74 33 32 28  zName);.  put32(
0af0: 26 7a 48 64 72 5b 30 5d 2c 20 30 78 30 34 30 33  &zHdr[0], 0x0403
0b00: 34 62 35 30 29 3b 0a 20 20 70 75 74 31 36 28 26  4b50);.  put16(&
0b10: 7a 48 64 72 5b 34 5d 2c 20 30 78 30 30 31 34 29  zHdr[4], 0x0014)
0b20: 3b 0a 20 20 70 75 74 31 36 28 26 7a 48 64 72 5b  ;.  put16(&zHdr[
0b30: 36 5d 2c 20 30 29 3b 0a 20 20 70 75 74 31 36 28  6], 0);.  put16(
0b40: 26 7a 48 64 72 5b 38 5d 2c 20 38 29 3b 0a 20 20  &zHdr[8], 8);.  
0b50: 70 75 74 31 36 28 26 7a 48 64 72 5b 31 30 5d 2c  put16(&zHdr[10],
0b60: 20 64 6f 73 54 69 6d 65 29 3b 0a 20 20 70 75 74   dosTime);.  put
0b70: 31 36 28 26 7a 48 64 72 5b 31 32 5d 2c 20 64 6f  16(&zHdr[12], do
0b80: 73 44 61 74 65 29 3b 0a 20 20 70 75 74 31 36 28  sDate);.  put16(
0b90: 26 7a 48 64 72 5b 32 36 5d 2c 20 6e 61 6d 65 4c  &zHdr[26], nameL
0ba0: 65 6e 29 3b 0a 20 20 70 75 74 31 36 28 26 7a 48  en);.  put16(&zH
0bb0: 64 72 5b 32 38 5d 2c 20 30 29 3b 0a 0a 20 20 2f  dr[28], 0);..  /
0bc0: 2a 20 57 72 69 74 65 20 74 68 65 20 68 65 61 64  * Write the head
0bd0: 65 72 20 61 6e 64 20 66 69 6c 65 6e 61 6d 65 2e  er and filename.
0be0: 0a 20 20 2a 2f 0a 20 20 69 53 74 61 72 74 20 3d  .  */.  iStart =
0bf0: 20 62 6c 6f 62 5f 73 69 7a 65 28 26 62 6f 64 79   blob_size(&body
0c00: 29 3b 0a 20 20 62 6c 6f 62 5f 61 70 70 65 6e 64  );.  blob_append
0c10: 28 26 62 6f 64 79 2c 20 7a 48 64 72 2c 20 33 30  (&body, zHdr, 30
0c20: 29 3b 0a 20 20 62 6c 6f 62 5f 61 70 70 65 6e 64  );.  blob_append
0c30: 28 26 62 6f 64 79 2c 20 7a 4e 61 6d 65 2c 20 6e  (&body, zName, n
0c40: 61 6d 65 4c 65 6e 29 3b 0a 0a 20 20 2f 2a 20 54  ameLen);..  /* T
0c50: 68 65 20 66 69 72 73 74 20 74 77 6f 20 62 79 74  he first two byt
0c60: 65 73 20 74 68 61 74 20 63 6f 6d 65 20 6f 75 74  es that come out
0c70: 20 6f 66 20 74 68 65 20 64 65 66 6c 61 74 65 20   of the deflate 
0c80: 63 6f 6d 70 72 65 73 73 6f 72 20 61 72 65 0a 20  compressor are. 
0c90: 20 2a 2a 20 73 6f 6d 65 20 6b 69 6e 64 20 6f 66   ** some kind of
0ca0: 20 68 65 61 64 65 72 20 74 68 61 74 20 5a 49 50   header that ZIP
0cb0: 20 64 6f 65 73 20 6e 6f 74 20 75 73 65 2e 20 20   does not use.  
0cc0: 53 6f 20 73 6b 69 70 20 74 68 65 20 66 69 72 73  So skip the firs
0cd0: 74 20 74 77 6f 0a 20 20 2a 2a 20 6f 75 74 70 75  t two.  ** outpu
0ce0: 74 20 62 79 74 65 73 2e 0a 20 20 2a 2f 0a 20 20  t bytes..  */.  
0cf0: 73 6b 69 70 20 3d 20 32 3b 0a 0a 20 20 2f 2a 20  skip = 2;..  /* 
0d00: 57 72 69 74 65 20 74 68 65 20 63 6f 6d 70 72 65  Write the compre
0d10: 73 73 65 64 20 66 69 6c 65 2e 20 20 43 6f 6d 70  ssed file.  Comp
0d20: 75 74 65 20 74 68 65 20 43 52 43 20 61 73 20 77  ute the CRC as w
0d30: 65 20 70 72 6f 67 72 65 73 73 2e 0a 20 20 2a 2f  e progress..  */
0d40: 0a 20 20 73 74 72 65 61 6d 2e 7a 61 6c 6c 6f 63  .  stream.zalloc
0d50: 20 3d 20 28 61 6c 6c 6f 63 5f 66 75 6e 63 29 30   = (alloc_func)0
0d60: 3b 0a 20 20 73 74 72 65 61 6d 2e 7a 66 72 65 65  ;.  stream.zfree
0d70: 20 3d 20 28 66 72 65 65 5f 66 75 6e 63 29 30 3b   = (free_func)0;
0d80: 0a 20 20 73 74 72 65 61 6d 2e 6f 70 61 71 75 65  .  stream.opaque
0d90: 20 3d 20 30 3b 0a 20 20 73 74 72 65 61 6d 2e 61   = 0;.  stream.a
0da0: 76 61 69 6c 5f 69 6e 20 3d 20 62 6c 6f 62 5f 73  vail_in = blob_s
0db0: 69 7a 65 28 70 46 69 6c 65 29 3b 0a 20 20 73 74  ize(pFile);.  st
0dc0: 72 65 61 6d 2e 6e 65 78 74 5f 69 6e 20 3d 20 28  ream.next_in = (
0dd0: 75 6e 73 69 67 6e 65 64 20 63 68 61 72 2a 29 62  unsigned char*)b
0de0: 6c 6f 62 5f 62 75 66 66 65 72 28 70 46 69 6c 65  lob_buffer(pFile
0df0: 29 3b 0a 20 20 73 74 72 65 61 6d 2e 61 76 61 69  );.  stream.avai
0e00: 6c 5f 6f 75 74 20 3d 20 73 69 7a 65 6f 66 28 7a  l_out = sizeof(z
0e10: 4f 75 74 42 75 66 29 3b 0a 20 20 73 74 72 65 61  OutBuf);.  strea
0e20: 6d 2e 6e 65 78 74 5f 6f 75 74 20 3d 20 28 75 6e  m.next_out = (un
0e30: 73 69 67 6e 65 64 20 63 68 61 72 2a 29 7a 4f 75  signed char*)zOu
0e40: 74 42 75 66 3b 0a 20 20 64 65 66 6c 61 74 65 49  tBuf;.  deflateI
0e50: 6e 69 74 28 26 73 74 72 65 61 6d 2c 20 39 29 3b  nit(&stream, 9);
0e60: 0a 20 20 69 43 52 43 20 3d 20 63 72 63 33 32 28  .  iCRC = crc32(
0e70: 30 2c 20 73 74 72 65 61 6d 2e 6e 65 78 74 5f 69  0, stream.next_i
0e80: 6e 2c 20 73 74 72 65 61 6d 2e 61 76 61 69 6c 5f  n, stream.avail_
0e90: 69 6e 29 3b 0a 20 20 77 68 69 6c 65 28 20 73 74  in);.  while( st
0ea0: 72 65 61 6d 2e 61 76 61 69 6c 5f 69 6e 3e 30 20  ream.avail_in>0 
0eb0: 29 7b 0a 20 20 20 20 64 65 66 6c 61 74 65 28 26  ){.    deflate(&
0ec0: 73 74 72 65 61 6d 2c 20 30 29 3b 0a 20 20 20 20  stream, 0);.    
0ed0: 74 6f 4f 75 74 20 3d 20 73 69 7a 65 6f 66 28 7a  toOut = sizeof(z
0ee0: 4f 75 74 42 75 66 29 20 2d 20 73 74 72 65 61 6d  OutBuf) - stream
0ef0: 2e 61 76 61 69 6c 5f 6f 75 74 3b 0a 20 20 20 20  .avail_out;.    
0f00: 69 66 28 20 74 6f 4f 75 74 3e 73 6b 69 70 20 29  if( toOut>skip )
0f10: 7b 0a 20 20 20 20 20 20 62 6c 6f 62 5f 61 70 70  {.      blob_app
0f20: 65 6e 64 28 26 62 6f 64 79 2c 20 26 7a 4f 75 74  end(&body, &zOut
0f30: 42 75 66 5b 73 6b 69 70 5d 2c 20 74 6f 4f 75 74  Buf[skip], toOut
0f40: 20 2d 20 73 6b 69 70 29 3b 0a 20 20 20 20 20 20   - skip);.      
0f50: 73 6b 69 70 20 3d 20 30 3b 0a 20 20 20 20 7d 65  skip = 0;.    }e
0f60: 6c 73 65 7b 0a 20 20 20 20 20 20 73 6b 69 70 20  lse{.      skip 
0f70: 2d 3d 20 74 6f 4f 75 74 3b 0a 20 20 20 20 7d 0a  -= toOut;.    }.
0f80: 20 20 20 20 73 74 72 65 61 6d 2e 61 76 61 69 6c      stream.avail
0f90: 5f 6f 75 74 20 3d 20 73 69 7a 65 6f 66 28 7a 4f  _out = sizeof(zO
0fa0: 75 74 42 75 66 29 3b 0a 20 20 20 20 73 74 72 65  utBuf);.    stre
0fb0: 61 6d 2e 6e 65 78 74 5f 6f 75 74 20 3d 20 28 75  am.next_out = (u
0fc0: 6e 73 69 67 6e 65 64 20 63 68 61 72 2a 29 7a 4f  nsigned char*)zO
0fd0: 75 74 42 75 66 3b 0a 20 20 7d 0a 20 20 64 6f 7b  utBuf;.  }.  do{
0fe0: 0a 20 20 20 20 73 74 72 65 61 6d 2e 61 76 61 69  .    stream.avai
0ff0: 6c 5f 6f 75 74 20 3d 20 73 69 7a 65 6f 66 28 7a  l_out = sizeof(z
1000: 4f 75 74 42 75 66 29 3b 0a 20 20 20 20 73 74 72  OutBuf);.    str
1010: 65 61 6d 2e 6e 65 78 74 5f 6f 75 74 20 3d 20 28  eam.next_out = (
1020: 75 6e 73 69 67 6e 65 64 20 63 68 61 72 2a 29 7a  unsigned char*)z
1030: 4f 75 74 42 75 66 3b 0a 20 20 20 20 64 65 66 6c  OutBuf;.    defl
1040: 61 74 65 28 26 73 74 72 65 61 6d 2c 20 5a 5f 46  ate(&stream, Z_F
1050: 49 4e 49 53 48 29 3b 0a 20 20 20 20 74 6f 4f 75  INISH);.    toOu
1060: 74 20 3d 20 73 69 7a 65 6f 66 28 7a 4f 75 74 42  t = sizeof(zOutB
1070: 75 66 29 20 2d 20 73 74 72 65 61 6d 2e 61 76 61  uf) - stream.ava
1080: 69 6c 5f 6f 75 74 3b 0a 20 20 20 20 69 66 28 20  il_out;.    if( 
1090: 74 6f 4f 75 74 3e 73 6b 69 70 20 29 7b 0a 20 20  toOut>skip ){.  
10a0: 20 20 20 20 62 6c 6f 62 5f 61 70 70 65 6e 64 28      blob_append(
10b0: 26 62 6f 64 79 2c 20 26 7a 4f 75 74 42 75 66 5b  &body, &zOutBuf[
10c0: 73 6b 69 70 5d 2c 20 74 6f 4f 75 74 20 2d 20 73  skip], toOut - s
10d0: 6b 69 70 29 3b 0a 20 20 20 20 20 20 73 6b 69 70  kip);.      skip
10e0: 20 3d 20 30 3b 0a 20 20 20 20 7d 65 6c 73 65 7b   = 0;.    }else{
10f0: 0a 20 20 20 20 20 20 73 6b 69 70 20 2d 3d 20 74  .      skip -= t
1100: 6f 4f 75 74 3b 0a 20 20 20 20 7d 0a 20 20 7d 77  oOut;.    }.  }w
1110: 68 69 6c 65 28 20 73 74 72 65 61 6d 2e 61 76 61  hile( stream.ava
1120: 69 6c 5f 6f 75 74 3d 3d 30 20 29 3b 0a 20 20 6e  il_out==0 );.  n
1130: 42 79 74 65 20 3d 20 73 74 72 65 61 6d 2e 74 6f  Byte = stream.to
1140: 74 61 6c 5f 69 6e 3b 0a 20 20 6e 42 79 74 65 43  tal_in;.  nByteC
1150: 6f 6d 70 72 20 3d 20 73 74 72 65 61 6d 2e 74 6f  ompr = stream.to
1160: 74 61 6c 5f 6f 75 74 20 2d 20 32 3b 0a 20 20 64  tal_out - 2;.  d
1170: 65 66 6c 61 74 65 45 6e 64 28 26 73 74 72 65 61  eflateEnd(&strea
1180: 6d 29 3b 0a 0a 20 20 2f 2a 20 47 6f 20 62 61 63  m);..  /* Go bac
1190: 6b 20 61 6e 64 20 77 72 69 74 65 20 74 68 65 20  k and write the 
11a0: 68 65 61 64 65 72 2c 20 6e 6f 77 20 74 68 61 74  header, now that
11b0: 20 77 65 20 6b 6e 6f 77 20 74 68 65 20 63 6f 6d   we know the com
11c0: 70 72 65 73 73 65 64 20 66 69 6c 65 20 73 69 7a  pressed file siz
11d0: 65 2e 0a 20 20 2a 2f 0a 20 20 7a 20 3d 20 26 62  e..  */.  z = &b
11e0: 6c 6f 62 5f 62 75 66 66 65 72 28 26 62 6f 64 79  lob_buffer(&body
11f0: 29 5b 69 53 74 61 72 74 5d 3b 0a 20 20 70 75 74  )[iStart];.  put
1200: 33 32 28 26 7a 5b 31 34 5d 2c 20 69 43 52 43 29  32(&z[14], iCRC)
1210: 3b 0a 20 20 70 75 74 33 32 28 26 7a 5b 31 38 5d  ;.  put32(&z[18]
1220: 2c 20 6e 42 79 74 65 43 6f 6d 70 72 29 3b 0a 20  , nByteCompr);. 
1230: 20 70 75 74 33 32 28 26 7a 5b 32 32 5d 2c 20 6e   put32(&z[22], n
1240: 42 79 74 65 29 3b 0a 0a 20 20 2f 2a 20 4d 61 6b  Byte);..  /* Mak
1250: 65 20 61 6e 20 65 6e 74 72 79 20 69 6e 20 74 68  e an entry in th
1260: 65 20 74 61 62 6c 65 73 20 6f 66 20 63 6f 6e 74  e tables of cont
1270: 65 6e 74 73 0a 20 20 2a 2f 0a 20 20 6d 65 6d 73  ents.  */.  mems
1280: 65 74 28 7a 42 75 66 2c 20 30 2c 20 73 69 7a 65  et(zBuf, 0, size
1290: 6f 66 28 7a 42 75 66 29 29 3b 0a 20 20 70 75 74  of(zBuf));.  put
12a0: 33 32 28 26 7a 42 75 66 5b 30 5d 2c 20 30 78 30  32(&zBuf[0], 0x0
12b0: 32 30 31 34 62 35 30 29 3b 0a 20 20 70 75 74 31  2014b50);.  put1
12c0: 36 28 26 7a 42 75 66 5b 34 5d 2c 20 30 78 30 33  6(&zBuf[4], 0x03
12d0: 31 37 29 3b 0a 20 20 70 75 74 31 36 28 26 7a 42  17);.  put16(&zB
12e0: 75 66 5b 36 5d 2c 20 30 78 30 30 31 34 29 3b 0a  uf[6], 0x0014);.
12f0: 20 20 70 75 74 31 36 28 26 7a 42 75 66 5b 38 5d    put16(&zBuf[8]
1300: 2c 20 30 29 3b 0a 20 20 70 75 74 31 36 28 26 7a  , 0);.  put16(&z
1310: 42 75 66 5b 31 30 5d 2c 20 30 78 30 30 30 38 29  Buf[10], 0x0008)
1320: 3b 0a 20 20 70 75 74 31 36 28 26 7a 42 75 66 5b  ;.  put16(&zBuf[
1330: 31 32 5d 2c 20 64 6f 73 54 69 6d 65 29 3b 0a 20  12], dosTime);. 
1340: 20 70 75 74 31 36 28 26 7a 42 75 66 5b 31 34 5d   put16(&zBuf[14]
1350: 2c 20 64 6f 73 44 61 74 65 29 3b 0a 20 20 70 75  , dosDate);.  pu
1360: 74 33 32 28 26 7a 42 75 66 5b 31 36 5d 2c 20 69  t32(&zBuf[16], i
1370: 43 52 43 29 3b 0a 20 20 70 75 74 33 32 28 26 7a  CRC);.  put32(&z
1380: 42 75 66 5b 32 30 5d 2c 20 6e 42 79 74 65 43 6f  Buf[20], nByteCo
1390: 6d 70 72 29 3b 0a 20 20 70 75 74 33 32 28 26 7a  mpr);.  put32(&z
13a0: 42 75 66 5b 32 34 5d 2c 20 6e 42 79 74 65 29 3b  Buf[24], nByte);
13b0: 0a 20 20 70 75 74 31 36 28 26 7a 42 75 66 5b 32  .  put16(&zBuf[2
13c0: 38 5d 2c 20 6e 61 6d 65 4c 65 6e 29 3b 0a 20 20  8], nameLen);.  
13d0: 70 75 74 31 36 28 26 7a 42 75 66 5b 33 30 5d 2c  put16(&zBuf[30],
13e0: 20 30 29 3b 0a 20 20 70 75 74 31 36 28 26 7a 42   0);.  put16(&zB
13f0: 75 66 5b 33 32 5d 2c 20 30 29 3b 0a 20 20 70 75  uf[32], 0);.  pu
1400: 74 31 36 28 26 7a 42 75 66 5b 33 34 5d 2c 20 30  t16(&zBuf[34], 0
1410: 29 3b 0a 20 20 70 75 74 31 36 28 26 7a 42 75 66  );.  put16(&zBuf
1420: 5b 33 36 5d 2c 20 30 29 3b 0a 20 20 70 75 74 33  [36], 0);.  put3
1430: 32 28 26 7a 42 75 66 5b 33 38 5d 2c 20 28 28 75  2(&zBuf[38], ((u
1440: 6e 73 69 67 6e 65 64 29 28 30 31 30 30 30 30 30  nsigned)(0100000
1450: 20 7c 20 30 36 34 34 29 29 3c 3c 31 36 29 3b 0a   | 0644))<<16);.
1460: 20 20 70 75 74 33 32 28 26 7a 42 75 66 5b 34 32    put32(&zBuf[42
1470: 5d 2c 20 69 53 74 61 72 74 29 3b 0a 20 20 62 6c  ], iStart);.  bl
1480: 6f 62 5f 61 70 70 65 6e 64 28 26 74 6f 63 2c 20  ob_append(&toc, 
1490: 7a 42 75 66 2c 20 34 36 29 3b 0a 20 20 62 6c 6f  zBuf, 46);.  blo
14a0: 62 5f 61 70 70 65 6e 64 28 26 74 6f 63 2c 20 7a  b_append(&toc, z
14b0: 4e 61 6d 65 2c 20 6e 61 6d 65 4c 65 6e 29 3b 0a  Name, nameLen);.
14c0: 20 20 6e 45 6e 74 72 79 2b 2b 3b 0a 7d 0a 0a 0a    nEntry++;.}...
14d0: 2f 2a 0a 2a 2a 20 57 72 69 74 65 20 74 68 65 20  /*.** Write the 
14e0: 5a 49 50 20 61 72 63 68 69 76 65 20 69 6e 74 6f  ZIP archive into
14f0: 20 74 68 65 20 67 69 76 65 6e 20 42 4c 4f 42 2e   the given BLOB.
1500: 0a 2a 2f 0a 76 6f 69 64 20 7a 69 70 5f 63 6c 6f  .*/.void zip_clo
1510: 73 65 28 42 6c 6f 62 20 2a 70 5a 69 70 29 7b 0a  se(Blob *pZip){.
1520: 20 20 69 6e 74 20 69 54 6f 63 53 74 61 72 74 3b    int iTocStart;
1530: 0a 20 20 69 6e 74 20 69 54 6f 63 45 6e 64 3b 0a  .  int iTocEnd;.
1540: 20 20 63 68 61 72 20 7a 42 75 66 5b 33 30 5d 3b    char zBuf[30];
1550: 0a 0a 20 20 69 54 6f 63 53 74 61 72 74 20 3d 20  ..  iTocStart = 
1560: 62 6c 6f 62 5f 73 69 7a 65 28 26 62 6f 64 79 29  blob_size(&body)
1570: 3b 0a 20 20 62 6c 6f 62 5f 61 70 70 65 6e 64 28  ;.  blob_append(
1580: 26 62 6f 64 79 2c 20 62 6c 6f 62 5f 62 75 66 66  &body, blob_buff
1590: 65 72 28 26 74 6f 63 29 2c 20 62 6c 6f 62 5f 73  er(&toc), blob_s
15a0: 69 7a 65 28 26 74 6f 63 29 29 3b 0a 20 20 69 54  ize(&toc));.  iT
15b0: 6f 63 45 6e 64 20 3d 20 62 6c 6f 62 5f 73 69 7a  ocEnd = blob_siz
15c0: 65 28 26 62 6f 64 79 29 3b 0a 0a 20 20 6d 65 6d  e(&body);..  mem
15d0: 73 65 74 28 7a 42 75 66 2c 20 30 2c 20 73 69 7a  set(zBuf, 0, siz
15e0: 65 6f 66 28 7a 42 75 66 29 29 3b 0a 20 20 70 75  eof(zBuf));.  pu
15f0: 74 33 32 28 26 7a 42 75 66 5b 30 5d 2c 20 30 78  t32(&zBuf[0], 0x
1600: 30 36 30 35 34 62 35 30 29 3b 0a 20 20 70 75 74  06054b50);.  put
1610: 31 36 28 26 7a 42 75 66 5b 34 5d 2c 20 30 29 3b  16(&zBuf[4], 0);
1620: 0a 20 20 70 75 74 31 36 28 26 7a 42 75 66 5b 36  .  put16(&zBuf[6
1630: 5d 2c 20 30 29 3b 0a 20 20 70 75 74 31 36 28 26  ], 0);.  put16(&
1640: 7a 42 75 66 5b 38 5d 2c 20 6e 45 6e 74 72 79 29  zBuf[8], nEntry)
1650: 3b 0a 20 20 70 75 74 31 36 28 26 7a 42 75 66 5b  ;.  put16(&zBuf[
1660: 31 30 5d 2c 20 6e 45 6e 74 72 79 29 3b 0a 20 20  10], nEntry);.  
1670: 70 75 74 33 32 28 26 7a 42 75 66 5b 31 32 5d 2c  put32(&zBuf[12],
1680: 20 69 54 6f 63 45 6e 64 20 2d 20 69 54 6f 63 53   iTocEnd - iTocS
1690: 74 61 72 74 29 3b 0a 20 20 70 75 74 33 32 28 26  tart);.  put32(&
16a0: 7a 42 75 66 5b 31 36 5d 2c 20 69 54 6f 63 53 74  zBuf[16], iTocSt
16b0: 61 72 74 29 3b 0a 20 20 70 75 74 31 36 28 26 7a  art);.  put16(&z
16c0: 42 75 66 5b 32 30 5d 2c 20 30 29 3b 0a 20 20 62  Buf[20], 0);.  b
16d0: 6c 6f 62 5f 61 70 70 65 6e 64 28 26 62 6f 64 79  lob_append(&body
16e0: 2c 20 7a 42 75 66 2c 20 32 32 29 3b 0a 20 20 62  , zBuf, 22);.  b
16f0: 6c 6f 62 5f 72 65 73 65 74 28 26 74 6f 63 29 3b  lob_reset(&toc);
1700: 0a 20 20 2a 70 5a 69 70 20 3d 20 62 6f 64 79 3b  .  *pZip = body;
1710: 0a 20 20 62 6c 6f 62 5f 7a 65 72 6f 28 26 62 6f  .  blob_zero(&bo
1720: 64 79 29 3b 0a 20 20 6e 45 6e 74 72 79 20 3d 20  dy);.  nEntry = 
1730: 30 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 43 4f 4d 4d  0;.}../*.** COMM
1740: 41 4e 44 3a 20 74 65 73 74 2d 66 69 6c 65 7a 69  AND: test-filezi
1750: 70 0a 2a 2a 0a 2a 2a 20 47 65 6e 65 72 61 74 65  p.**.** Generate
1760: 20 61 20 5a 49 50 20 61 72 63 68 69 76 65 20 73   a ZIP archive s
1770: 70 65 63 69 66 69 65 64 20 62 79 20 74 68 65 20  pecified by the 
1780: 66 69 72 73 74 20 61 72 67 75 6d 65 6e 74 20 74  first argument t
1790: 68 61 74 0a 2a 2a 20 63 6f 6e 74 61 69 6e 73 20  hat.** contains 
17a0: 66 69 6c 65 73 20 67 69 76 65 6e 20 69 6e 20 74  files given in t
17b0: 68 65 20 73 65 63 6f 6e 64 20 61 6e 64 20 73 75  he second and su
17c0: 62 73 65 71 75 65 6e 74 20 61 72 67 75 6d 65 6e  bsequent argumen
17d0: 74 73 2e 0a 2a 2f 0a 76 6f 69 64 20 66 69 6c 65  ts..*/.void file
17e0: 7a 69 70 5f 63 6d 64 28 76 6f 69 64 29 7b 0a 20  zip_cmd(void){. 
17f0: 20 69 6e 74 20 69 3b 0a 20 20 42 6c 6f 62 20 7a   int i;.  Blob z
1800: 69 70 3b 0a 20 20 42 6c 6f 62 20 66 69 6c 65 3b  ip;.  Blob file;
1810: 0a 20 20 69 66 28 20 67 2e 61 72 67 63 3c 33 20  .  if( g.argc<3 
1820: 29 7b 0a 20 20 20 20 75 73 61 67 65 28 22 41 52  ){.    usage("AR
1830: 43 48 49 56 45 20 46 49 4c 45 2e 2e 2e 2e 22 29  CHIVE FILE....")
1840: 3b 0a 20 20 7d 0a 20 20 7a 69 70 5f 6f 70 65 6e  ;.  }.  zip_open
1850: 28 29 3b 0a 20 20 66 6f 72 28 69 3d 33 3b 20 69  ();.  for(i=3; i
1860: 3c 67 2e 61 72 67 63 3b 20 69 2b 2b 29 7b 0a 20  <g.argc; i++){. 
1870: 20 20 20 62 6c 6f 62 5f 7a 65 72 6f 28 26 66 69     blob_zero(&fi
1880: 6c 65 29 3b 0a 20 20 20 20 62 6c 6f 62 5f 72 65  le);.    blob_re
1890: 61 64 5f 66 72 6f 6d 5f 66 69 6c 65 28 26 66 69  ad_from_file(&fi
18a0: 6c 65 2c 20 67 2e 61 72 67 76 5b 69 5d 29 3b 0a  le, g.argv[i]);.
18b0: 20 20 20 20 7a 69 70 5f 61 64 64 5f 66 69 6c 65      zip_add_file
18c0: 28 67 2e 61 72 67 76 5b 69 5d 2c 20 26 66 69 6c  (g.argv[i], &fil
18d0: 65 29 3b 0a 20 20 20 20 62 6c 6f 62 5f 72 65 73  e);.    blob_res
18e0: 65 74 28 26 66 69 6c 65 29 3b 0a 20 20 7d 0a 20  et(&file);.  }. 
18f0: 20 7a 69 70 5f 63 6c 6f 73 65 28 26 7a 69 70 29   zip_close(&zip)
1900: 3b 0a 20 20 62 6c 6f 62 5f 77 72 69 74 65 5f 74  ;.  blob_write_t
1910: 6f 5f 66 69 6c 65 28 26 7a 69 70 2c 20 67 2e 61  o_file(&zip, g.a
1920: 72 67 76 5b 32 5d 29 3b 0a 7d 0a 0a 2f 2a 0a 2a  rgv[2]);.}../*.*
1930: 2a 20 47 69 76 65 6e 20 74 68 65 20 52 49 44 20  * Given the RID 
1940: 66 6f 72 20 61 20 6d 61 6e 69 66 65 73 74 2c 20  for a manifest, 
1950: 63 6f 6e 73 74 72 75 63 74 20 61 20 5a 49 50 20  construct a ZIP 
1960: 61 72 63 68 69 76 65 20 63 6f 6e 74 61 69 6e 69  archive containi
1970: 6e 67 0a 2a 2a 20 61 6c 6c 20 66 69 6c 65 73 20  ng.** all files 
1980: 69 6e 20 74 68 65 20 63 6f 72 72 65 73 70 6f 6e  in the correspon
1990: 64 69 6e 67 20 62 61 73 65 6c 69 6e 65 2e 0a 2a  ding baseline..*
19a0: 2a 0a 2a 2a 20 49 66 20 52 49 44 20 69 73 20 66  *.** If RID is f
19b0: 6f 72 20 61 6e 20 6f 62 6a 65 63 74 20 74 68 61  or an object tha
19c0: 74 20 69 73 20 6e 6f 74 20 61 20 72 65 61 6c 20  t is not a real 
19d0: 6d 61 6e 69 66 65 73 74 2c 20 74 68 65 6e 20 74  manifest, then t
19e0: 68 65 0a 2a 2a 20 72 65 73 75 6c 74 69 6e 67 20  he.** resulting 
19f0: 5a 49 50 20 61 72 63 68 69 76 65 20 63 6f 6e 74  ZIP archive cont
1a00: 61 69 6e 73 20 61 20 73 69 6e 67 6c 65 20 66 69  ains a single fi
1a10: 6c 65 20 77 68 69 63 68 20 69 73 20 74 68 65 20  le which is the 
1a20: 52 49 44 0a 2a 2a 20 6f 62 6a 65 63 74 2e 0a 2a  RID.** object..*
1a30: 2a 0a 2a 2a 20 49 66 20 74 68 65 20 52 49 44 20  *.** If the RID 
1a40: 6f 62 6a 65 63 74 20 64 6f 65 73 20 6e 6f 74 20  object does not 
1a50: 65 78 69 73 74 20 69 6e 20 74 68 65 20 72 65 70  exist in the rep
1a60: 6f 73 69 74 6f 72 79 2c 20 74 68 65 6e 0a 2a 2a  ository, then.**
1a70: 20 70 5a 69 70 20 69 73 20 7a 65 72 6f 65 64 2e   pZip is zeroed.
1a80: 0a 2a 2a 0a 2a 2a 20 7a 44 69 72 20 69 73 20 61  .**.** zDir is a
1a90: 20 22 73 79 6e 74 68 65 74 69 63 22 20 73 75 62   "synthetic" sub
1aa0: 64 69 72 65 63 74 6f 72 79 20 77 68 69 63 68 20  directory which 
1ab0: 61 6c 6c 20 7a 69 70 70 65 64 20 66 69 6c 65 73  all zipped files
1ac0: 20 67 65 74 0a 2a 2a 20 61 64 64 65 64 20 74 6f   get.** added to
1ad0: 20 61 73 20 70 61 72 74 20 6f 66 20 74 68 65 20   as part of the 
1ae0: 7a 69 70 20 66 69 6c 65 2e 20 49 74 20 6d 61 79  zip file. It may
1af0: 20 62 65 20 30 20 6f 72 20 61 6e 20 65 6d 70 74   be 0 or an empt
1b00: 79 20 73 74 72 69 6e 67 2c 0a 2a 2a 20 69 6e 20  y string,.** in 
1b10: 77 68 69 63 68 20 63 61 73 65 20 69 74 20 69 73  which case it is
1b20: 20 69 67 6e 6f 72 65 64 2e 20 54 68 65 20 69 6e   ignored. The in
1b30: 74 65 6e 74 69 6f 6e 20 69 73 20 74 6f 20 63 72  tention is to cr
1b40: 65 61 74 65 20 61 20 7a 69 70 20 77 68 69 63 68  eate a zip which
1b50: 0a 2a 2a 20 70 6f 6c 69 74 65 6c 79 20 65 78 70  .** politely exp
1b60: 61 6e 64 73 20 69 6e 74 6f 20 61 20 73 75 62 64  ands into a subd
1b70: 69 72 20 69 6e 73 74 65 61 64 20 6f 66 20 66 69  ir instead of fi
1b80: 6c 6c 69 6e 67 20 79 6f 75 72 20 63 75 72 72 65  lling your curre
1b90: 6e 74 20 64 69 72 0a 2a 2a 20 77 69 74 68 20 73  nt dir.** with s
1ba0: 6f 75 72 63 65 20 66 69 6c 65 73 2e 20 46 6f 72  ource files. For
1bb0: 20 65 78 61 6d 70 6c 65 2c 20 70 61 73 73 20 61   example, pass a
1bc0: 20 55 55 49 44 20 6f 72 20 22 50 72 6f 6a 65 63   UUID or "Projec
1bd0: 74 4e 61 6d 65 22 2e 0a 2a 2a 0a 2a 2f 0a 76 6f  tName"..**.*/.vo
1be0: 69 64 20 7a 69 70 5f 6f 66 5f 62 61 73 65 6c 69  id zip_of_baseli
1bf0: 6e 65 28 69 6e 74 20 72 69 64 2c 20 42 6c 6f 62  ne(int rid, Blob
1c00: 20 2a 70 5a 69 70 2c 20 63 6f 6e 73 74 20 63 68   *pZip, const ch
1c10: 61 72 20 2a 7a 44 69 72 29 7b 0a 20 20 69 6e 74  ar *zDir){.  int
1c20: 20 69 3b 0a 20 20 42 6c 6f 62 20 6d 66 69 6c 65   i;.  Blob mfile
1c30: 2c 20 66 69 6c 65 2c 20 68 61 73 68 3b 0a 20 20  , file, hash;.  
1c40: 4d 61 6e 69 66 65 73 74 20 6d 3b 0a 20 20 42 6c  Manifest m;.  Bl
1c50: 6f 62 20 66 69 6c 65 6e 61 6d 65 3b 0a 20 20 69  ob filename;.  i
1c60: 6e 74 20 6e 50 72 65 66 69 78 3b 0a 20 20 0a 20  nt nPrefix;.  . 
1c70: 20 63 6f 6e 74 65 6e 74 5f 67 65 74 28 72 69 64   content_get(rid
1c80: 2c 20 26 6d 66 69 6c 65 29 3b 0a 20 20 69 66 28  , &mfile);.  if(
1c90: 20 62 6c 6f 62 5f 73 69 7a 65 28 26 6d 66 69 6c   blob_size(&mfil
1ca0: 65 29 3d 3d 30 20 29 7b 0a 20 20 20 20 62 6c 6f  e)==0 ){.    blo
1cb0: 62 5f 7a 65 72 6f 28 70 5a 69 70 29 3b 0a 20 20  b_zero(pZip);.  
1cc0: 20 20 72 65 74 75 72 6e 3b 0a 20 20 7d 0a 20 20    return;.  }.  
1cd0: 62 6c 6f 62 5f 7a 65 72 6f 28 26 66 69 6c 65 29  blob_zero(&file)
1ce0: 3b 0a 20 20 62 6c 6f 62 5f 7a 65 72 6f 28 26 68  ;.  blob_zero(&h
1cf0: 61 73 68 29 3b 0a 20 20 62 6c 6f 62 5f 63 6f 70  ash);.  blob_cop
1d00: 79 28 26 66 69 6c 65 2c 20 26 6d 66 69 6c 65 29  y(&file, &mfile)
1d10: 3b 0a 20 20 62 6c 6f 62 5f 7a 65 72 6f 28 26 66  ;.  blob_zero(&f
1d20: 69 6c 65 6e 61 6d 65 29 3b 0a 20 20 7a 69 70 5f  ilename);.  zip_
1d30: 6f 70 65 6e 28 29 3b 0a 0a 20 20 69 66 28 20 7a  open();..  if( z
1d40: 44 69 72 20 26 26 20 7a 44 69 72 5b 30 5d 20 29  Dir && zDir[0] )
1d50: 7b 0a 20 20 20 20 62 6c 6f 62 5f 61 70 70 65 6e  {.    blob_appen
1d60: 64 66 28 26 66 69 6c 65 6e 61 6d 65 2c 20 22 25  df(&filename, "%
1d70: 73 2f 22 2c 20 7a 44 69 72 29 3b 0a 20 20 7d 0a  s/", zDir);.  }.
1d80: 20 20 6e 50 72 65 66 69 78 20 3d 20 62 6c 6f 62    nPrefix = blob
1d90: 5f 73 69 7a 65 28 26 66 69 6c 65 6e 61 6d 65 29  _size(&filename)
1da0: 3b 0a 0a 20 20 69 66 28 20 6d 61 6e 69 66 65 73  ;..  if( manifes
1db0: 74 5f 70 61 72 73 65 28 26 6d 2c 20 26 6d 66 69  t_parse(&m, &mfi
1dc0: 6c 65 29 20 29 7b 0a 20 20 20 20 7a 69 70 5f 73  le) ){.    zip_s
1dd0: 65 74 5f 74 69 6d 65 64 61 74 65 28 6d 2e 72 44  et_timedate(m.rD
1de0: 61 74 65 29 3b 0a 20 20 20 20 62 6c 6f 62 5f 61  ate);.    blob_a
1df0: 70 70 65 6e 64 28 26 66 69 6c 65 6e 61 6d 65 2c  ppend(&filename,
1e00: 20 22 6d 61 6e 69 66 65 73 74 22 2c 20 2d 31 29   "manifest", -1)
1e10: 3b 0a 20 20 20 20 7a 69 70 5f 61 64 64 5f 66 69  ;.    zip_add_fi
1e20: 6c 65 28 62 6c 6f 62 5f 73 74 72 28 26 66 69 6c  le(blob_str(&fil
1e30: 65 6e 61 6d 65 29 2c 20 26 66 69 6c 65 29 3b 0a  ename), &file);.
1e40: 20 20 20 20 73 68 61 31 73 75 6d 5f 62 6c 6f 62      sha1sum_blob
1e50: 28 26 66 69 6c 65 2c 20 26 68 61 73 68 29 3b 0a  (&file, &hash);.
1e60: 20 20 20 20 62 6c 6f 62 5f 72 65 73 65 74 28 26      blob_reset(&
1e70: 66 69 6c 65 29 3b 0a 20 20 20 20 62 6c 6f 62 5f  file);.    blob_
1e80: 61 70 70 65 6e 64 28 26 68 61 73 68 2c 20 22 5c  append(&hash, "\
1e90: 6e 22 2c 20 31 29 3b 0a 20 20 20 20 62 6c 6f 62  n", 1);.    blob
1ea0: 5f 72 65 73 69 7a 65 28 26 66 69 6c 65 6e 61 6d  _resize(&filenam
1eb0: 65 2c 20 6e 50 72 65 66 69 78 29 3b 0a 20 20 20  e, nPrefix);.   
1ec0: 20 62 6c 6f 62 5f 61 70 70 65 6e 64 28 26 66 69   blob_append(&fi
1ed0: 6c 65 6e 61 6d 65 2c 20 22 6d 61 6e 69 66 65 73  lename, "manifes
1ee0: 74 2e 75 75 69 64 22 2c 20 2d 31 29 3b 0a 20 20  t.uuid", -1);.  
1ef0: 20 20 7a 69 70 5f 61 64 64 5f 66 69 6c 65 28 62    zip_add_file(b
1f00: 6c 6f 62 5f 73 74 72 28 26 66 69 6c 65 6e 61 6d  lob_str(&filenam
1f10: 65 29 2c 20 26 68 61 73 68 29 3b 0a 20 20 20 20  e), &hash);.    
1f20: 62 6c 6f 62 5f 72 65 73 65 74 28 26 68 61 73 68  blob_reset(&hash
1f30: 29 3b 0a 20 20 20 20 66 6f 72 28 69 3d 30 3b 20  );.    for(i=0; 
1f40: 69 3c 6d 2e 6e 46 69 6c 65 3b 20 69 2b 2b 29 7b  i<m.nFile; i++){
1f50: 0a 20 20 20 20 20 20 69 6e 74 20 66 69 64 20 3d  .      int fid =
1f60: 20 75 75 69 64 5f 74 6f 5f 72 69 64 28 6d 2e 61   uuid_to_rid(m.a
1f70: 46 69 6c 65 5b 69 5d 2e 7a 55 75 69 64 2c 20 30  File[i].zUuid, 0
1f80: 29 3b 0a 20 20 20 20 20 20 69 66 28 20 66 69 64  );.      if( fid
1f90: 20 29 7b 0a 20 20 20 20 20 20 20 20 63 6f 6e 74   ){.        cont
1fa0: 65 6e 74 5f 67 65 74 28 66 69 64 2c 20 26 66 69  ent_get(fid, &fi
1fb0: 6c 65 29 3b 0a 20 20 20 20 20 20 20 20 62 6c 6f  le);.        blo
1fc0: 62 5f 72 65 73 69 7a 65 28 26 66 69 6c 65 6e 61  b_resize(&filena
1fd0: 6d 65 2c 20 6e 50 72 65 66 69 78 29 3b 0a 20 20  me, nPrefix);.  
1fe0: 20 20 20 20 20 20 62 6c 6f 62 5f 61 70 70 65 6e        blob_appen
1ff0: 64 28 26 66 69 6c 65 6e 61 6d 65 2c 20 6d 2e 61  d(&filename, m.a
2000: 46 69 6c 65 5b 69 5d 2e 7a 4e 61 6d 65 2c 20 2d  File[i].zName, -
2010: 31 29 3b 0a 20 20 20 20 20 20 20 20 7a 69 70 5f  1);.        zip_
2020: 61 64 64 5f 66 69 6c 65 28 62 6c 6f 62 5f 73 74  add_file(blob_st
2030: 72 28 26 66 69 6c 65 6e 61 6d 65 29 2c 20 26 66  r(&filename), &f
2040: 69 6c 65 29 3b 0a 20 20 20 20 20 20 20 20 62 6c  ile);.        bl
2050: 6f 62 5f 72 65 73 65 74 28 26 66 69 6c 65 29 3b  ob_reset(&file);
2060: 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a 20  .      }.    }. 
2070: 20 20 20 6d 61 6e 69 66 65 73 74 5f 63 6c 65 61     manifest_clea
2080: 72 28 26 6d 29 3b 0a 20 20 7d 65 6c 73 65 7b 0a  r(&m);.  }else{.
2090: 20 20 20 20 62 6c 6f 62 5f 72 65 73 65 74 28 26      blob_reset(&
20a0: 6d 66 69 6c 65 29 3b 0a 20 20 20 20 62 6c 6f 62  mfile);.    blob
20b0: 5f 72 65 73 65 74 28 26 66 69 6c 65 29 3b 0a 20  _reset(&file);. 
20c0: 20 7d 0a 20 20 62 6c 6f 62 5f 72 65 73 65 74 28   }.  blob_reset(
20d0: 26 66 69 6c 65 6e 61 6d 65 29 3b 0a 20 20 7a 69  &filename);.  zi
20e0: 70 5f 63 6c 6f 73 65 28 70 5a 69 70 29 3b 0a 7d  p_close(pZip);.}
20f0: 0a 0a 2f 2a 0a 2a 2a 20 43 4f 4d 4d 41 4e 44 3a  ../*.** COMMAND:
2100: 20 74 65 73 74 2d 62 61 73 65 6c 69 6e 65 2d 7a   test-baseline-z
2110: 69 70 0a 2a 2a 0a 2a 2a 20 47 65 6e 65 72 61 74  ip.**.** Generat
2120: 65 20 61 20 5a 49 50 20 61 72 63 68 69 76 65 20  e a ZIP archive 
2130: 66 6f 72 20 61 20 73 70 65 63 69 66 69 65 64 20  for a specified 
2140: 62 61 73 65 6c 69 6e 65 2e 0a 2a 2f 0a 76 6f 69  baseline..*/.voi
2150: 64 20 62 61 73 65 6c 69 6e 65 5f 7a 69 70 5f 63  d baseline_zip_c
2160: 6d 64 28 76 6f 69 64 29 7b 0a 20 20 69 6e 74 20  md(void){.  int 
2170: 72 69 64 3b 0a 20 20 42 6c 6f 62 20 7a 69 70 3b  rid;.  Blob zip;
2180: 0a 20 20 69 66 28 20 67 2e 61 72 67 63 21 3d 34  .  if( g.argc!=4
2190: 20 29 7b 0a 20 20 20 20 75 73 61 67 65 28 22 55   ){.    usage("U
21a0: 55 49 44 20 5a 49 50 46 49 4c 45 22 29 3b 0a 20  UID ZIPFILE");. 
21b0: 20 7d 0a 20 20 64 62 5f 6d 75 73 74 5f 62 65 5f   }.  db_must_be_
21c0: 77 69 74 68 69 6e 5f 74 72 65 65 28 29 3b 0a 20  within_tree();. 
21d0: 20 72 69 64 20 3d 20 6e 61 6d 65 5f 74 6f 5f 72   rid = name_to_r
21e0: 69 64 28 67 2e 61 72 67 76 5b 32 5d 29 3b 0a 20  id(g.argv[2]);. 
21f0: 20 7a 69 70 5f 6f 66 5f 62 61 73 65 6c 69 6e 65   zip_of_baseline
2200: 28 72 69 64 2c 20 26 7a 69 70 2c 20 67 2e 61 72  (rid, &zip, g.ar
2210: 67 76 5b 32 5d 29 3b 0a 20 20 62 6c 6f 62 5f 77  gv[2]);.  blob_w
2220: 72 69 74 65 5f 74 6f 5f 66 69 6c 65 28 26 7a 69  rite_to_file(&zi
2230: 70 2c 20 67 2e 61 72 67 76 5b 33 5d 29 3b 0a 7d  p, g.argv[3]);.}
2240: 0a 0a 2f 2a 0a 2a 2a 20 57 45 42 50 41 47 45 3a  ../*.** WEBPAGE:
2250: 20 7a 69 70 0a 2a 2a 20 55 52 4c 3a 20 2f 7a 69   zip.** URL: /zi
2260: 70 2f 52 49 44 2e 7a 69 70 0a 2a 2a 0a 2a 2a 20  p/RID.zip.**.** 
2270: 47 65 6e 65 72 61 74 65 20 61 20 5a 49 50 20 61  Generate a ZIP a
2280: 72 63 68 69 76 65 20 66 6f 72 20 74 68 65 20 62  rchive for the b
2290: 61 73 65 6c 69 6e 65 2e 0a 2a 2a 20 52 65 74 75  aseline..** Retu
22a0: 72 6e 20 74 68 61 74 20 5a 49 50 20 61 72 63 68  rn that ZIP arch
22b0: 69 76 65 20 61 73 20 74 68 65 20 48 54 54 50 20  ive as the HTTP 
22c0: 72 65 70 6c 79 20 63 6f 6e 74 65 6e 74 2e 0a 2a  reply content..*
22d0: 2f 0a 76 6f 69 64 20 62 61 73 65 6c 69 6e 65 5f  /.void baseline_
22e0: 7a 69 70 5f 70 61 67 65 28 76 6f 69 64 29 7b 0a  zip_page(void){.
22f0: 20 20 69 6e 74 20 72 69 64 3b 0a 20 20 63 68 61    int rid;.  cha
2300: 72 20 2a 7a 4e 61 6d 65 2c 20 2a 7a 52 69 64 3b  r *zName, *zRid;
2310: 0a 20 20 69 6e 74 20 6e 4e 61 6d 65 2c 20 6e 52  .  int nName, nR
2320: 69 64 3b 0a 20 20 42 6c 6f 62 20 7a 69 70 3b 0a  id;.  Blob zip;.
2330: 0a 20 20 6c 6f 67 69 6e 5f 63 68 65 63 6b 5f 63  .  login_check_c
2340: 72 65 64 65 6e 74 69 61 6c 73 28 29 3b 0a 20 20  redentials();.  
2350: 69 66 28 20 21 67 2e 6f 6b 5a 69 70 20 26 26 20  if( !g.okZip && 
2360: 28 21 67 2e 6f 6b 52 65 61 64 20 7c 7c 20 21 67  (!g.okRead || !g
2370: 2e 6f 6b 48 69 73 74 6f 72 79 29 20 29 7b 20 6c  .okHistory) ){ l
2380: 6f 67 69 6e 5f 6e 65 65 64 65 64 28 29 3b 20 72  ogin_needed(); r
2390: 65 74 75 72 6e 3b 20 7d 0a 20 20 7a 4e 61 6d 65  eturn; }.  zName
23a0: 20 3d 20 6d 70 72 69 6e 74 66 28 22 25 73 22 2c   = mprintf("%s",
23b0: 20 50 44 28 22 6e 61 6d 65 22 2c 22 22 29 29 3b   PD("name",""));
23c0: 0a 20 20 6e 4e 61 6d 65 20 3d 20 73 74 72 6c 65  .  nName = strle
23d0: 6e 28 7a 4e 61 6d 65 29 3b 0a 20 20 7a 52 69 64  n(zName);.  zRid
23e0: 20 3d 20 6d 70 72 69 6e 74 66 28 22 25 73 22 2c   = mprintf("%s",
23f0: 20 50 44 28 22 75 75 69 64 22 2c 22 22 29 29 3b   PD("uuid",""));
2400: 0a 20 20 6e 52 69 64 20 3d 20 73 74 72 6c 65 6e  .  nRid = strlen
2410: 28 7a 52 69 64 29 3b 0a 20 20 66 6f 72 28 6e 4e  (zRid);.  for(nN
2420: 61 6d 65 3d 73 74 72 6c 65 6e 28 7a 4e 61 6d 65  ame=strlen(zName
2430: 29 2d 31 3b 20 6e 4e 61 6d 65 3e 35 3b 20 6e 4e  )-1; nName>5; nN
2440: 61 6d 65 2d 2d 29 7b 0a 20 20 20 20 69 66 28 20  ame--){.    if( 
2450: 7a 4e 61 6d 65 5b 6e 4e 61 6d 65 5d 3d 3d 27 2e  zName[nName]=='.
2460: 27 20 29 7b 0a 20 20 20 20 20 20 7a 4e 61 6d 65  ' ){.      zName
2470: 5b 6e 4e 61 6d 65 5d 20 3d 20 30 3b 0a 20 20 20  [nName] = 0;.   
2480: 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 7d 0a     break;.    }.
2490: 20 20 7d 0a 20 20 72 69 64 20 3d 20 6e 61 6d 65    }.  rid = name
24a0: 5f 74 6f 5f 72 69 64 28 6e 52 69 64 3f 7a 52 69  _to_rid(nRid?zRi
24b0: 64 3a 7a 4e 61 6d 65 29 3b 0a 20 20 69 66 28 20  d:zName);.  if( 
24c0: 72 69 64 3d 3d 30 20 29 7b 0a 20 20 20 20 40 20  rid==0 ){.    @ 
24d0: 4e 6f 74 20 66 6f 75 6e 64 0a 20 20 20 20 72 65  Not found.    re
24e0: 74 75 72 6e 3b 0a 20 20 7d 0a 20 20 69 66 28 20  turn;.  }.  if( 
24f0: 6e 52 69 64 3d 3d 30 20 26 26 20 6e 4e 61 6d 65  nRid==0 && nName
2500: 3e 31 30 20 29 20 7a 4e 61 6d 65 5b 31 30 5d 20  >10 ) zName[10] 
2510: 3d 20 30 3b 0a 20 20 7a 69 70 5f 6f 66 5f 62 61  = 0;.  zip_of_ba
2520: 73 65 6c 69 6e 65 28 72 69 64 2c 20 26 7a 69 70  seline(rid, &zip
2530: 2c 20 7a 4e 61 6d 65 29 3b 0a 20 20 66 72 65 65  , zName);.  free
2540: 28 20 7a 4e 61 6d 65 20 29 3b 0a 20 20 66 72 65  ( zName );.  fre
2550: 65 28 20 7a 52 69 64 20 29 3b 0a 20 20 63 67 69  e( zRid );.  cgi
2560: 5f 73 65 74 5f 63 6f 6e 74 65 6e 74 28 26 7a 69  _set_content(&zi
2570: 70 29 3b 0a 20 20 63 67 69 5f 73 65 74 5f 63 6f  p);.  cgi_set_co
2580: 6e 74 65 6e 74 5f 74 79 70 65 28 22 61 70 70 6c  ntent_type("appl
2590: 69 63 61 74 69 6f 6e 2f 7a 69 70 22 29 3b 0a 7d  ication/zip");.}
25a0: 0a                                               .