Hex Artifact Content
Not logged in

Artifact fa39badf00bdfc6623bdd19226b365aca10b3eae:

File src/cgi.c part of check-in [677aa71bca] - The g.zExtra parameter is now always available as P("name"). This means the /wiki/xyz and /wiki?name=xyz are equivalent URLs. by drh on 2007-10-12 22:56:18.

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 36 20 44 2e 20 52 69 63 68  (c) 2006 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 43 20 66 75 6e 63   contains C func
0380: 74 69 6f 6e 73 20 61 6e 64 20 70 72 6f 63 65 64  tions and proced
0390: 75 72 65 73 20 74 68 61 74 20 70 72 6f 76 69 64  ures that provid
03a0: 65 20 75 73 65 66 75 6c 0a 2a 2a 20 73 65 72 76  e useful.** serv
03b0: 69 63 65 73 20 74 6f 20 43 47 49 20 70 72 6f 67  ices to CGI prog
03c0: 72 61 6d 73 2e 20 20 54 68 65 72 65 20 61 72 65  rams.  There are
03d0: 20 70 72 6f 63 65 64 75 72 65 73 20 66 6f 72 20   procedures for 
03e0: 70 61 72 73 69 6e 67 20 61 6e 64 0a 2a 2a 20 64  parsing and.** d
03f0: 69 73 70 65 6e 73 69 6e 67 20 51 55 45 52 59 5f  ispensing QUERY_
0400: 53 54 52 49 4e 47 20 70 61 72 61 6d 65 74 65 72  STRING parameter
0410: 73 20 61 6e 64 20 63 6f 6f 6b 69 65 73 2c 20 74  s and cookies, t
0420: 68 65 20 22 6d 70 72 69 6e 74 66 28 29 22 0a 2a  he "mprintf()".*
0430: 2a 20 66 6f 72 6d 61 74 74 69 6e 67 20 66 75 6e  * formatting fun
0440: 63 74 69 6f 6e 20 61 6e 64 20 69 74 73 20 63 6f  ction and its co
0450: 75 73 69 6e 73 2c 20 61 6e 64 20 72 6f 75 74 69  usins, and routi
0460: 6e 65 73 20 74 6f 20 65 6e 63 6f 64 65 20 61 6e  nes to encode an
0470: 64 0a 2a 2a 20 64 65 63 6f 64 65 20 73 74 72 69  d.** decode stri
0480: 6e 67 73 20 69 6e 20 48 54 4d 4c 20 6f 72 20 48  ngs in HTML or H
0490: 54 54 50 2e 0a 2a 2f 0a 23 69 6e 63 6c 75 64 65  TTP..*/.#include
04a0: 20 22 63 6f 6e 66 69 67 2e 68 22 0a 23 69 66 64   "config.h".#ifd
04b0: 65 66 20 5f 5f 4d 49 4e 47 57 33 32 5f 5f 0a 23  ef __MINGW32__.#
04c0: 20 20 69 6e 63 6c 75 64 65 20 3c 77 69 6e 64 6f    include <windo
04d0: 77 73 2e 68 3e 20 20 20 20 20 20 20 20 20 20 20  ws.h>           
04e0: 2f 2a 20 66 6f 72 20 53 6c 65 65 70 20 6f 6e 63  /* for Sleep onc
04f0: 65 20 73 65 72 76 65 72 20 77 6f 72 6b 73 20 61  e server works a
0500: 67 61 69 6e 20 2a 2f 0a 23 20 20 69 6e 63 6c 75  gain */.#  inclu
0510: 64 65 20 3c 77 69 6e 73 6f 63 6b 32 2e 68 3e 20  de <winsock2.h> 
0520: 20 20 20 20 20 20 20 20 20 2f 2a 20 73 6f 63 6b           /* sock
0530: 65 74 20 6f 70 65 72 61 74 69 6f 6e 73 20 2a 2f  et operations */
0540: 0a 23 20 20 64 65 66 69 6e 65 20 73 6c 65 65 70  .#  define sleep
0550: 20 53 6c 65 65 70 20 20 20 20 20 20 20 20 20 20   Sleep          
0560: 20 20 2f 2a 20 77 69 6e 64 6f 77 73 20 64 6f 65    /* windows doe
0570: 73 20 6e 6f 74 20 68 61 76 65 20 73 6c 65 65 70  s not have sleep
0580: 2c 20 62 75 74 20 53 6c 65 65 70 20 2a 2f 0a 23  , but Sleep */.#
0590: 20 20 69 6e 63 6c 75 64 65 20 3c 77 73 32 74 63    include <ws2tc
05a0: 70 69 70 2e 68 3e 20 20 20 20 20 20 20 20 20 20  pip.h>          
05b0: 0a 23 65 6c 73 65 0a 23 20 20 69 6e 63 6c 75 64  .#else.#  includ
05c0: 65 20 3c 73 79 73 2f 73 6f 63 6b 65 74 2e 68 3e  e <sys/socket.h>
05d0: 0a 23 20 20 69 6e 63 6c 75 64 65 20 3c 6e 65 74  .#  include <net
05e0: 69 6e 65 74 2f 69 6e 2e 68 3e 0a 23 20 20 69 6e  inet/in.h>.#  in
05f0: 63 6c 75 64 65 20 3c 61 72 70 61 2f 69 6e 65 74  clude <arpa/inet
0600: 2e 68 3e 0a 23 20 20 69 6e 63 6c 75 64 65 20 3c  .h>.#  include <
0610: 73 79 73 2f 74 69 6d 65 73 2e 68 3e 0a 23 20 20  sys/times.h>.#  
0620: 69 6e 63 6c 75 64 65 20 3c 73 79 73 2f 74 69 6d  include <sys/tim
0630: 65 2e 68 3e 0a 23 20 20 69 6e 63 6c 75 64 65 20  e.h>.#  include 
0640: 3c 73 79 73 2f 77 61 69 74 2e 68 3e 0a 23 20 20  <sys/wait.h>.#  
0650: 69 6e 63 6c 75 64 65 20 3c 73 79 73 2f 73 65 6c  include <sys/sel
0660: 65 63 74 2e 68 3e 0a 23 65 6e 64 69 66 0a 23 69  ect.h>.#endif.#i
0670: 6e 63 6c 75 64 65 20 3c 74 69 6d 65 2e 68 3e 0a  nclude <time.h>.
0680: 23 69 6e 63 6c 75 64 65 20 3c 73 74 64 69 6f 2e  #include <stdio.
0690: 68 3e 0a 23 69 6e 63 6c 75 64 65 20 3c 73 74 64  h>.#include <std
06a0: 6c 69 62 2e 68 3e 0a 23 69 6e 63 6c 75 64 65 20  lib.h>.#include 
06b0: 3c 75 6e 69 73 74 64 2e 68 3e 0a 23 69 6e 63 6c  <unistd.h>.#incl
06c0: 75 64 65 20 22 63 67 69 2e 68 22 0a 0a 23 69 66  ude "cgi.h"..#if
06d0: 20 49 4e 54 45 52 46 41 43 45 0a 2f 2a 0a 2a 2a   INTERFACE./*.**
06e0: 20 53 68 6f 72 74 63 75 74 73 20 66 6f 72 20 63   Shortcuts for c
06f0: 67 69 5f 70 61 72 61 6d 65 74 65 72 2e 20 20 50  gi_parameter.  P
0700: 28 22 78 22 29 20 72 65 74 75 72 6e 73 20 74 68  ("x") returns th
0710: 65 20 76 61 6c 75 65 20 6f 66 20 71 75 65 72 79  e value of query
0720: 20 70 61 72 61 6d 65 74 65 72 0a 2a 2a 20 6f 72   parameter.** or
0730: 20 63 6f 6f 6b 69 65 20 22 78 22 2c 20 6f 72 20   cookie "x", or 
0740: 4e 55 4c 4c 20 69 66 20 74 68 65 72 65 20 69 73  NULL if there is
0750: 20 6e 6f 20 73 75 63 68 20 70 61 72 61 6d 65 74   no such paramet
0760: 65 72 20 6f 72 20 63 6f 6f 6b 69 65 2e 20 20 50  er or cookie.  P
0770: 44 28 22 78 22 2c 22 79 22 29 0a 2a 2a 20 64 6f  D("x","y").** do
0780: 65 73 20 74 68 65 20 73 61 6d 65 20 65 78 63 65  es the same exce
0790: 70 74 20 22 79 22 20 69 73 20 72 65 74 75 72 6e  pt "y" is return
07a0: 65 64 20 69 6e 20 70 6c 61 63 65 20 6f 66 20 4e  ed in place of N
07b0: 55 4c 4c 20 69 66 20 74 68 65 72 65 20 69 73 20  ULL if there is 
07c0: 6e 6f 74 20 6d 61 74 63 68 2e 0a 2a 2f 0a 23 64  not match..*/.#d
07d0: 65 66 69 6e 65 20 50 28 78 29 20 20 20 20 20 20  efine P(x)      
07e0: 20 20 63 67 69 5f 70 61 72 61 6d 65 74 65 72 28    cgi_parameter(
07f0: 28 78 29 2c 30 29 0a 23 64 65 66 69 6e 65 20 50  (x),0).#define P
0800: 44 28 78 2c 79 29 20 20 20 20 20 63 67 69 5f 70  D(x,y)     cgi_p
0810: 61 72 61 6d 65 74 65 72 28 28 78 29 2c 28 79 29  arameter((x),(y)
0820: 29 0a 23 64 65 66 69 6e 65 20 51 50 28 78 29 20  ).#define QP(x) 
0830: 20 20 20 20 20 20 71 75 6f 74 61 62 6c 65 5f 73        quotable_s
0840: 74 72 69 6e 67 28 63 67 69 5f 70 61 72 61 6d 65  tring(cgi_parame
0850: 74 65 72 28 28 78 29 2c 30 29 29 0a 23 64 65 66  ter((x),0)).#def
0860: 69 6e 65 20 51 50 44 28 78 2c 79 29 20 20 20 20  ine QPD(x,y)    
0870: 71 75 6f 74 61 62 6c 65 5f 73 74 72 69 6e 67 28  quotable_string(
0880: 63 67 69 5f 70 61 72 61 6d 65 74 65 72 28 28 78  cgi_parameter((x
0890: 29 2c 28 79 29 29 29 0a 0a 23 65 6e 64 69 66 20  ),(y)))..#endif 
08a0: 2f 2a 20 49 4e 54 45 52 46 41 43 45 20 2a 2f 0a  /* INTERFACE */.
08b0: 0a 2f 2a 0a 2a 2a 20 50 72 6f 76 69 64 65 20 61  ./*.** Provide a
08c0: 20 72 65 6c 69 61 62 6c 65 20 69 6d 70 6c 65 6d   reliable implem
08d0: 65 6e 74 61 74 69 6f 6e 20 6f 66 20 61 20 63 61  entation of a ca
08e0: 73 65 6c 65 73 73 20 73 74 72 69 6e 67 20 63 6f  seless string co
08f0: 6d 70 61 72 69 73 6f 6e 0a 2a 2a 20 66 75 6e 63  mparison.** func
0900: 74 69 6f 6e 2e 0a 2a 2f 0a 23 64 65 66 69 6e 65  tion..*/.#define
0910: 20 73 74 72 69 63 6d 70 20 73 71 6c 69 74 65 33   stricmp sqlite3
0920: 53 74 72 49 43 6d 70 0a 65 78 74 65 72 6e 20 69  StrICmp.extern i
0930: 6e 74 20 73 71 6c 69 74 65 33 53 74 72 49 43 6d  nt sqlite3StrICm
0940: 70 28 63 6f 6e 73 74 20 63 68 61 72 2a 2c 20 63  p(const char*, c
0950: 6f 6e 73 74 20 63 68 61 72 2a 29 3b 0a 0a 2f 2a  onst char*);../*
0960: 0a 2a 2a 20 54 68 65 20 62 6f 64 79 20 6f 66 20  .** The body of 
0970: 74 68 65 20 48 54 54 50 20 72 65 70 6c 79 20 74  the HTTP reply t
0980: 65 78 74 20 69 73 20 73 74 6f 72 65 64 20 68 65  ext is stored he
0990: 72 65 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 42 6c  re..*/.static Bl
09a0: 6f 62 20 63 67 69 43 6f 6e 74 65 6e 74 20 3d 20  ob cgiContent = 
09b0: 42 4c 4f 42 5f 49 4e 49 54 49 41 4c 49 5a 45 52  BLOB_INITIALIZER
09c0: 3b 0a 0a 2f 2a 0a 2a 2a 20 41 70 70 65 6e 64 20  ;../*.** Append 
09d0: 72 65 70 6c 79 20 63 6f 6e 74 65 6e 74 20 74 6f  reply content to
09e0: 20 77 68 61 74 20 61 6c 72 65 61 64 79 20 65 78   what already ex
09f0: 69 73 74 73 2e 0a 2a 2f 0a 76 6f 69 64 20 63 67  ists..*/.void cg
0a00: 69 5f 61 70 70 65 6e 64 5f 63 6f 6e 74 65 6e 74  i_append_content
0a10: 28 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 44 61  (const char *zDa
0a20: 74 61 2c 20 69 6e 74 20 6e 41 6d 74 29 7b 0a 20  ta, int nAmt){. 
0a30: 20 62 6c 6f 62 5f 61 70 70 65 6e 64 28 26 63 67   blob_append(&cg
0a40: 69 43 6f 6e 74 65 6e 74 2c 20 7a 44 61 74 61 2c  iContent, zData,
0a50: 20 6e 41 6d 74 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a   nAmt);.}../*.**
0a60: 20 52 65 73 65 74 20 74 68 65 20 48 54 54 50 20   Reset the HTTP 
0a70: 72 65 70 6c 79 20 74 65 78 74 20 74 6f 20 62 65  reply text to be
0a80: 20 61 6e 20 65 6d 70 74 79 20 73 74 72 69 6e 67   an empty string
0a90: 2e 0a 2a 2f 0a 76 6f 69 64 20 63 67 69 5f 72 65  ..*/.void cgi_re
0aa0: 73 65 74 5f 63 6f 6e 74 65 6e 74 28 76 6f 69 64  set_content(void
0ab0: 29 7b 0a 20 20 62 6c 6f 62 5f 72 65 73 65 74 28  ){.  blob_reset(
0ac0: 26 63 67 69 43 6f 6e 74 65 6e 74 29 3b 0a 7d 0a  &cgiContent);.}.
0ad0: 0a 2f 2a 0a 2a 2a 20 52 65 74 75 72 6e 20 61 20  ./*.** Return a 
0ae0: 70 6f 69 6e 74 65 72 20 74 6f 20 74 68 65 20 43  pointer to the C
0af0: 47 49 20 6f 75 74 70 75 74 20 62 6c 6f 62 2e 0a  GI output blob..
0b00: 2a 2f 0a 42 6c 6f 62 20 2a 63 67 69 5f 6f 75 74  */.Blob *cgi_out
0b10: 70 75 74 5f 62 6c 6f 62 28 76 6f 69 64 29 7b 0a  put_blob(void){.
0b20: 20 20 72 65 74 75 72 6e 20 26 63 67 69 43 6f 6e    return &cgiCon
0b30: 74 65 6e 74 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 52  tent;.}../*.** R
0b40: 65 74 75 72 6e 20 61 20 70 6f 69 6e 74 65 72 20  eturn a pointer 
0b50: 74 6f 20 74 68 65 20 48 54 54 50 20 72 65 70 6c  to the HTTP repl
0b60: 79 20 74 65 78 74 2e 0a 2a 2f 0a 63 68 61 72 20  y text..*/.char 
0b70: 2a 63 67 69 5f 65 78 74 72 61 63 74 5f 63 6f 6e  *cgi_extract_con
0b80: 74 65 6e 74 28 69 6e 74 20 2a 70 6e 41 6d 74 29  tent(int *pnAmt)
0b90: 7b 0a 20 20 72 65 74 75 72 6e 20 62 6c 6f 62 5f  {.  return blob_
0ba0: 62 75 66 66 65 72 28 26 63 67 69 43 6f 6e 74 65  buffer(&cgiConte
0bb0: 6e 74 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 41 64  nt);.}../*.** Ad
0bc0: 64 69 74 69 6f 6e 61 6c 20 69 6e 66 6f 72 6d 61  ditional informa
0bd0: 74 69 6f 6e 20 75 73 65 64 20 74 6f 20 66 6f 72  tion used to for
0be0: 6d 20 74 68 65 20 48 54 54 50 20 72 65 70 6c 79  m the HTTP reply
0bf0: 0a 2a 2f 0a 73 74 61 74 69 63 20 63 68 61 72 20  .*/.static char 
0c00: 2a 7a 43 6f 6e 74 65 6e 74 54 79 70 65 20 3d 20  *zContentType = 
0c10: 22 74 65 78 74 2f 68 74 6d 6c 22 3b 20 20 20 20  "text/html";    
0c20: 20 2f 2a 20 43 6f 6e 74 65 6e 74 20 74 79 70 65   /* Content type
0c30: 20 6f 66 20 74 68 65 20 72 65 70 6c 79 20 2a 2f   of the reply */
0c40: 0a 73 74 61 74 69 63 20 63 68 61 72 20 2a 7a 52  .static char *zR
0c50: 65 70 6c 79 53 74 61 74 75 73 20 3d 20 22 4f 4b  eplyStatus = "OK
0c60: 22 3b 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a  ";            /*
0c70: 20 52 65 70 6c 79 20 73 74 61 74 75 73 20 64 65   Reply status de
0c80: 73 63 72 69 70 74 69 6f 6e 20 2a 2f 0a 73 74 61  scription */.sta
0c90: 74 69 63 20 69 6e 74 20 69 52 65 70 6c 79 53 74  tic int iReplySt
0ca0: 61 74 75 73 20 3d 20 32 30 30 3b 20 20 20 20 20  atus = 200;     
0cb0: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 52 65 70            /* Rep
0cc0: 6c 79 20 73 74 61 74 75 73 20 63 6f 64 65 20 2a  ly status code *
0cd0: 2f 0a 73 74 61 74 69 63 20 42 6c 6f 62 20 65 78  /.static Blob ex
0ce0: 74 72 61 48 65 61 64 65 72 20 3d 20 42 4c 4f 42  traHeader = BLOB
0cf0: 5f 49 4e 49 54 49 41 4c 49 5a 45 52 3b 20 20 2f  _INITIALIZER;  /
0d00: 2a 20 45 78 74 72 61 20 68 65 61 64 65 72 20 74  * Extra header t
0d10: 65 78 74 20 2a 2f 0a 73 74 61 74 69 63 20 69 6e  ext */.static in
0d20: 74 20 66 75 6c 6c 48 74 74 70 52 65 70 6c 79 20  t fullHttpReply 
0d30: 3d 20 30 3b 20 20 20 20 20 20 2f 2a 20 54 72 75  = 0;      /* Tru
0d40: 65 20 66 6f 72 20 61 20 66 75 6c 6c 2d 62 6c 6f  e for a full-blo
0d50: 77 6e 20 48 54 54 50 20 68 65 61 64 65 72 20 2a  wn HTTP header *
0d60: 2f 0a 0a 2f 2a 0a 2a 2a 20 53 65 74 20 74 68 65  /../*.** Set the
0d70: 20 72 65 70 6c 79 20 63 6f 6e 74 65 6e 74 20 74   reply content t
0d80: 79 70 65 0a 2a 2f 0a 76 6f 69 64 20 63 67 69 5f  ype.*/.void cgi_
0d90: 73 65 74 5f 63 6f 6e 74 65 6e 74 5f 74 79 70 65  set_content_type
0da0: 28 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 54 79  (const char *zTy
0db0: 70 65 29 7b 0a 20 20 7a 43 6f 6e 74 65 6e 74 54  pe){.  zContentT
0dc0: 79 70 65 20 3d 20 6d 70 72 69 6e 74 66 28 22 25  ype = mprintf("%
0dd0: 73 22 2c 20 7a 54 79 70 65 29 3b 0a 7d 0a 0a 2f  s", zType);.}../
0de0: 2a 0a 2a 2a 20 53 65 74 20 74 68 65 20 72 65 70  *.** Set the rep
0df0: 6c 79 20 63 6f 6e 74 65 6e 74 20 74 6f 20 74 68  ly content to th
0e00: 65 20 73 70 65 63 69 66 69 65 64 20 42 4c 4f 42  e specified BLOB
0e10: 2e 0a 2a 2f 0a 76 6f 69 64 20 63 67 69 5f 73 65  ..*/.void cgi_se
0e20: 74 5f 63 6f 6e 74 65 6e 74 28 42 6c 6f 62 20 2a  t_content(Blob *
0e30: 70 4e 65 77 43 6f 6e 74 65 6e 74 29 7b 0a 20 20  pNewContent){.  
0e40: 62 6c 6f 62 5f 72 65 73 65 74 28 26 63 67 69 43  blob_reset(&cgiC
0e50: 6f 6e 74 65 6e 74 29 3b 0a 20 20 63 67 69 43 6f  ontent);.  cgiCo
0e60: 6e 74 65 6e 74 20 3d 20 2a 70 4e 65 77 43 6f 6e  ntent = *pNewCon
0e70: 74 65 6e 74 3b 0a 20 20 62 6c 6f 62 5f 7a 65 72  tent;.  blob_zer
0e80: 6f 28 70 4e 65 77 43 6f 6e 74 65 6e 74 29 3b 0a  o(pNewContent);.
0e90: 7d 0a 0a 2f 2a 0a 2a 2a 20 53 65 74 20 74 68 65  }../*.** Set the
0ea0: 20 72 65 70 6c 79 20 73 74 61 74 75 73 20 63 6f   reply status co
0eb0: 64 65 0a 2a 2f 0a 76 6f 69 64 20 63 67 69 5f 73  de.*/.void cgi_s
0ec0: 65 74 5f 73 74 61 74 75 73 28 69 6e 74 20 69 53  et_status(int iS
0ed0: 74 61 74 2c 20 63 6f 6e 73 74 20 63 68 61 72 20  tat, const char 
0ee0: 2a 7a 53 74 61 74 29 7b 0a 20 20 7a 52 65 70 6c  *zStat){.  zRepl
0ef0: 79 53 74 61 74 75 73 20 3d 20 6d 70 72 69 6e 74  yStatus = mprint
0f00: 66 28 22 25 73 22 2c 20 7a 53 74 61 74 29 3b 0a  f("%s", zStat);.
0f10: 20 20 69 52 65 70 6c 79 53 74 61 74 75 73 20 3d    iReplyStatus =
0f20: 20 69 53 74 61 74 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a   iStat;.}../*.**
0f30: 20 41 70 70 65 6e 64 20 74 65 78 74 20 74 6f 20   Append text to 
0f40: 74 68 65 20 68 65 61 64 65 72 20 6f 66 20 61 6e  the header of an
0f50: 20 48 54 54 50 20 72 65 70 6c 79 0a 2a 2f 0a 76   HTTP reply.*/.v
0f60: 6f 69 64 20 63 67 69 5f 61 70 70 65 6e 64 5f 68  oid cgi_append_h
0f70: 65 61 64 65 72 28 63 6f 6e 73 74 20 63 68 61 72  eader(const char
0f80: 20 2a 7a 4c 69 6e 65 29 7b 0a 20 20 62 6c 6f 62   *zLine){.  blob
0f90: 5f 61 70 70 65 6e 64 28 26 65 78 74 72 61 48 65  _append(&extraHe
0fa0: 61 64 65 72 2c 20 7a 4c 69 6e 65 2c 20 2d 31 29  ader, zLine, -1)
0fb0: 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 53 65 74 20 61  ;.}../*.** Set a
0fc0: 20 63 6f 6f 6b 69 65 2e 0a 2a 2a 0a 2a 2a 20 5a   cookie..**.** Z
0fd0: 65 72 6f 20 6c 69 66 65 74 69 6d 65 20 69 6d 70  ero lifetime imp
0fe0: 6c 69 65 73 20 61 20 73 65 73 73 69 6f 6e 20 63  lies a session c
0ff0: 6f 6f 6b 69 65 2e 0a 2a 2f 0a 76 6f 69 64 20 63  ookie..*/.void c
1000: 67 69 5f 73 65 74 5f 63 6f 6f 6b 69 65 28 0a 20  gi_set_cookie(. 
1010: 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 4e 61   const char *zNa
1020: 6d 65 2c 20 20 20 20 2f 2a 20 4e 61 6d 65 20 6f  me,    /* Name o
1030: 66 20 74 68 65 20 63 6f 6f 6b 69 65 20 2a 2f 0a  f the cookie */.
1040: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 56    const char *zV
1050: 61 6c 75 65 2c 20 20 20 2f 2a 20 56 61 6c 75 65  alue,   /* Value
1060: 20 6f 66 20 74 68 65 20 63 6f 6f 6b 69 65 2e 20   of the cookie. 
1070: 20 41 75 74 6f 6d 61 74 69 63 61 6c 6c 79 20 65   Automatically e
1080: 73 63 61 70 65 64 20 2a 2f 0a 20 20 63 6f 6e 73  scaped */.  cons
1090: 74 20 63 68 61 72 20 2a 7a 50 61 74 68 2c 20 20  t char *zPath,  
10a0: 20 20 2f 2a 20 50 61 74 68 20 63 6f 6f 6b 69 65    /* Path cookie
10b0: 20 61 70 70 6c 69 65 73 20 74 6f 2e 20 20 4e 55   applies to.  NU
10c0: 4c 4c 20 6d 65 61 6e 73 20 22 2f 22 20 2a 2f 0a  LL means "/" */.
10d0: 20 20 69 6e 74 20 6c 69 66 65 74 69 6d 65 20 20    int lifetime  
10e0: 20 20 20 20 20 20 20 20 2f 2a 20 45 78 70 69 72          /* Expir
10f0: 61 74 69 6f 6e 20 6f 66 20 74 68 65 20 63 6f 6f  ation of the coo
1100: 6b 69 65 20 69 6e 20 73 65 63 6f 6e 64 73 20 66  kie in seconds f
1110: 72 6f 6d 20 6e 6f 77 20 2a 2f 0a 29 7b 0a 20 20  rom now */.){.  
1120: 69 66 28 20 7a 50 61 74 68 3d 3d 30 20 29 20 7a  if( zPath==0 ) z
1130: 50 61 74 68 20 3d 20 22 2f 22 3b 0a 20 20 69 66  Path = "/";.  if
1140: 28 20 6c 69 66 65 74 69 6d 65 3e 30 20 29 7b 0a  ( lifetime>0 ){.
1150: 20 20 20 20 6c 69 66 65 74 69 6d 65 20 2b 3d 20      lifetime += 
1160: 28 69 6e 74 29 74 69 6d 65 28 30 29 3b 0a 20 20  (int)time(0);.  
1170: 20 20 62 6c 6f 62 5f 61 70 70 65 6e 64 66 28 26    blob_appendf(&
1180: 65 78 74 72 61 48 65 61 64 65 72 2c 0a 20 20 20  extraHeader,.   
1190: 20 20 20 20 22 53 65 74 2d 43 6f 6f 6b 69 65 3a      "Set-Cookie:
11a0: 20 25 73 3d 25 74 3b 20 50 61 74 68 3d 25 73 3b   %s=%t; Path=%s;
11b0: 20 65 78 70 69 72 65 73 3d 25 73 3b 20 56 65 72   expires=%s; Ver
11c0: 73 69 6f 6e 3d 31 5c 72 5c 6e 22 2c 0a 20 20 20  sion=1\r\n",.   
11d0: 20 20 20 20 20 7a 4e 61 6d 65 2c 20 7a 56 61 6c       zName, zVal
11e0: 75 65 2c 20 7a 50 61 74 68 2c 20 63 67 69 5f 72  ue, zPath, cgi_r
11f0: 66 63 38 32 32 5f 64 61 74 65 73 74 61 6d 70 28  fc822_datestamp(
1200: 6c 69 66 65 74 69 6d 65 29 29 3b 0a 20 20 7d 65  lifetime));.  }e
1210: 6c 73 65 7b 0a 20 20 20 20 62 6c 6f 62 5f 61 70  lse{.    blob_ap
1220: 70 65 6e 64 66 28 26 65 78 74 72 61 48 65 61 64  pendf(&extraHead
1230: 65 72 2c 0a 20 20 20 20 20 20 20 22 53 65 74 2d  er,.       "Set-
1240: 43 6f 6f 6b 69 65 3a 20 25 73 3d 25 74 3b 20 50  Cookie: %s=%t; P
1250: 61 74 68 3d 25 73 3b 20 56 65 72 73 69 6f 6e 3d  ath=%s; Version=
1260: 31 5c 72 5c 6e 22 2c 0a 20 20 20 20 20 20 20 7a  1\r\n",.       z
1270: 4e 61 6d 65 2c 20 7a 56 61 6c 75 65 2c 20 7a 50  Name, zValue, zP
1280: 61 74 68 29 3b 0a 20 20 7d 0a 7d 0a 0a 23 69 66  ath);.  }.}..#if
1290: 20 30 0a 2f 2a 0a 2a 2a 20 41 64 64 20 61 6e 20   0./*.** Add an 
12a0: 45 54 61 67 20 68 65 61 64 65 72 20 6c 69 6e 65  ETag header line
12b0: 0a 2a 2f 0a 73 74 61 74 69 63 20 63 68 61 72 20  .*/.static char 
12c0: 2a 63 67 69 5f 61 64 64 5f 65 74 61 67 28 63 68  *cgi_add_etag(ch
12d0: 61 72 20 2a 7a 54 78 74 2c 20 69 6e 74 20 6e 4c  ar *zTxt, int nL
12e0: 65 6e 29 7b 0a 20 20 4d 44 35 43 6f 6e 74 65 78  en){.  MD5Contex
12f0: 74 20 63 74 78 3b 0a 20 20 75 6e 73 69 67 6e 65  t ctx;.  unsigne
1300: 64 20 63 68 61 72 20 64 69 67 65 73 74 5b 31 36  d char digest[16
1310: 5d 3b 0a 20 20 69 6e 74 20 69 2c 20 6a 3b 0a 20  ];.  int i, j;. 
1320: 20 63 68 61 72 20 7a 45 54 61 67 5b 36 34 5d 3b   char zETag[64];
1330: 0a 0a 20 20 4d 44 35 49 6e 69 74 28 26 63 74 78  ..  MD5Init(&ctx
1340: 29 3b 0a 20 20 4d 44 35 55 70 64 61 74 65 28 26  );.  MD5Update(&
1350: 63 74 78 2c 7a 54 78 74 2c 6e 4c 65 6e 29 3b 0a  ctx,zTxt,nLen);.
1360: 20 20 4d 44 35 46 69 6e 61 6c 28 64 69 67 65 73    MD5Final(diges
1370: 74 2c 26 63 74 78 29 3b 0a 20 20 66 6f 72 28 6a  t,&ctx);.  for(j
1380: 3d 69 3d 30 3b 20 69 3c 31 36 3b 20 69 2b 2b 2c  =i=0; i<16; i++,
1390: 6a 2b 3d 32 29 7b 0a 20 20 20 20 62 70 72 69 6e  j+=2){.    bprin
13a0: 74 66 28 26 7a 45 54 61 67 5b 6a 5d 2c 73 69 7a  tf(&zETag[j],siz
13b0: 65 6f 66 28 7a 45 54 61 67 29 2d 6a 2c 22 25 30  eof(zETag)-j,"%0
13c0: 32 78 22 2c 28 69 6e 74 29 64 69 67 65 73 74 5b  2x",(int)digest[
13d0: 69 5d 29 3b 0a 20 20 7d 0a 20 20 62 6c 6f 62 5f  i]);.  }.  blob_
13e0: 61 70 70 65 6e 64 66 28 26 65 78 74 72 61 48 65  appendf(&extraHe
13f0: 61 64 65 72 2c 20 22 45 54 61 67 3a 20 25 73 5c  ader, "ETag: %s\
1400: 72 5c 6e 22 2c 20 7a 45 54 61 67 29 3b 0a 20 20  r\n", zETag);.  
1410: 72 65 74 75 72 6e 20 73 74 72 64 75 70 28 7a 45  return strdup(zE
1420: 54 61 67 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 44  Tag);.}../*.** D
1430: 6f 20 73 6f 6d 65 20 63 61 63 68 65 20 63 6f 6e  o some cache con
1440: 74 72 6f 6c 20 73 74 75 66 66 2e 20 46 69 72 73  trol stuff. Firs
1450: 74 2c 20 77 65 20 67 65 6e 65 72 61 74 65 20 61  t, we generate a
1460: 6e 20 45 54 61 67 20 61 6e 64 20 69 6e 63 6c 75  n ETag and inclu
1470: 64 65 20 69 74 20 69 6e 0a 2a 2a 20 74 68 65 20  de it in.** the 
1480: 72 65 73 70 6f 6e 73 65 20 68 65 61 64 65 72 73  response headers
1490: 2e 20 53 65 63 6f 6e 64 2c 20 77 65 20 64 6f 20  . Second, we do 
14a0: 77 68 61 74 65 76 65 72 20 69 73 20 6e 65 63 65  whatever is nece
14b0: 73 73 61 72 79 20 74 6f 20 64 65 74 65 72 6d 69  ssary to determi
14c0: 6e 65 20 69 66 0a 2a 2a 20 74 68 65 20 72 65 71  ne if.** the req
14d0: 75 65 73 74 20 77 61 73 20 61 73 6b 69 6e 67 20  uest was asking 
14e0: 61 62 6f 75 74 20 63 61 63 68 69 6e 67 20 61 6e  about caching an
14f0: 64 20 77 68 65 74 68 65 72 20 77 65 20 6e 65 65  d whether we nee
1500: 64 20 74 6f 20 73 65 6e 64 20 62 61 63 6b 20 74  d to send back t
1510: 68 65 0a 2a 2a 20 72 65 73 70 6f 6e 73 65 20 62  he.** response b
1520: 6f 64 79 2e 20 49 66 20 77 65 20 73 68 6f 75 6c  ody. If we shoul
1530: 64 6e 27 74 20 73 65 6e 64 20 61 20 62 6f 64 79  dn't send a body
1540: 2c 20 72 65 74 75 72 6e 20 6e 6f 6e 2d 7a 65 72  , return non-zer
1550: 6f 2e 0a 2a 2a 0a 2a 2a 20 43 75 72 72 65 6e 74  o..**.** Current
1560: 6c 79 2c 20 77 65 20 6a 75 73 74 20 63 68 65 63  ly, we just chec
1570: 6b 20 74 68 65 20 45 54 61 67 20 61 67 61 69 6e  k the ETag again
1580: 73 74 20 61 6e 79 20 49 66 2d 4e 6f 6e 65 2d 4d  st any If-None-M
1590: 61 74 63 68 20 68 65 61 64 65 72 2e 0a 2a 2a 0a  atch header..**.
15a0: 2a 2a 20 46 49 58 4d 45 3a 20 49 6e 20 73 6f 6d  ** FIXME: In som
15b0: 65 20 63 61 73 65 73 20 28 61 74 74 61 63 68 6d  e cases (attachm
15c0: 65 6e 74 73 2c 20 66 69 6c 65 20 63 6f 6e 74 65  ents, file conte
15d0: 6e 74 73 29 20 77 65 20 63 6f 75 6c 64 20 63 68  nts) we could ch
15e0: 65 63 6b 0a 2a 2a 20 49 66 2d 4d 6f 64 69 66 69  eck.** If-Modifi
15f0: 65 64 2d 53 69 6e 63 65 20 68 65 61 64 65 72 73  ed-Since headers
1600: 20 61 6e 64 20 61 6c 77 61 79 73 20 69 6e 63 6c   and always incl
1610: 75 64 65 20 4c 61 73 74 2d 4d 6f 64 69 66 69 65  ude Last-Modifie
1620: 64 20 69 6e 20 72 65 73 70 6f 6e 73 65 73 2e 0a  d in responses..
1630: 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 63 68  */.static int ch
1640: 65 63 6b 5f 63 61 63 68 65 5f 63 6f 6e 74 72 6f  eck_cache_contro
1650: 6c 28 76 6f 69 64 29 7b 0a 20 20 2f 2a 20 46 49  l(void){.  /* FI
1660: 58 4d 45 3a 20 74 68 65 72 65 27 73 20 73 6f 6d  XME: there's som
1670: 65 20 67 6f 74 63 68 61 73 20 77 74 68 20 63 6f  e gotchas wth co
1680: 6f 6b 69 65 73 20 61 6e 64 20 73 6f 6d 65 20 68  okies and some h
1690: 65 61 64 65 72 73 2e 20 2a 2f 0a 20 20 63 68 61  eaders. */.  cha
16a0: 72 20 2a 7a 45 54 61 67 20 3d 20 63 67 69 5f 61  r *zETag = cgi_a
16b0: 64 64 5f 65 74 61 67 28 62 6c 6f 62 5f 62 75 66  dd_etag(blob_buf
16c0: 66 65 72 28 26 63 67 69 43 6f 6e 74 65 6e 74 29  fer(&cgiContent)
16d0: 2c 62 6c 6f 62 5f 73 69 7a 65 28 26 63 67 69 43  ,blob_size(&cgiC
16e0: 6f 6e 74 65 6e 74 29 29 3b 0a 20 20 63 68 61 72  ontent));.  char
16f0: 20 2a 7a 4d 61 74 63 68 20 3d 20 50 28 22 48 54   *zMatch = P("HT
1700: 54 50 5f 49 46 5f 4e 4f 4e 45 5f 4d 41 54 43 48  TP_IF_NONE_MATCH
1710: 22 29 3b 0a 0a 20 20 69 66 28 20 7a 45 54 61 67  ");..  if( zETag
1720: 21 3d 30 20 26 26 20 7a 4d 61 74 63 68 21 3d 30  !=0 && zMatch!=0
1730: 20 29 20 7b 0a 20 20 20 20 63 68 61 72 20 2a 7a   ) {.    char *z
1740: 42 75 66 20 3d 20 73 74 72 64 75 70 28 7a 4d 61  Buf = strdup(zMa
1750: 74 63 68 29 3b 0a 20 20 20 20 69 66 28 20 7a 42  tch);.    if( zB
1760: 75 66 21 3d 30 20 29 7b 0a 20 20 20 20 20 20 63  uf!=0 ){.      c
1770: 68 61 72 20 2a 7a 54 6f 6b 20 3d 20 30 3b 0a 20  har *zTok = 0;. 
1780: 20 20 20 20 20 63 68 61 72 20 2a 7a 50 6f 73 3b       char *zPos;
1790: 0a 20 20 20 20 20 20 66 6f 72 28 20 7a 54 6f 6b  .      for( zTok
17a0: 20 3d 20 73 74 72 74 6f 6b 5f 72 28 7a 42 75 66   = strtok_r(zBuf
17b0: 2c 20 22 2c 5c 22 22 2c 26 7a 50 6f 73 29 3b 0a  , ",\"",&zPos);.
17c0: 20 20 20 20 20 20 20 20 20 20 20 7a 54 6f 6b 20             zTok 
17d0: 26 26 20 73 74 72 63 61 73 65 63 6d 70 28 7a 54  && strcasecmp(zT
17e0: 6f 6b 2c 7a 45 54 61 67 29 3b 0a 20 20 20 20 20  ok,zETag);.     
17f0: 20 20 20 20 20 20 7a 54 6f 6b 20 3d 20 20 73 74        zTok =  st
1800: 72 74 6f 6b 5f 72 28 30 2c 20 22 2c 5c 22 22 2c  rtok_r(0, ",\"",
1810: 26 7a 50 6f 73 29 29 7b 7d 0a 20 20 20 20 20 20  &zPos)){}.      
1820: 66 72 65 65 28 7a 42 75 66 29 3b 0a 20 20 20 20  free(zBuf);.    
1830: 20 20 69 66 28 7a 54 6f 6b 29 20 72 65 74 75 72    if(zTok) retur
1840: 6e 20 31 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 20  n 1;.    }.  }. 
1850: 20 0a 20 20 72 65 74 75 72 6e 20 30 3b 0a 7d 0a   .  return 0;.}.
1860: 23 65 6e 64 69 66 0a 0a 2f 2a 0a 2a 2a 20 44 6f  #endif../*.** Do
1870: 20 61 20 6e 6f 72 6d 61 6c 20 48 54 54 50 20 72   a normal HTTP r
1880: 65 70 6c 79 0a 2a 2f 0a 76 6f 69 64 20 63 67 69  eply.*/.void cgi
1890: 5f 72 65 70 6c 79 28 76 6f 69 64 29 7b 0a 20 20  _reply(void){.  
18a0: 69 66 28 20 69 52 65 70 6c 79 53 74 61 74 75 73  if( iReplyStatus
18b0: 3c 3d 30 20 29 7b 0a 20 20 20 20 69 52 65 70 6c  <=0 ){.    iRepl
18c0: 79 53 74 61 74 75 73 20 3d 20 32 30 30 3b 0a 20  yStatus = 200;. 
18d0: 20 20 20 7a 52 65 70 6c 79 53 74 61 74 75 73 20     zReplyStatus 
18e0: 3d 20 22 4f 4b 22 3b 0a 20 20 7d 0a 0a 23 69 66  = "OK";.  }..#if
18f0: 20 30 0a 20 20 69 66 28 20 69 52 65 70 6c 79 53   0.  if( iReplyS
1900: 74 61 74 75 73 3d 3d 32 30 30 20 26 26 20 63 68  tatus==200 && ch
1910: 65 63 6b 5f 63 61 63 68 65 5f 63 6f 6e 74 72 6f  eck_cache_contro
1920: 6c 28 29 20 29 20 7b 0a 20 20 20 20 2f 2a 20 63  l() ) {.    /* c
1930: 68 61 6e 67 65 20 74 68 65 20 73 74 61 74 75 73  hange the status
1940: 20 74 6f 20 22 75 6e 63 68 61 6e 67 65 64 22 20   to "unchanged" 
1950: 61 6e 64 20 77 65 20 63 61 6e 20 73 6b 69 70 20  and we can skip 
1960: 73 65 6e 64 69 6e 67 20 74 68 65 0a 20 20 20 20  sending the.    
1970: 2a 2a 20 61 63 74 75 61 6c 20 72 65 73 70 6f 6e  ** actual respon
1980: 73 65 20 62 6f 64 79 2e 20 4f 62 76 69 6f 75 73  se body. Obvious
1990: 6c 79 20 77 65 20 6f 6e 6c 79 20 64 6f 20 74 68  ly we only do th
19a0: 69 73 20 77 68 65 6e 20 77 65 20 5f 68 61 76 65  is when we _have
19b0: 5f 20 61 0a 20 20 20 20 2a 2a 20 62 6f 64 79 20  _ a.    ** body 
19c0: 28 63 6f 64 65 20 32 30 30 29 2e 0a 20 20 20 20  (code 200)..    
19d0: 2a 2f 0a 20 20 20 20 69 52 65 70 6c 79 53 74 61  */.    iReplySta
19e0: 74 75 73 20 3d 20 33 30 34 3b 0a 20 20 20 20 7a  tus = 304;.    z
19f0: 52 65 70 6c 79 53 74 61 74 75 73 20 3d 20 22 4e  ReplyStatus = "N
1a00: 6f 74 20 4d 6f 64 69 66 69 65 64 22 3b 0a 20 20  ot Modified";.  
1a10: 7d 0a 23 65 6e 64 69 66 0a 0a 20 20 69 66 28 20  }.#endif..  if( 
1a20: 66 75 6c 6c 48 74 74 70 52 65 70 6c 79 20 29 7b  fullHttpReply ){
1a30: 0a 20 20 20 20 70 72 69 6e 74 66 28 22 48 54 54  .    printf("HTT
1a40: 50 2f 31 2e 30 20 25 64 20 25 73 5c 72 5c 6e 22  P/1.0 %d %s\r\n"
1a50: 2c 20 69 52 65 70 6c 79 53 74 61 74 75 73 2c 20  , iReplyStatus, 
1a60: 7a 52 65 70 6c 79 53 74 61 74 75 73 29 3b 0a 20  zReplyStatus);. 
1a70: 20 20 20 70 72 69 6e 74 66 28 22 44 61 74 65 3a     printf("Date:
1a80: 20 25 73 5c 72 5c 6e 22 2c 20 63 67 69 5f 72 66   %s\r\n", cgi_rf
1a90: 63 38 32 32 5f 64 61 74 65 73 74 61 6d 70 28 74  c822_datestamp(t
1aa0: 69 6d 65 28 30 29 29 29 3b 0a 20 20 20 20 70 72  ime(0)));.    pr
1ab0: 69 6e 74 66 28 22 43 6f 6e 6e 65 63 74 69 6f 6e  intf("Connection
1ac0: 3a 20 63 6c 6f 73 65 5c 72 5c 6e 22 29 3b 0a 20  : close\r\n");. 
1ad0: 20 7d 65 6c 73 65 7b 0a 20 20 20 20 70 72 69 6e   }else{.    prin
1ae0: 74 66 28 22 53 74 61 74 75 73 3a 20 25 64 20 25  tf("Status: %d %
1af0: 73 5c 72 5c 6e 22 2c 20 69 52 65 70 6c 79 53 74  s\r\n", iReplySt
1b00: 61 74 75 73 2c 20 7a 52 65 70 6c 79 53 74 61 74  atus, zReplyStat
1b10: 75 73 29 3b 0a 20 20 7d 0a 0a 20 20 69 66 28 20  us);.  }..  if( 
1b20: 62 6c 6f 62 5f 73 69 7a 65 28 26 65 78 74 72 61  blob_size(&extra
1b30: 48 65 61 64 65 72 29 3e 30 20 29 7b 0a 20 20 20  Header)>0 ){.   
1b40: 20 70 72 69 6e 74 66 28 22 25 73 22 2c 20 62 6c   printf("%s", bl
1b50: 6f 62 5f 62 75 66 66 65 72 28 26 65 78 74 72 61  ob_buffer(&extra
1b60: 48 65 61 64 65 72 29 29 3b 0a 20 20 7d 0a 0a 20  Header));.  }.. 
1b70: 20 69 66 28 20 67 2e 69 73 43 6f 6e 73 74 20 29   if( g.isConst )
1b80: 7b 0a 20 20 20 20 2f 2a 20 63 6f 6e 73 74 61 6e  {.    /* constan
1b90: 74 20 6d 65 61 6e 73 20 74 68 61 74 20 74 68 65  t means that the
1ba0: 20 69 6e 70 75 74 20 55 52 4c 20 77 69 6c 6c 20   input URL will 
1bb0: 5f 6e 65 76 65 72 5f 20 67 65 6e 65 72 61 74 65  _never_ generate
1bc0: 20 61 6e 79 74 68 69 6e 67 0a 20 20 20 20 2a 2a   anything.    **
1bd0: 20 65 6c 73 65 2e 20 49 6e 20 74 68 65 20 63 61   else. In the ca
1be0: 73 65 20 6f 66 20 61 74 74 61 63 68 6d 65 6e 74  se of attachment
1bf0: 73 2c 20 74 68 65 20 63 6f 6e 74 65 6e 74 73 20  s, the contents 
1c00: 77 6f 6e 27 74 20 63 68 61 6e 67 65 20 62 65 63  won't change bec
1c10: 61 75 73 65 0a 20 20 20 20 2a 2a 20 61 6e 20 61  ause.    ** an a
1c20: 74 74 65 6d 70 74 20 74 6f 20 63 68 61 6e 67 65  ttempt to change
1c30: 20 74 68 65 6d 20 67 65 6e 65 72 61 74 65 73 20   them generates 
1c40: 61 20 6e 65 77 20 61 74 74 61 63 68 6d 65 6e 74  a new attachment
1c50: 20 6e 75 6d 62 65 72 2e 20 49 6e 20 74 68 65 0a   number. In the.
1c60: 20 20 20 20 2a 2a 20 63 61 73 65 20 6f 66 20 6d      ** case of m
1c70: 6f 73 74 20 2f 67 65 74 66 69 6c 65 20 63 61 6c  ost /getfile cal
1c80: 6c 73 20 66 6f 72 20 73 70 65 63 69 66 69 63 20  ls for specific 
1c90: 76 65 72 73 69 6f 6e 73 2c 20 74 68 65 20 6f 6e  versions, the on
1ca0: 6c 79 20 77 61 79 20 74 68 65 0a 20 20 20 20 2a  ly way the.    *
1cb0: 2a 20 63 6f 6e 74 65 6e 74 20 63 68 61 6e 67 65  * content change
1cc0: 73 20 69 73 20 69 66 20 73 6f 6d 65 6f 6e 65 20  s is if someone 
1cd0: 62 72 65 61 6b 73 20 74 68 65 20 53 43 4d 2e 20  breaks the SCM. 
1ce0: 41 6e 64 20 69 66 20 74 68 61 74 20 68 61 70 70  And if that happ
1cf0: 65 6e 73 2c 20 61 0a 20 20 20 20 2a 2a 20 73 74  ens, a.    ** st
1d00: 61 6c 65 20 63 61 63 68 65 20 69 73 20 74 68 65  ale cache is the
1d10: 20 6c 65 61 73 74 20 6f 66 20 74 68 65 20 70 72   least of the pr
1d20: 6f 62 6c 65 6d 2e 20 53 6f 20 77 65 20 70 72 6f  oblem. So we pro
1d30: 76 69 64 65 20 61 6e 20 45 78 70 69 72 65 73 0a  vide an Expires.
1d40: 20 20 20 20 2a 2a 20 68 65 61 64 65 72 20 73 65      ** header se
1d50: 74 20 74 6f 20 61 20 72 65 61 73 6f 6e 61 62 6c  t to a reasonabl
1d60: 65 20 70 65 72 69 6f 64 20 28 64 65 66 61 75 6c  e period (defaul
1d70: 74 3a 20 6f 6e 65 20 77 65 65 6b 29 2e 0a 20 20  t: one week)..  
1d80: 20 20 2a 2f 0a 20 20 20 20 2f 2a 74 69 6d 65 5f    */.    /*time_
1d90: 74 20 65 78 70 69 72 65 73 20 3d 20 74 69 6d 65  t expires = time
1da0: 28 30 29 20 2b 20 61 74 6f 69 28 64 62 5f 63 6f  (0) + atoi(db_co
1db0: 6e 66 69 67 28 22 63 6f 6e 73 74 61 6e 74 5f 65  nfig("constant_e
1dc0: 78 70 69 72 65 73 22 2c 22 36 30 34 38 30 30 22  xpires","604800"
1dd0: 29 29 3b 2a 2f 0a 20 20 20 20 74 69 6d 65 5f 74  ));*/.    time_t
1de0: 20 65 78 70 69 72 65 73 20 3d 20 74 69 6d 65 28   expires = time(
1df0: 30 29 20 2b 20 36 30 34 38 30 30 3b 0a 20 20 20  0) + 604800;.   
1e00: 20 70 72 69 6e 74 66 28 20 22 45 78 70 69 72 65   printf( "Expire
1e10: 73 3a 20 25 73 5c 72 5c 6e 22 2c 20 63 67 69 5f  s: %s\r\n", cgi_
1e20: 72 66 63 38 32 32 5f 64 61 74 65 73 74 61 6d 70  rfc822_datestamp
1e30: 28 65 78 70 69 72 65 73 29 29 3b 0a 20 20 7d 0a  (expires));.  }.
1e40: 0a 20 20 2f 2a 20 43 6f 6e 74 65 6e 74 20 69 6e  .  /* Content in
1e50: 74 65 6e 64 65 64 20 66 6f 72 20 6c 6f 67 67 65  tended for logge
1e60: 64 20 69 6e 20 75 73 65 72 73 20 73 68 6f 75 6c  d in users shoul
1e70: 64 20 6f 6e 6c 79 20 62 65 20 63 61 63 68 65 64  d only be cached
1e80: 20 69 6e 0a 20 20 2a 2a 20 74 68 65 20 62 72 6f   in.  ** the bro
1e90: 77 73 65 72 2c 20 6e 6f 74 20 73 6f 6d 65 20 73  wser, not some s
1ea0: 68 61 72 65 64 20 6c 6f 63 61 74 69 6f 6e 2e 0a  hared location..
1eb0: 20 20 2a 2f 0a 20 20 70 72 69 6e 74 66 28 22 43    */.  printf("C
1ec0: 61 63 68 65 2d 63 6f 6e 74 72 6f 6c 3a 20 70 72  ache-control: pr
1ed0: 69 76 61 74 65 5c 72 5c 6e 22 29 3b 0a 0a 23 69  ivate\r\n");..#i
1ee0: 66 20 46 4f 53 53 49 4c 5f 49 31 38 4e 0a 20 20  f FOSSIL_I18N.  
1ef0: 70 72 69 6e 74 66 28 20 22 43 6f 6e 74 65 6e 74  printf( "Content
1f00: 2d 54 79 70 65 3a 20 25 73 3b 20 63 68 61 72 73  -Type: %s; chars
1f10: 65 74 3d 25 73 5c 72 5c 6e 22 2c 20 7a 43 6f 6e  et=%s\r\n", zCon
1f20: 74 65 6e 74 54 79 70 65 2c 20 6e 6c 5f 6c 61 6e  tentType, nl_lan
1f30: 67 69 6e 66 6f 28 43 4f 44 45 53 45 54 29 29 3b  ginfo(CODESET));
1f40: 0a 23 65 6c 73 65 0a 20 20 70 72 69 6e 74 66 28  .#else.  printf(
1f50: 20 22 43 6f 6e 74 65 6e 74 2d 54 79 70 65 3a 20   "Content-Type: 
1f60: 25 73 3b 20 63 68 61 72 73 65 74 3d 49 53 4f 2d  %s; charset=ISO-
1f70: 38 38 35 39 2d 31 5c 72 5c 6e 22 2c 20 7a 43 6f  8859-1\r\n", zCo
1f80: 6e 74 65 6e 74 54 79 70 65 29 3b 0a 23 65 6e 64  ntentType);.#end
1f90: 69 66 0a 20 20 69 66 28 20 73 74 72 63 6d 70 28  if.  if( strcmp(
1fa0: 7a 43 6f 6e 74 65 6e 74 54 79 70 65 2c 22 61 70  zContentType,"ap
1fb0: 70 6c 69 63 61 74 69 6f 6e 2f 78 2d 66 6f 73 73  plication/x-foss
1fc0: 69 6c 22 29 3d 3d 30 20 29 7b 0a 20 20 20 20 62  il")==0 ){.    b
1fd0: 6c 6f 62 5f 63 6f 6d 70 72 65 73 73 28 26 63 67  lob_compress(&cg
1fe0: 69 43 6f 6e 74 65 6e 74 2c 20 26 63 67 69 43 6f  iContent, &cgiCo
1ff0: 6e 74 65 6e 74 29 3b 0a 20 20 7d 0a 0a 20 20 69  ntent);.  }..  i
2000: 66 28 20 69 52 65 70 6c 79 53 74 61 74 75 73 20  f( iReplyStatus 
2010: 21 3d 20 33 30 34 20 29 20 7b 0a 20 20 20 20 70  != 304 ) {.    p
2020: 72 69 6e 74 66 28 20 22 43 6f 6e 74 65 6e 74 2d  rintf( "Content-
2030: 4c 65 6e 67 74 68 3a 20 25 64 5c 72 5c 6e 22 2c  Length: %d\r\n",
2040: 20 62 6c 6f 62 5f 73 69 7a 65 28 26 63 67 69 43   blob_size(&cgiC
2050: 6f 6e 74 65 6e 74 29 20 29 3b 0a 20 20 7d 0a 20  ontent) );.  }. 
2060: 20 70 72 69 6e 74 66 28 22 5c 72 5c 6e 22 29 3b   printf("\r\n");
2070: 0a 20 20 69 66 28 20 62 6c 6f 62 5f 73 69 7a 65  .  if( blob_size
2080: 28 26 63 67 69 43 6f 6e 74 65 6e 74 29 3e 30 20  (&cgiContent)>0 
2090: 26 26 20 69 52 65 70 6c 79 53 74 61 74 75 73 20  && iReplyStatus 
20a0: 21 3d 20 33 30 34 20 29 7b 0a 20 20 20 20 66 77  != 304 ){.    fw
20b0: 72 69 74 65 28 62 6c 6f 62 5f 62 75 66 66 65 72  rite(blob_buffer
20c0: 28 26 63 67 69 43 6f 6e 74 65 6e 74 29 2c 20 31  (&cgiContent), 1
20d0: 2c 20 62 6c 6f 62 5f 73 69 7a 65 28 26 63 67 69  , blob_size(&cgi
20e0: 43 6f 6e 74 65 6e 74 29 2c 20 73 74 64 6f 75 74  Content), stdout
20f0: 29 3b 0a 20 20 7d 0a 20 20 43 47 49 44 45 42 55  );.  }.  CGIDEBU
2100: 47 28 28 22 44 4f 4e 45 5c 6e 22 29 29 3b 0a 7d  G(("DONE\n"));.}
2110: 0a 0a 2f 2a 0a 2a 2a 20 44 6f 20 61 20 72 65 64  ../*.** Do a red
2120: 69 72 65 63 74 20 72 65 71 75 65 73 74 20 74 6f  irect request to
2130: 20 74 68 65 20 55 52 4c 20 67 69 76 65 6e 20 69   the URL given i
2140: 6e 20 74 68 65 20 61 72 67 75 6d 65 6e 74 2e 0a  n the argument..
2150: 2a 2a 0a 2a 2a 20 54 68 65 20 55 52 4c 20 6d 75  **.** The URL mu
2160: 73 74 20 62 65 20 72 65 6c 61 74 69 76 65 20 74  st be relative t
2170: 6f 20 74 68 65 20 62 61 73 65 20 6f 66 20 74 68  o the base of th
2180: 65 20 66 6f 73 73 69 6c 20 73 65 72 76 65 72 2e  e fossil server.
2190: 0a 2a 2f 0a 76 6f 69 64 20 63 67 69 5f 72 65 64  .*/.void cgi_red
21a0: 69 72 65 63 74 28 63 6f 6e 73 74 20 63 68 61 72  irect(const char
21b0: 20 2a 7a 55 52 4c 29 7b 0a 20 20 63 68 61 72 20   *zURL){.  char 
21c0: 2a 7a 4c 6f 63 61 74 69 6f 6e 3b 0a 20 20 43 47  *zLocation;.  CG
21d0: 49 44 45 42 55 47 28 28 22 72 65 64 69 72 65 63  IDEBUG(("redirec
21e0: 74 20 74 6f 20 25 73 5c 6e 22 2c 20 7a 55 52 4c  t to %s\n", zURL
21f0: 29 29 3b 0a 20 20 69 66 28 20 73 74 72 6e 63 6d  ));.  if( strncm
2200: 70 28 7a 55 52 4c 2c 22 68 74 74 70 3a 22 2c 35  p(zURL,"http:",5
2210: 29 3d 3d 30 20 7c 7c 20 73 74 72 6e 63 6d 70 28  )==0 || strncmp(
2220: 7a 55 52 4c 2c 22 68 74 74 70 73 3a 22 2c 36 29  zURL,"https:",6)
2230: 3d 3d 30 20 7c 7c 20 2a 7a 55 52 4c 3d 3d 27 2f  ==0 || *zURL=='/
2240: 27 20 29 7b 0a 20 20 20 20 63 67 69 5f 70 61 6e  ' ){.    cgi_pan
2250: 69 63 28 22 69 6e 76 61 6c 69 64 20 72 65 64 69  ic("invalid redi
2260: 72 65 63 74 20 55 52 4c 3a 20 25 73 22 2c 20 7a  rect URL: %s", z
2270: 55 52 4c 29 3b 0a 20 20 7d 0a 20 20 7a 4c 6f 63  URL);.  }.  zLoc
2280: 61 74 69 6f 6e 20 3d 20 6d 70 72 69 6e 74 66 28  ation = mprintf(
2290: 22 4c 6f 63 61 74 69 6f 6e 3a 20 25 73 2f 25 73  "Location: %s/%s
22a0: 5c 72 5c 6e 22 2c 20 67 2e 7a 42 61 73 65 55 52  \r\n", g.zBaseUR
22b0: 4c 2c 20 7a 55 52 4c 29 3b 0a 20 20 63 67 69 5f  L, zURL);.  cgi_
22c0: 61 70 70 65 6e 64 5f 68 65 61 64 65 72 28 7a 4c  append_header(zL
22d0: 6f 63 61 74 69 6f 6e 29 3b 0a 20 20 63 67 69 5f  ocation);.  cgi_
22e0: 72 65 73 65 74 5f 63 6f 6e 74 65 6e 74 28 29 3b  reset_content();
22f0: 0a 20 20 63 67 69 5f 70 72 69 6e 74 66 28 22 3c  .  cgi_printf("<
2300: 68 74 6d 6c 3e 5c 6e 3c 70 3e 52 65 64 69 72 65  html>\n<p>Redire
2310: 63 74 20 74 6f 20 25 68 3c 2f 70 3e 5c 6e 3c 2f  ct to %h</p>\n</
2320: 68 74 6d 6c 3e 5c 6e 22 2c 20 7a 55 52 4c 29 3b  html>\n", zURL);
2330: 0a 20 20 63 67 69 5f 73 65 74 5f 73 74 61 74 75  .  cgi_set_statu
2340: 73 28 33 30 32 2c 20 22 4d 6f 76 65 64 20 54 65  s(302, "Moved Te
2350: 6d 70 6f 72 61 72 69 6c 79 22 29 3b 0a 20 20 66  mporarily");.  f
2360: 72 65 65 28 7a 4c 6f 63 61 74 69 6f 6e 29 3b 0a  ree(zLocation);.
2370: 20 20 63 67 69 5f 72 65 70 6c 79 28 29 3b 0a 20    cgi_reply();. 
2380: 20 65 78 69 74 28 30 29 3b 0a 7d 0a 76 6f 69 64   exit(0);.}.void
2390: 20 63 67 69 5f 72 65 64 69 72 65 63 74 66 28 63   cgi_redirectf(c
23a0: 6f 6e 73 74 20 63 68 61 72 20 2a 7a 46 6f 72 6d  onst char *zForm
23b0: 61 74 2c 20 2e 2e 2e 29 7b 0a 20 20 76 61 5f 6c  at, ...){.  va_l
23c0: 69 73 74 20 61 70 3b 0a 20 20 76 61 5f 73 74 61  ist ap;.  va_sta
23d0: 72 74 28 61 70 2c 20 7a 46 6f 72 6d 61 74 29 3b  rt(ap, zFormat);
23e0: 0a 20 20 63 67 69 5f 72 65 64 69 72 65 63 74 28  .  cgi_redirect(
23f0: 76 6d 70 72 69 6e 74 66 28 7a 46 6f 72 6d 61 74  vmprintf(zFormat
2400: 2c 20 61 70 29 29 3b 0a 20 20 76 61 5f 65 6e 64  , ap));.  va_end
2410: 28 61 70 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 49  (ap);.}../*.** I
2420: 6e 66 6f 72 6d 61 74 69 6f 6e 20 61 62 6f 75 74  nformation about
2430: 20 61 6c 6c 20 71 75 65 72 79 20 70 61 72 61 6d   all query param
2440: 65 74 65 72 73 20 61 6e 64 20 63 6f 6f 6b 69 65  eters and cookie
2450: 73 20 61 72 65 20 73 74 6f 72 65 64 0a 2a 2a 20  s are stored.** 
2460: 69 6e 20 74 68 65 73 65 20 76 61 72 69 61 62 6c  in these variabl
2470: 65 73 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e  es..*/.static in
2480: 74 20 6e 41 6c 6c 6f 63 51 50 20 3d 20 30 3b 20  t nAllocQP = 0; 
2490: 2f 2a 20 53 70 61 63 65 20 61 6c 6c 6f 63 61 74  /* Space allocat
24a0: 65 64 20 66 6f 72 20 61 50 61 72 61 6d 51 50 5b  ed for aParamQP[
24b0: 5d 20 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20  ] */.static int 
24c0: 6e 55 73 65 64 51 50 20 3d 20 30 3b 20 20 2f 2a  nUsedQP = 0;  /*
24d0: 20 53 70 61 63 65 20 61 63 74 75 61 6c 6c 79 20   Space actually 
24e0: 75 73 65 64 20 69 6e 20 61 50 61 72 61 6d 51 50  used in aParamQP
24f0: 5b 5d 20 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74  [] */.static int
2500: 20 73 6f 72 74 51 50 20 3d 20 30 3b 20 20 20 2f   sortQP = 0;   /
2510: 2a 20 54 72 75 65 20 69 66 20 61 50 61 72 61 6d  * True if aParam
2520: 51 50 5b 5d 20 6e 65 65 64 73 20 73 6f 72 74 69  QP[] needs sorti
2530: 6e 67 20 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74  ng */.static int
2540: 20 73 65 71 51 50 20 3d 20 30 3b 20 20 20 20 2f   seqQP = 0;    /
2550: 2a 20 53 65 71 75 65 6e 63 65 20 6e 75 6d 62 65  * Sequence numbe
2560: 72 73 20 2a 2f 0a 73 74 61 74 69 63 20 73 74 72  rs */.static str
2570: 75 63 74 20 51 50 61 72 61 6d 20 7b 20 20 20 2f  uct QParam {   /
2580: 2a 20 4f 6e 65 20 65 6e 74 72 79 20 66 6f 72 20  * One entry for 
2590: 65 61 63 68 20 71 75 65 72 79 20 70 61 72 61 6d  each query param
25a0: 65 74 65 72 20 6f 72 20 63 6f 6f 6b 69 65 20 2a  eter or cookie *
25b0: 2f 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a  /.  const char *
25c0: 7a 4e 61 6d 65 3b 20 20 20 20 20 20 20 20 2f 2a  zName;        /*
25d0: 20 50 61 72 61 6d 65 74 65 72 20 6f 72 20 63 6f   Parameter or co
25e0: 6f 6b 69 65 20 6e 61 6d 65 20 2a 2f 0a 20 20 63  okie name */.  c
25f0: 6f 6e 73 74 20 63 68 61 72 20 2a 7a 56 61 6c 75  onst char *zValu
2600: 65 3b 20 20 20 20 20 20 20 2f 2a 20 56 61 6c 75  e;       /* Valu
2610: 65 20 6f 66 20 74 68 65 20 71 75 65 72 79 20 70  e of the query p
2620: 61 72 61 6d 65 74 65 72 20 6f 72 20 63 6f 6f 6b  arameter or cook
2630: 69 65 20 2a 2f 0a 20 20 69 6e 74 20 73 65 71 3b  ie */.  int seq;
2640: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2650: 20 20 2f 2a 20 4f 72 64 65 72 20 6f 66 20 69 6e    /* Order of in
2660: 73 65 72 74 69 6f 6e 20 2a 2f 0a 7d 20 2a 61 50  sertion */.} *aP
2670: 61 72 61 6d 51 50 3b 20 20 20 20 20 20 20 20 20  aramQP;         
2680: 20 20 20 20 2f 2a 20 41 6e 20 61 72 72 61 79 20      /* An array 
2690: 6f 66 20 61 6c 6c 20 70 61 72 61 6d 65 74 65 72  of all parameter
26a0: 73 20 61 6e 64 20 63 6f 6f 6b 69 65 73 20 2a 2f  s and cookies */
26b0: 0a 0a 2f 2a 0a 2a 2a 20 41 64 64 20 61 6e 6f 74  ../*.** Add anot
26c0: 68 65 72 20 71 75 65 72 79 20 70 61 72 61 6d 65  her query parame
26d0: 74 65 72 20 6f 72 20 63 6f 6f 6b 69 65 20 74 6f  ter or cookie to
26e0: 20 74 68 65 20 70 61 72 61 6d 65 74 65 72 20 73   the parameter s
26f0: 65 74 2e 0a 2a 2a 20 7a 4e 61 6d 65 20 69 73 20  et..** zName is 
2700: 74 68 65 20 6e 61 6d 65 20 6f 66 20 74 68 65 20  the name of the 
2710: 71 75 65 72 79 20 70 61 72 61 6d 65 74 65 72 20  query parameter 
2720: 6f 72 20 63 6f 6f 6b 69 65 20 61 6e 64 20 7a 56  or cookie and zV
2730: 61 6c 75 65 0a 2a 2a 20 69 73 20 69 74 73 20 66  alue.** is its f
2740: 75 6c 6c 79 20 64 65 63 6f 64 65 64 20 76 61 6c  ully decoded val
2750: 75 65 2e 0a 2a 2a 0a 2a 2a 20 7a 4e 61 6d 65 20  ue..**.** zName 
2760: 61 6e 64 20 7a 56 61 6c 75 65 20 61 72 65 20 6e  and zValue are n
2770: 6f 74 20 63 6f 70 69 65 64 20 61 6e 64 20 6d 75  ot copied and mu
2780: 73 74 20 6e 6f 74 20 63 68 61 6e 67 65 20 6f 72  st not change or
2790: 20 62 65 0a 2a 2a 20 64 65 61 6c 6c 6f 63 61 74   be.** deallocat
27a0: 65 64 20 61 66 74 65 72 20 74 68 69 73 20 72 6f  ed after this ro
27b0: 75 74 69 6e 65 20 72 65 74 75 72 6e 73 2e 0a 2a  utine returns..*
27c0: 2f 0a 76 6f 69 64 20 63 67 69 5f 73 65 74 5f 70  /.void cgi_set_p
27d0: 61 72 61 6d 65 74 65 72 5f 6e 6f 63 6f 70 79 28  arameter_nocopy(
27e0: 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 4e 61 6d  const char *zNam
27f0: 65 2c 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a  e, const char *z
2800: 56 61 6c 75 65 29 7b 0a 20 20 69 66 28 20 6e 41  Value){.  if( nA
2810: 6c 6c 6f 63 51 50 3c 3d 6e 55 73 65 64 51 50 20  llocQP<=nUsedQP 
2820: 29 7b 0a 20 20 20 20 6e 41 6c 6c 6f 63 51 50 20  ){.    nAllocQP 
2830: 3d 20 6e 41 6c 6c 6f 63 51 50 2a 32 20 2b 20 31  = nAllocQP*2 + 1
2840: 30 3b 0a 20 20 20 20 61 50 61 72 61 6d 51 50 20  0;.    aParamQP 
2850: 3d 20 72 65 61 6c 6c 6f 63 28 20 61 50 61 72 61  = realloc( aPara
2860: 6d 51 50 2c 20 6e 41 6c 6c 6f 63 51 50 2a 73 69  mQP, nAllocQP*si
2870: 7a 65 6f 66 28 61 50 61 72 61 6d 51 50 5b 30 5d  zeof(aParamQP[0]
2880: 29 20 29 3b 0a 20 20 20 20 69 66 28 20 61 50 61  ) );.    if( aPa
2890: 72 61 6d 51 50 3d 3d 30 20 29 20 65 78 69 74 28  ramQP==0 ) exit(
28a0: 31 29 3b 0a 20 20 7d 0a 20 20 61 50 61 72 61 6d  1);.  }.  aParam
28b0: 51 50 5b 6e 55 73 65 64 51 50 5d 2e 7a 4e 61 6d  QP[nUsedQP].zNam
28c0: 65 20 3d 20 7a 4e 61 6d 65 3b 0a 20 20 61 50 61  e = zName;.  aPa
28d0: 72 61 6d 51 50 5b 6e 55 73 65 64 51 50 5d 2e 7a  ramQP[nUsedQP].z
28e0: 56 61 6c 75 65 20 3d 20 7a 56 61 6c 75 65 3b 0a  Value = zValue;.
28f0: 20 20 61 50 61 72 61 6d 51 50 5b 6e 55 73 65 64    aParamQP[nUsed
2900: 51 50 5d 2e 73 65 71 20 3d 20 73 65 71 51 50 2b  QP].seq = seqQP+
2910: 2b 3b 0a 20 20 6e 55 73 65 64 51 50 2b 2b 3b 0a  +;.  nUsedQP++;.
2920: 20 20 73 6f 72 74 51 50 20 3d 20 31 3b 0a 7d 0a    sortQP = 1;.}.
2930: 0a 2f 2a 0a 2a 2a 20 41 64 64 20 61 6e 6f 74 68  ./*.** Add anoth
2940: 65 72 20 71 75 65 72 79 20 70 61 72 61 6d 65 74  er query paramet
2950: 65 72 20 6f 72 20 63 6f 6f 6b 69 65 20 74 6f 20  er or cookie to 
2960: 74 68 65 20 70 61 72 61 6d 65 74 65 72 20 73 65  the parameter se
2970: 74 2e 0a 2a 2a 20 7a 4e 61 6d 65 20 69 73 20 74  t..** zName is t
2980: 68 65 20 6e 61 6d 65 20 6f 66 20 74 68 65 20 71  he name of the q
2990: 75 65 72 79 20 70 61 72 61 6d 65 74 65 72 20 6f  uery parameter o
29a0: 72 20 63 6f 6f 6b 69 65 20 61 6e 64 20 7a 56 61  r cookie and zVa
29b0: 6c 75 65 0a 2a 2a 20 69 73 20 69 74 73 20 66 75  lue.** is its fu
29c0: 6c 6c 79 20 64 65 63 6f 64 65 64 20 76 61 6c 75  lly decoded valu
29d0: 65 2e 0a 2a 2a 0a 2a 2a 20 43 6f 70 69 65 73 20  e..**.** Copies 
29e0: 61 72 65 20 6d 61 64 65 20 6f 66 20 62 6f 74 68  are made of both
29f0: 20 74 68 65 20 7a 4e 61 6d 65 20 61 6e 64 20 7a   the zName and z
2a00: 56 61 6c 75 65 20 70 61 72 61 6d 65 74 65 72 73  Value parameters
2a10: 2e 0a 2a 2f 0a 76 6f 69 64 20 63 67 69 5f 73 65  ..*/.void cgi_se
2a20: 74 5f 70 61 72 61 6d 65 74 65 72 28 63 6f 6e 73  t_parameter(cons
2a30: 74 20 63 68 61 72 20 2a 7a 4e 61 6d 65 2c 20 63  t char *zName, c
2a40: 6f 6e 73 74 20 63 68 61 72 20 2a 7a 56 61 6c 75  onst char *zValu
2a50: 65 29 7b 0a 20 20 63 67 69 5f 73 65 74 5f 70 61  e){.  cgi_set_pa
2a60: 72 61 6d 65 74 65 72 5f 6e 6f 63 6f 70 79 28 6d  rameter_nocopy(m
2a70: 70 72 69 6e 74 66 28 22 25 73 22 2c 7a 4e 61 6d  printf("%s",zNam
2a80: 65 29 2c 20 6d 70 72 69 6e 74 66 28 22 25 73 22  e), mprintf("%s"
2a90: 2c 7a 56 61 6c 75 65 29 29 3b 0a 7d 0a 0a 2f 2a  ,zValue));.}../*
2aa0: 0a 2a 2a 20 41 64 64 20 61 20 71 75 65 72 79 20  .** Add a query 
2ab0: 70 61 72 61 6d 65 74 65 72 2e 20 20 54 68 65 20  parameter.  The 
2ac0: 7a 4e 61 6d 65 20 70 6f 72 74 69 6f 6e 20 69 73  zName portion is
2ad0: 20 66 69 78 65 64 20 62 75 74 20 61 20 63 6f 70   fixed but a cop
2ae0: 79 0a 2a 2a 20 6d 75 73 74 20 62 65 20 6d 61 64  y.** must be mad
2af0: 65 20 6f 66 20 7a 56 61 6c 75 65 2e 0a 2a 2f 0a  e of zValue..*/.
2b00: 76 6f 69 64 20 63 67 69 5f 73 65 74 65 6e 76 28  void cgi_setenv(
2b10: 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 4e 61 6d  const char *zNam
2b20: 65 2c 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a  e, const char *z
2b30: 56 61 6c 75 65 29 7b 0a 20 20 63 67 69 5f 73 65  Value){.  cgi_se
2b40: 74 5f 70 61 72 61 6d 65 74 65 72 5f 6e 6f 63 6f  t_parameter_noco
2b50: 70 79 28 7a 4e 61 6d 65 2c 20 6d 70 72 69 6e 74  py(zName, mprint
2b60: 66 28 22 25 73 22 2c 7a 56 61 6c 75 65 29 29 3b  f("%s",zValue));
2b70: 0a 7d 0a 20 0a 0a 2f 2a 0a 2a 2a 20 41 64 64 20  .}. ../*.** Add 
2b80: 61 20 6c 69 73 74 20 6f 66 20 71 75 65 72 79 20  a list of query 
2b90: 70 61 72 61 6d 65 74 65 72 73 20 6f 72 20 63 6f  parameters or co
2ba0: 6f 6b 69 65 73 20 74 6f 20 74 68 65 20 70 61 72  okies to the par
2bb0: 61 6d 65 74 65 72 20 73 65 74 2e 0a 2a 2a 0a 2a  ameter set..**.*
2bc0: 2a 20 45 61 63 68 20 70 61 72 61 6d 65 74 65 72  * Each parameter
2bd0: 20 69 73 20 6f 66 20 74 68 65 20 66 6f 72 6d 20   is of the form 
2be0: 4e 41 4d 45 3d 56 41 4c 55 45 2e 20 20 42 6f 74  NAME=VALUE.  Bot
2bf0: 68 20 74 68 65 20 4e 41 4d 45 20 61 6e 64 20 74  h the NAME and t
2c00: 68 65 0a 2a 2a 20 56 41 4c 55 45 20 6d 61 79 20  he.** VALUE may 
2c10: 62 65 20 75 72 6c 2d 65 6e 63 6f 64 65 64 20 28  be url-encoded (
2c20: 22 2b 22 20 66 6f 72 20 73 70 61 63 65 2c 20 22  "+" for space, "
2c30: 25 48 48 22 20 66 6f 72 20 6f 74 68 65 72 20 73  %HH" for other s
2c40: 70 65 63 69 61 6c 0a 2a 2a 20 63 68 61 72 61 63  pecial.** charac
2c50: 74 65 72 73 29 2e 20 20 42 75 74 20 74 68 69 73  ters).  But this
2c60: 20 72 6f 75 74 69 6e 65 20 61 73 73 75 6d 65 73   routine assumes
2c70: 20 74 68 61 74 20 4e 41 4d 45 20 63 6f 6e 74 61   that NAME conta
2c80: 69 6e 73 20 6e 6f 0a 2a 2a 20 73 70 65 63 69 61  ins no.** specia
2c90: 6c 20 63 68 61 72 61 63 74 65 72 20 61 6e 64 20  l character and 
2ca0: 74 68 65 72 65 66 6f 72 65 20 64 6f 65 73 20 6e  therefore does n
2cb0: 6f 74 20 64 65 63 6f 64 65 20 69 74 2e 0a 2a 2a  ot decode it..**
2cc0: 0a 2a 2a 20 49 66 20 4e 41 4d 45 20 62 65 67 69  .** If NAME begi
2cd0: 6e 73 20 77 69 74 68 20 61 6e 6f 74 68 65 72 20  ns with another 
2ce0: 6f 74 68 65 72 20 74 68 61 6e 20 61 20 6c 6f 77  other than a low
2cf0: 65 72 2d 63 61 73 65 20 6c 65 74 74 65 72 20 74  er-case letter t
2d00: 68 65 6e 0a 2a 2a 20 74 68 65 20 65 6e 74 69 72  hen.** the entir
2d10: 65 20 4e 41 4d 45 3d 56 41 4c 55 45 20 74 65 72  e NAME=VALUE ter
2d20: 6d 20 69 73 20 69 67 6e 6f 72 65 64 2e 20 20 48  m is ignored.  H
2d30: 65 6e 63 65 3a 0a 2a 2a 0a 2a 2a 20 20 20 20 20  ence:.**.**     
2d40: 20 2a 20 20 63 6f 6f 6b 69 65 73 20 61 6e 64 20   *  cookies and 
2d50: 71 75 65 72 79 20 70 61 72 61 6d 65 74 65 72 73  query parameters
2d60: 20 74 68 61 74 20 68 61 76 65 20 75 70 70 65 72   that have upper
2d70: 63 61 73 65 20 6e 61 6d 65 73 0a 2a 2a 20 20 20  case names.**   
2d80: 20 20 20 20 20 20 61 72 65 20 69 67 6e 6f 72 65        are ignore
2d90: 64 2e 0a 2a 2a 0a 2a 2a 20 20 20 20 20 20 2a 20  d..**.**      * 
2da0: 20 69 74 20 69 73 20 69 6d 70 6f 73 73 69 62 6c   it is impossibl
2db0: 65 20 66 6f 72 20 61 20 63 6f 6f 6b 69 65 20 6f  e for a cookie o
2dc0: 72 20 71 75 65 72 79 20 70 61 72 61 6d 65 74 65  r query paramete
2dd0: 72 20 74 6f 0a 2a 2a 20 20 20 20 20 20 20 20 20  r to.**         
2de0: 6f 76 65 72 72 69 64 65 20 74 68 65 20 76 61 6c  override the val
2df0: 75 65 20 6f 66 20 61 6e 20 65 6e 76 69 72 6f 6e  ue of an environ
2e00: 6d 65 6e 74 20 76 61 72 69 61 62 6c 65 20 73 69  ment variable si
2e10: 6e 63 65 0a 2a 2a 20 20 20 20 20 20 20 20 20 65  nce.**         e
2e20: 6e 76 69 72 6f 6e 6d 65 6e 74 20 76 61 72 69 61  nvironment varia
2e30: 62 6c 65 73 20 61 6c 77 61 79 73 20 68 61 76 65  bles always have
2e40: 20 75 70 70 65 72 63 61 73 65 20 6e 61 6d 65 73   uppercase names
2e50: 2e 0a 2a 2a 0a 2a 2a 20 50 61 72 61 6d 65 74 65  ..**.** Paramete
2e60: 72 73 20 61 72 65 20 73 65 70 61 72 61 74 65 64  rs are separated
2e70: 20 62 79 20 74 68 65 20 22 74 65 72 6d 69 6e 61   by the "termina
2e80: 74 6f 72 22 20 63 68 61 72 61 63 74 65 72 2e 20  tor" character. 
2e90: 20 57 68 69 74 65 73 70 61 63 65 0a 2a 2a 20 62   Whitespace.** b
2ea0: 65 66 6f 72 65 20 74 68 65 20 4e 41 4d 45 20 69  efore the NAME i
2eb0: 73 20 69 67 6e 6f 72 65 64 2e 0a 2a 2a 0a 2a 2a  s ignored..**.**
2ec0: 20 54 68 65 20 69 6e 70 75 74 20 73 74 72 69 6e   The input strin
2ed0: 67 20 22 7a 22 20 69 73 20 6d 6f 64 69 66 69 65  g "z" is modifie
2ee0: 64 20 62 75 74 20 6e 6f 20 63 6f 70 69 65 73 20  d but no copies 
2ef0: 69 73 20 6d 61 64 65 2e 20 20 22 7a 22 0a 2a 2a  is made.  "z".**
2f00: 20 73 68 6f 75 6c 64 20 6e 6f 74 20 62 65 20 64   should not be d
2f10: 65 61 6c 6c 6f 63 61 74 65 64 20 6f 72 20 63 68  eallocated or ch
2f20: 61 6e 67 65 64 20 61 67 61 69 6e 20 61 66 74 65  anged again afte
2f30: 72 20 74 68 69 73 20 72 6f 75 74 69 6e 65 0a 2a  r this routine.*
2f40: 2a 20 72 65 74 75 72 6e 73 20 6f 72 20 69 74 20  * returns or it 
2f50: 77 69 6c 6c 20 63 6f 72 72 75 70 74 20 74 68 65  will corrupt the
2f60: 20 70 61 72 61 6d 65 74 65 72 20 74 61 62 6c 65   parameter table
2f70: 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 76 6f 69 64  ..*/.static void
2f80: 20 61 64 64 5f 70 61 72 61 6d 5f 6c 69 73 74 28   add_param_list(
2f90: 63 68 61 72 20 2a 7a 2c 20 69 6e 74 20 74 65 72  char *z, int ter
2fa0: 6d 69 6e 61 74 6f 72 29 7b 0a 20 20 77 68 69 6c  minator){.  whil
2fb0: 65 28 20 2a 7a 20 29 7b 0a 20 20 20 20 63 68 61  e( *z ){.    cha
2fc0: 72 20 2a 7a 4e 61 6d 65 3b 0a 20 20 20 20 63 68  r *zName;.    ch
2fd0: 61 72 20 2a 7a 56 61 6c 75 65 3b 0a 20 20 20 20  ar *zValue;.    
2fe0: 77 68 69 6c 65 28 20 69 73 73 70 61 63 65 28 2a  while( isspace(*
2ff0: 7a 29 20 29 7b 20 7a 2b 2b 3b 20 7d 0a 20 20 20  z) ){ z++; }.   
3000: 20 7a 4e 61 6d 65 20 3d 20 7a 3b 0a 20 20 20 20   zName = z;.    
3010: 77 68 69 6c 65 28 20 2a 7a 20 26 26 20 2a 7a 21  while( *z && *z!
3020: 3d 27 3d 27 20 26 26 20 2a 7a 21 3d 74 65 72 6d  ='=' && *z!=term
3030: 69 6e 61 74 6f 72 20 29 7b 20 7a 2b 2b 3b 20 7d  inator ){ z++; }
3040: 0a 20 20 20 20 69 66 28 20 2a 7a 3d 3d 27 3d 27  .    if( *z=='='
3050: 20 29 7b 0a 20 20 20 20 20 20 2a 7a 20 3d 20 30   ){.      *z = 0
3060: 3b 0a 20 20 20 20 20 20 7a 2b 2b 3b 0a 20 20 20  ;.      z++;.   
3070: 20 20 20 7a 56 61 6c 75 65 20 3d 20 7a 3b 0a 20     zValue = z;. 
3080: 20 20 20 20 20 77 68 69 6c 65 28 20 2a 7a 20 26       while( *z &
3090: 26 20 2a 7a 21 3d 74 65 72 6d 69 6e 61 74 6f 72  & *z!=terminator
30a0: 20 29 7b 20 7a 2b 2b 3b 20 7d 0a 20 20 20 20 20   ){ z++; }.     
30b0: 20 69 66 28 20 2a 7a 20 29 7b 0a 20 20 20 20 20   if( *z ){.     
30c0: 20 20 20 2a 7a 20 3d 20 30 3b 0a 20 20 20 20 20     *z = 0;.     
30d0: 20 20 20 7a 2b 2b 3b 0a 20 20 20 20 20 20 7d 0a     z++;.      }.
30e0: 20 20 20 20 20 20 64 65 68 74 74 70 69 7a 65 28        dehttpize(
30f0: 7a 56 61 6c 75 65 29 3b 0a 20 20 20 20 7d 65 6c  zValue);.    }el
3100: 73 65 7b 0a 20 20 20 20 20 20 69 66 28 20 2a 7a  se{.      if( *z
3110: 20 29 7b 20 2a 7a 2b 2b 20 3d 20 30 3b 20 7d 0a   ){ *z++ = 0; }.
3120: 20 20 20 20 20 20 7a 56 61 6c 75 65 20 3d 20 22        zValue = "
3130: 22 3b 0a 20 20 20 20 7d 0a 20 20 20 20 69 66 28  ";.    }.    if(
3140: 20 69 73 6c 6f 77 65 72 28 7a 4e 61 6d 65 5b 30   islower(zName[0
3150: 5d 29 20 29 7b 0a 20 20 20 20 20 20 63 67 69 5f  ]) ){.      cgi_
3160: 73 65 74 5f 70 61 72 61 6d 65 74 65 72 5f 6e 6f  set_parameter_no
3170: 63 6f 70 79 28 7a 4e 61 6d 65 2c 20 7a 56 61 6c  copy(zName, zVal
3180: 75 65 29 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 7d  ue);.    }.  }.}
3190: 0a 0a 2f 2a 0a 2a 2a 20 2a 70 7a 20 69 73 20 61  ../*.** *pz is a
31a0: 20 73 74 72 69 6e 67 20 74 68 61 74 20 63 6f 6e   string that con
31b0: 73 69 73 74 73 20 6f 66 20 6d 75 6c 74 69 70 6c  sists of multipl
31c0: 65 20 6c 69 6e 65 73 20 6f 66 20 74 65 78 74 2e  e lines of text.
31d0: 20 20 54 68 69 73 0a 2a 2a 20 72 6f 75 74 69 6e    This.** routin
31e0: 65 20 66 69 6e 64 73 20 74 68 65 20 65 6e 64 20  e finds the end 
31f0: 6f 66 20 74 68 65 20 63 75 72 72 65 6e 74 20 6c  of the current l
3200: 69 6e 65 20 6f 66 20 74 65 78 74 20 61 6e 64 20  ine of text and 
3210: 63 6f 6e 76 65 72 74 73 0a 2a 2a 20 74 68 65 20  converts.** the 
3220: 22 5c 6e 22 20 6f 72 20 22 5c 72 5c 6e 22 20 74  "\n" or "\r\n" t
3230: 68 61 74 20 65 6e 64 73 20 74 68 61 74 20 6c 69  hat ends that li
3240: 6e 65 20 69 6e 74 6f 20 61 20 22 5c 30 30 30 22  ne into a "\000"
3250: 2e 20 20 49 74 20 74 68 65 6e 0a 2a 2a 20 61 64  .  It then.** ad
3260: 76 61 6e 63 65 73 20 2a 70 7a 20 74 6f 20 74 68  vances *pz to th
3270: 65 20 62 65 67 69 6e 6e 69 6e 67 20 6f 66 20 74  e beginning of t
3280: 68 65 20 6e 65 78 74 20 6c 69 6e 65 20 61 6e 64  he next line and
3290: 20 72 65 74 75 72 6e 73 20 74 68 65 0a 2a 2a 20   returns the.** 
32a0: 70 72 65 76 69 6f 75 73 20 76 61 6c 75 65 20 6f  previous value o
32b0: 66 20 2a 70 7a 20 28 77 68 69 63 68 20 69 73 20  f *pz (which is 
32c0: 74 68 65 20 73 74 61 72 74 20 6f 66 20 74 68 65  the start of the
32d0: 20 63 75 72 72 65 6e 74 20 6c 69 6e 65 2e 29 0a   current line.).
32e0: 2a 2f 0a 73 74 61 74 69 63 20 63 68 61 72 20 2a  */.static char *
32f0: 67 65 74 5f 6c 69 6e 65 5f 66 72 6f 6d 5f 73 74  get_line_from_st
3300: 72 69 6e 67 28 63 68 61 72 20 2a 2a 70 7a 2c 20  ring(char **pz, 
3310: 69 6e 74 20 2a 70 4c 65 6e 29 7b 0a 20 20 63 68  int *pLen){.  ch
3320: 61 72 20 2a 7a 20 3d 20 2a 70 7a 3b 0a 20 20 69  ar *z = *pz;.  i
3330: 6e 74 20 69 3b 0a 20 20 69 66 28 20 7a 5b 30 5d  nt i;.  if( z[0]
3340: 3d 3d 30 20 29 20 72 65 74 75 72 6e 20 30 3b 0a  ==0 ) return 0;.
3350: 20 20 66 6f 72 28 69 3d 30 3b 20 7a 5b 69 5d 3b    for(i=0; z[i];
3360: 20 69 2b 2b 29 7b 0a 20 20 20 20 69 66 28 20 7a   i++){.    if( z
3370: 5b 69 5d 3d 3d 27 5c 6e 27 20 29 7b 0a 20 20 20  [i]=='\n' ){.   
3380: 20 20 20 69 66 28 20 69 3e 30 20 26 26 20 7a 5b     if( i>0 && z[
3390: 69 2d 31 5d 3d 3d 27 5c 72 27 20 29 7b 0a 20 20  i-1]=='\r' ){.  
33a0: 20 20 20 20 20 20 7a 5b 69 2d 31 5d 20 3d 20 30        z[i-1] = 0
33b0: 3b 0a 20 20 20 20 20 20 7d 65 6c 73 65 7b 0a 20  ;.      }else{. 
33c0: 20 20 20 20 20 20 20 7a 5b 69 5d 20 3d 20 30 3b         z[i] = 0;
33d0: 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 69  .      }.      i
33e0: 2b 2b 3b 0a 20 20 20 20 20 20 62 72 65 61 6b 3b  ++;.      break;
33f0: 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20 2a 70 7a  .    }.  }.  *pz
3400: 20 3d 20 26 7a 5b 69 5d 3b 0a 20 20 2a 70 4c 65   = &z[i];.  *pLe
3410: 6e 20 2d 3d 20 69 3b 0a 20 20 72 65 74 75 72 6e  n -= i;.  return
3420: 20 7a 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54 68 65   z;.}../*.** The
3430: 20 69 6e 70 75 74 20 2a 70 7a 20 70 6f 69 6e 74   input *pz point
3440: 73 20 74 6f 20 63 6f 6e 74 65 6e 74 20 74 68 61  s to content tha
3450: 74 20 69 73 20 74 65 72 6d 69 6e 61 74 65 64 20  t is terminated 
3460: 62 79 20 61 20 22 5c 72 5c 6e 22 0a 2a 2a 20 66  by a "\r\n".** f
3470: 6f 6c 6c 6f 77 65 64 20 62 79 20 74 68 65 20 62  ollowed by the b
3480: 6f 75 6e 64 72 79 20 6d 61 72 6b 65 72 20 7a 42  oundry marker zB
3490: 6f 75 6e 64 72 79 2e 20 20 41 6e 20 65 78 74 72  oundry.  An extr
34a0: 61 20 22 2d 2d 22 20 6d 61 79 20 6f 72 0a 2a 2a  a "--" may or.**
34b0: 20 6d 61 79 20 6e 6f 74 20 62 65 20 61 70 70 65   may not be appe
34c0: 6e 64 65 64 20 74 6f 20 74 68 65 20 62 6f 75 6e  nded to the boun
34d0: 64 72 79 20 6d 61 72 6b 65 72 2e 20 20 54 68 65  dry marker.  The
34e0: 72 65 20 61 72 65 20 2a 70 4c 65 6e 20 63 68 61  re are *pLen cha
34f0: 72 61 63 74 65 72 73 0a 2a 2a 20 69 6e 20 2a 70  racters.** in *p
3500: 7a 2e 0a 2a 2a 0a 2a 2a 20 54 68 69 73 20 72 6f  z..**.** This ro
3510: 75 74 69 6e 65 20 61 64 64 73 20 61 20 22 5c 30  utine adds a "\0
3520: 30 30 22 20 74 6f 20 74 68 65 20 65 6e 64 20 6f  00" to the end o
3530: 66 20 74 68 65 20 63 6f 6e 74 65 6e 74 20 28 6f  f the content (o
3540: 76 65 72 77 72 69 74 69 6e 67 0a 2a 2a 20 74 68  verwriting.** th
3550: 65 20 22 5c 72 5c 6e 22 29 20 61 6e 64 20 72 65  e "\r\n") and re
3560: 74 75 72 6e 73 20 61 20 70 6f 69 6e 74 65 72 20  turns a pointer 
3570: 74 6f 20 74 68 65 20 63 6f 6e 74 65 6e 74 2e 20  to the content. 
3580: 20 54 68 65 20 2a 70 7a 20 69 6e 70 75 74 0a 2a   The *pz input.*
3590: 2a 20 69 73 20 61 64 6a 75 73 74 65 64 20 74 6f  * is adjusted to
35a0: 20 70 6f 69 6e 74 20 74 6f 20 74 68 65 20 66 69   point to the fi
35b0: 72 73 74 20 6c 69 6e 65 20 66 6f 6c 6c 6f 77 69  rst line followi
35c0: 6e 67 20 74 68 65 20 62 6f 75 6e 64 72 79 2e 0a  ng the boundry..
35d0: 2a 2a 20 54 68 65 20 6c 65 6e 67 74 68 20 6f 66  ** The length of
35e0: 20 74 68 65 20 63 6f 6e 74 65 6e 74 20 69 73 20   the content is 
35f0: 73 74 6f 72 65 64 20 69 6e 20 2a 70 6e 43 6f 6e  stored in *pnCon
3600: 74 65 6e 74 2e 0a 2a 2f 0a 73 74 61 74 69 63 20  tent..*/.static 
3610: 63 68 61 72 20 2a 67 65 74 5f 62 6f 75 6e 64 65  char *get_bounde
3620: 64 5f 63 6f 6e 74 65 6e 74 28 0a 20 20 63 68 61  d_content(.  cha
3630: 72 20 2a 2a 70 7a 2c 20 20 20 20 20 20 20 20 20  r **pz,         
3640: 2f 2a 20 43 6f 6e 74 65 6e 74 20 74 61 6b 65 6e  /* Content taken
3650: 20 66 72 6f 6d 20 68 65 72 65 20 2a 2f 0a 20 20   from here */.  
3660: 69 6e 74 20 2a 70 4c 65 6e 2c 20 20 20 20 20 20  int *pLen,      
3670: 20 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f 66 20     /* Number of 
3680: 62 79 74 65 73 20 6f 66 20 64 61 74 61 20 69 6e  bytes of data in
3690: 20 28 2a 70 7a 29 5b 5d 20 2a 2f 0a 20 20 63 68   (*pz)[] */.  ch
36a0: 61 72 20 2a 7a 42 6f 75 6e 64 72 79 2c 20 20 20  ar *zBoundry,   
36b0: 20 2f 2a 20 42 6f 75 6e 64 72 79 20 74 65 78 74   /* Boundry text
36c0: 20 6d 61 72 6b 69 6e 67 20 74 68 65 20 65 6e 64   marking the end
36d0: 20 6f 66 20 63 6f 6e 74 65 6e 74 20 2a 2f 0a 20   of content */. 
36e0: 20 69 6e 74 20 2a 70 6e 43 6f 6e 74 65 6e 74 20   int *pnContent 
36f0: 20 20 20 20 2f 2a 20 57 72 69 74 65 20 74 68 65      /* Write the
3700: 20 73 69 7a 65 20 6f 66 20 74 68 65 20 63 6f 6e   size of the con
3710: 74 65 6e 74 20 68 65 72 65 20 2a 2f 0a 29 7b 0a  tent here */.){.
3720: 20 20 63 68 61 72 20 2a 7a 20 3d 20 2a 70 7a 3b    char *z = *pz;
3730: 0a 20 20 69 6e 74 20 6c 65 6e 20 3d 20 2a 70 4c  .  int len = *pL
3740: 65 6e 3b 0a 20 20 69 6e 74 20 69 3b 0a 20 20 69  en;.  int i;.  i
3750: 6e 74 20 6e 42 6f 75 6e 64 72 79 20 3d 20 73 74  nt nBoundry = st
3760: 72 6c 65 6e 28 7a 42 6f 75 6e 64 72 79 29 3b 0a  rlen(zBoundry);.
3770: 20 20 2a 70 6e 43 6f 6e 74 65 6e 74 20 3d 20 6c    *pnContent = l
3780: 65 6e 3b 0a 20 20 66 6f 72 28 69 3d 30 3b 20 69  en;.  for(i=0; i
3790: 3c 6c 65 6e 3b 20 69 2b 2b 29 7b 0a 20 20 20 20  <len; i++){.    
37a0: 69 66 28 20 7a 5b 69 5d 3d 3d 27 5c 6e 27 20 26  if( z[i]=='\n' &
37b0: 26 20 73 74 72 6e 63 6d 70 28 7a 42 6f 75 6e 64  & strncmp(zBound
37c0: 72 79 2c 20 26 7a 5b 69 2b 31 5d 2c 20 6e 42 6f  ry, &z[i+1], nBo
37d0: 75 6e 64 72 79 29 3d 3d 30 20 29 7b 0a 20 20 20  undry)==0 ){.   
37e0: 20 20 20 69 66 28 20 69 3e 30 20 26 26 20 7a 5b     if( i>0 && z[
37f0: 69 2d 31 5d 3d 3d 27 5c 72 27 20 29 20 69 2d 2d  i-1]=='\r' ) i--
3800: 3b 0a 20 20 20 20 20 20 7a 5b 69 5d 20 3d 20 30  ;.      z[i] = 0
3810: 3b 0a 20 20 20 20 20 20 2a 70 6e 43 6f 6e 74 65  ;.      *pnConte
3820: 6e 74 20 3d 20 69 3b 0a 20 20 20 20 20 20 69 20  nt = i;.      i 
3830: 2b 3d 20 6e 42 6f 75 6e 64 72 79 3b 0a 20 20 20  += nBoundry;.   
3840: 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 7d 0a     break;.    }.
3850: 20 20 7d 0a 20 20 2a 70 7a 20 3d 20 26 7a 5b 69    }.  *pz = &z[i
3860: 5d 3b 0a 20 20 67 65 74 5f 6c 69 6e 65 5f 66 72  ];.  get_line_fr
3870: 6f 6d 5f 73 74 72 69 6e 67 28 70 7a 2c 20 70 4c  om_string(pz, pL
3880: 65 6e 29 3b 0a 20 20 72 65 74 75 72 6e 20 7a 3b  en);.  return z;
3890: 20 20 20 20 20 20 0a 7d 0a 0a 2f 2a 0a 2a 2a 20        .}../*.** 
38a0: 54 6f 6b 65 6e 69 7a 65 20 61 20 6c 69 6e 65 20  Tokenize a line 
38b0: 6f 66 20 74 65 78 74 20 69 6e 74 6f 20 61 73 20  of text into as 
38c0: 6d 61 6e 79 20 61 73 20 6e 41 72 67 20 74 6f 6b  many as nArg tok
38d0: 65 6e 73 2e 20 20 4d 61 6b 65 0a 2a 2a 20 61 7a  ens.  Make.** az
38e0: 41 72 67 5b 5d 20 70 6f 69 6e 74 20 74 6f 20 74  Arg[] point to t
38f0: 68 65 20 73 74 61 72 74 20 6f 66 20 65 61 63 68  he start of each
3900: 20 74 6f 6b 65 6e 2e 0a 2a 2a 0a 2a 2a 20 54 6f   token..**.** To
3910: 6b 65 6e 73 20 63 6f 6e 73 69 73 74 20 6f 66 20  kens consist of 
3920: 73 70 61 63 65 20 6f 72 20 73 65 6d 69 2d 63 6f  space or semi-co
3930: 6c 6f 6e 20 64 65 6c 69 6d 69 74 65 64 20 77 6f  lon delimited wo
3940: 72 64 73 20 6f 72 0a 2a 2a 20 73 74 72 69 6e 67  rds or.** string
3950: 73 20 69 6e 73 69 64 65 20 64 6f 75 62 6c 65 2d  s inside double-
3960: 71 75 6f 74 65 73 2e 20 20 45 78 61 6d 70 6c 65  quotes.  Example
3970: 3a 0a 2a 2a 0a 2a 2a 20 20 20 20 63 6f 6e 74 65  :.**.**    conte
3980: 6e 74 2d 64 69 73 70 6f 73 69 74 69 6f 6e 3a 20  nt-disposition: 
3990: 66 6f 72 6d 2d 64 61 74 61 3b 20 6e 61 6d 65 3d  form-data; name=
39a0: 22 66 6e 22 3b 20 66 69 6c 65 6e 61 6d 65 3d 22  "fn"; filename="
39b0: 69 6e 64 65 78 2e 68 74 6d 6c 22 0a 2a 2a 0a 2a  index.html".**.*
39c0: 2a 20 54 68 65 20 6c 69 6e 65 20 61 62 6f 76 65  * The line above
39d0: 20 69 73 20 74 6f 6b 65 6e 69 7a 65 64 20 61 73   is tokenized as
39e0: 20 66 6f 6c 6c 6f 77 73 3a 0a 2a 2a 0a 2a 2a 20   follows:.**.** 
39f0: 20 20 20 61 7a 41 72 67 5b 30 5d 20 3d 20 22 63     azArg[0] = "c
3a00: 6f 6e 74 65 6e 74 2d 64 69 73 70 6f 73 69 74 69  ontent-dispositi
3a10: 6f 6e 3a 22 0a 2a 2a 20 20 20 20 61 7a 41 72 67  on:".**    azArg
3a20: 5b 31 5d 20 3d 20 22 66 6f 72 6d 2d 64 61 74 61  [1] = "form-data
3a30: 22 0a 2a 2a 20 20 20 20 61 7a 41 72 67 5b 32 5d  ".**    azArg[2]
3a40: 20 3d 20 22 6e 61 6d 65 3d 22 0a 2a 2a 20 20 20   = "name=".**   
3a50: 20 61 7a 41 72 67 5b 33 5d 20 3d 20 22 66 6e 22   azArg[3] = "fn"
3a60: 0a 2a 2a 20 20 20 20 61 7a 41 72 67 5b 34 5d 20  .**    azArg[4] 
3a70: 3d 20 22 66 69 6c 65 6e 61 6d 65 3d 22 0a 2a 2a  = "filename=".**
3a80: 20 20 20 20 61 7a 41 72 67 5b 35 5d 20 3d 20 22      azArg[5] = "
3a90: 69 6e 64 65 78 2e 68 74 6d 6c 22 0a 2a 2a 20 20  index.html".**  
3aa0: 20 20 61 7a 41 72 67 5b 36 5d 20 3d 20 30 3b 0a    azArg[6] = 0;.
3ab0: 2a 2a 0a 2a 2a 20 27 5c 30 30 30 27 20 63 68 61  **.** '\000' cha
3ac0: 72 61 63 74 65 72 73 20 61 72 65 20 69 6e 73 65  racters are inse
3ad0: 72 74 65 64 20 69 6e 20 7a 5b 5d 20 61 74 20 74  rted in z[] at t
3ae0: 68 65 20 65 6e 64 20 6f 66 20 65 61 63 68 20 74  he end of each t
3af0: 6f 6b 65 6e 2e 0a 2a 2a 20 54 68 69 73 20 72 6f  oken..** This ro
3b00: 75 74 69 6e 65 20 72 65 74 75 72 6e 73 20 74 68  utine returns th
3b10: 65 20 74 6f 74 61 6c 20 6e 75 6d 62 65 72 20 6f  e total number o
3b20: 66 20 74 6f 6b 65 6e 73 20 6f 6e 20 74 68 65 20  f tokens on the 
3b30: 6c 69 6e 65 2c 20 36 0a 2a 2a 20 69 6e 20 74 68  line, 6.** in th
3b40: 65 20 65 78 61 6d 70 6c 65 20 61 62 6f 76 65 2e  e example above.
3b50: 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 74  .*/.static int t
3b60: 6f 6b 65 6e 69 7a 65 5f 6c 69 6e 65 28 63 68 61  okenize_line(cha
3b70: 72 20 2a 7a 2c 20 69 6e 74 20 6d 78 41 72 67 2c  r *z, int mxArg,
3b80: 20 63 68 61 72 20 2a 2a 61 7a 41 72 67 29 7b 0a   char **azArg){.
3b90: 20 20 69 6e 74 20 69 20 3d 20 30 3b 0a 20 20 77    int i = 0;.  w
3ba0: 68 69 6c 65 28 20 2a 7a 20 29 7b 0a 20 20 20 20  hile( *z ){.    
3bb0: 77 68 69 6c 65 28 20 69 73 73 70 61 63 65 28 2a  while( isspace(*
3bc0: 7a 29 20 7c 7c 20 2a 7a 3d 3d 27 3b 27 20 29 7b  z) || *z==';' ){
3bd0: 20 7a 2b 2b 3b 20 7d 0a 20 20 20 20 69 66 28 20   z++; }.    if( 
3be0: 2a 7a 3d 3d 27 22 27 20 26 26 20 7a 5b 31 5d 20  *z=='"' && z[1] 
3bf0: 29 7b 0a 20 20 20 20 20 20 2a 7a 20 3d 20 30 3b  ){.      *z = 0;
3c00: 0a 20 20 20 20 20 20 7a 2b 2b 3b 0a 20 20 20 20  .      z++;.    
3c10: 20 20 69 66 28 20 69 3c 6d 78 41 72 67 2d 31 20    if( i<mxArg-1 
3c20: 29 7b 20 61 7a 41 72 67 5b 69 2b 2b 5d 20 3d 20  ){ azArg[i++] = 
3c30: 7a 3b 20 7d 0a 20 20 20 20 20 20 77 68 69 6c 65  z; }.      while
3c40: 28 20 2a 7a 20 26 26 20 2a 7a 21 3d 27 22 27 20  ( *z && *z!='"' 
3c50: 29 7b 20 7a 2b 2b 3b 20 7d 0a 20 20 20 20 20 20  ){ z++; }.      
3c60: 69 66 28 20 2a 7a 3d 3d 30 20 29 20 62 72 65 61  if( *z==0 ) brea
3c70: 6b 3b 0a 20 20 20 20 20 20 2a 7a 20 3d 20 30 3b  k;.      *z = 0;
3c80: 0a 20 20 20 20 20 20 7a 2b 2b 3b 0a 20 20 20 20  .      z++;.    
3c90: 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 69 66 28  }else{.      if(
3ca0: 20 69 3c 6d 78 41 72 67 2d 31 20 29 7b 20 61 7a   i<mxArg-1 ){ az
3cb0: 41 72 67 5b 69 2b 2b 5d 20 3d 20 7a 3b 20 7d 0a  Arg[i++] = z; }.
3cc0: 20 20 20 20 20 20 77 68 69 6c 65 28 20 2a 7a 20        while( *z 
3cd0: 26 26 20 21 69 73 73 70 61 63 65 28 2a 7a 29 20  && !isspace(*z) 
3ce0: 26 26 20 2a 7a 21 3d 27 3b 27 20 26 26 20 2a 7a  && *z!=';' && *z
3cf0: 21 3d 27 22 27 20 29 7b 20 7a 2b 2b 3b 20 7d 0a  !='"' ){ z++; }.
3d00: 20 20 20 20 20 20 69 66 28 20 2a 7a 20 26 26 20        if( *z && 
3d10: 2a 7a 21 3d 27 22 27 20 29 7b 0a 20 20 20 20 20  *z!='"' ){.     
3d20: 20 20 20 2a 7a 20 3d 20 30 3b 0a 20 20 20 20 20     *z = 0;.     
3d30: 20 20 20 7a 2b 2b 3b 0a 20 20 20 20 20 20 7d 0a     z++;.      }.
3d40: 20 20 20 20 7d 0a 20 20 7d 0a 20 20 61 7a 41 72      }.  }.  azAr
3d50: 67 5b 69 5d 20 3d 20 30 3b 0a 20 20 72 65 74 75  g[i] = 0;.  retu
3d60: 72 6e 20 69 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 53  rn i;.}../*.** S
3d70: 63 61 6e 20 74 68 65 20 6d 75 6c 74 69 70 61 72  can the multipar
3d80: 74 2d 66 6f 72 6d 20 63 6f 6e 74 65 6e 74 20 61  t-form content a
3d90: 6e 64 20 6d 61 6b 65 20 61 70 70 72 6f 70 72 69  nd make appropri
3da0: 61 74 65 20 65 6e 74 72 69 65 73 0a 2a 2a 20 69  ate entries.** i
3db0: 6e 74 6f 20 74 68 65 20 70 61 72 61 6d 65 74 65  nto the paramete
3dc0: 72 20 74 61 62 6c 65 2e 0a 2a 2a 0a 2a 2a 20 54  r table..**.** T
3dd0: 68 65 20 63 6f 6e 74 65 6e 74 20 73 74 72 69 6e  he content strin
3de0: 67 20 22 7a 22 20 69 73 20 6d 6f 64 69 66 69 65  g "z" is modifie
3df0: 64 20 62 79 20 74 68 69 73 20 72 6f 75 74 69 6e  d by this routin
3e00: 65 20 62 75 74 20 69 74 20 69 73 0a 2a 2a 20 6e  e but it is.** n
3e10: 6f 74 20 63 6f 70 69 65 64 2e 20 20 54 68 65 20  ot copied.  The 
3e20: 63 61 6c 6c 69 6e 67 20 66 75 6e 63 74 69 6f 6e  calling function
3e30: 20 6d 75 73 74 20 6e 6f 74 20 64 65 61 6c 6c 6f   must not deallo
3e40: 63 61 74 65 20 6f 72 20 6d 6f 64 69 66 79 0a 2a  cate or modify.*
3e50: 2a 20 22 7a 22 20 61 66 74 65 72 20 74 68 69 73  * "z" after this
3e60: 20 72 6f 75 74 69 6e 65 20 66 69 6e 69 73 68 65   routine finishe
3e70: 73 20 6f 72 20 69 74 20 63 6f 75 6c 64 20 63 6f  s or it could co
3e80: 72 72 75 70 74 20 74 68 65 20 70 61 72 61 6d 65  rrupt the parame
3e90: 74 65 72 0a 2a 2a 20 74 61 62 6c 65 2e 0a 2a 2f  ter.** table..*/
3ea0: 0a 73 74 61 74 69 63 20 76 6f 69 64 20 70 72 6f  .static void pro
3eb0: 63 65 73 73 5f 6d 75 6c 74 69 70 61 72 74 5f 66  cess_multipart_f
3ec0: 6f 72 6d 5f 64 61 74 61 28 63 68 61 72 20 2a 7a  orm_data(char *z
3ed0: 2c 20 69 6e 74 20 6c 65 6e 29 7b 0a 20 20 63 68  , int len){.  ch
3ee0: 61 72 20 2a 7a 4c 69 6e 65 3b 0a 20 20 69 6e 74  ar *zLine;.  int
3ef0: 20 6e 41 72 67 2c 20 69 3b 0a 20 20 63 68 61 72   nArg, i;.  char
3f00: 20 2a 7a 42 6f 75 6e 64 72 79 3b 0a 20 20 63 68   *zBoundry;.  ch
3f10: 61 72 20 2a 7a 56 61 6c 75 65 3b 0a 20 20 63 68  ar *zValue;.  ch
3f20: 61 72 20 2a 7a 4e 61 6d 65 20 3d 20 30 3b 0a 20  ar *zName = 0;. 
3f30: 20 69 6e 74 20 73 68 6f 77 42 79 74 65 73 20 3d   int showBytes =
3f40: 20 30 3b 0a 20 20 63 68 61 72 20 2a 61 7a 41 72   0;.  char *azAr
3f50: 67 5b 35 30 5d 3b 0a 0a 20 20 7a 42 6f 75 6e 64  g[50];..  zBound
3f60: 72 79 20 3d 20 67 65 74 5f 6c 69 6e 65 5f 66 72  ry = get_line_fr
3f70: 6f 6d 5f 73 74 72 69 6e 67 28 26 7a 2c 20 26 6c  om_string(&z, &l
3f80: 65 6e 29 3b 0a 20 20 69 66 28 20 7a 42 6f 75 6e  en);.  if( zBoun
3f90: 64 72 79 3d 3d 30 20 29 20 72 65 74 75 72 6e 3b  dry==0 ) return;
3fa0: 0a 20 20 77 68 69 6c 65 28 20 28 7a 4c 69 6e 65  .  while( (zLine
3fb0: 20 3d 20 67 65 74 5f 6c 69 6e 65 5f 66 72 6f 6d   = get_line_from
3fc0: 5f 73 74 72 69 6e 67 28 26 7a 2c 20 26 6c 65 6e  _string(&z, &len
3fd0: 29 29 21 3d 30 20 29 7b 0a 20 20 20 20 69 66 28  ))!=0 ){.    if(
3fe0: 20 7a 4c 69 6e 65 5b 30 5d 3d 3d 30 20 29 7b 0a   zLine[0]==0 ){.
3ff0: 20 20 20 20 20 20 69 6e 74 20 6e 43 6f 6e 74 65        int nConte
4000: 6e 74 20 3d 20 30 3b 0a 20 20 20 20 20 20 7a 56  nt = 0;.      zV
4010: 61 6c 75 65 20 3d 20 67 65 74 5f 62 6f 75 6e 64  alue = get_bound
4020: 65 64 5f 63 6f 6e 74 65 6e 74 28 26 7a 2c 20 26  ed_content(&z, &
4030: 6c 65 6e 2c 20 7a 42 6f 75 6e 64 72 79 2c 20 26  len, zBoundry, &
4040: 6e 43 6f 6e 74 65 6e 74 29 3b 0a 20 20 20 20 20  nContent);.     
4050: 20 69 66 28 20 7a 4e 61 6d 65 20 26 26 20 7a 56   if( zName && zV
4060: 61 6c 75 65 20 26 26 20 69 73 6c 6f 77 65 72 28  alue && islower(
4070: 7a 4e 61 6d 65 5b 30 5d 29 20 29 7b 0a 20 20 20  zName[0]) ){.   
4080: 20 20 20 20 20 63 67 69 5f 73 65 74 5f 70 61 72       cgi_set_par
4090: 61 6d 65 74 65 72 5f 6e 6f 63 6f 70 79 28 7a 4e  ameter_nocopy(zN
40a0: 61 6d 65 2c 20 7a 56 61 6c 75 65 29 3b 0a 20 20  ame, zValue);.  
40b0: 20 20 20 20 20 20 69 66 28 20 73 68 6f 77 42 79        if( showBy
40c0: 74 65 73 20 29 7b 0a 20 20 20 20 20 20 20 20 20  tes ){.         
40d0: 20 63 67 69 5f 73 65 74 5f 70 61 72 61 6d 65 74   cgi_set_paramet
40e0: 65 72 5f 6e 6f 63 6f 70 79 28 6d 70 72 69 6e 74  er_nocopy(mprint
40f0: 66 28 22 25 73 3a 62 79 74 65 73 22 2c 20 7a 4e  f("%s:bytes", zN
4100: 61 6d 65 29 2c 0a 20 20 20 20 20 20 20 20 20 20  ame),.          
4110: 20 20 20 20 20 6d 70 72 69 6e 74 66 28 22 25 64       mprintf("%d
4120: 22 2c 6e 43 6f 6e 74 65 6e 74 29 29 3b 0a 20 20  ",nContent));.  
4130: 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 7d 0a        }.      }.
4140: 20 20 20 20 20 20 7a 4e 61 6d 65 20 3d 20 30 3b        zName = 0;
4150: 0a 20 20 20 20 20 20 73 68 6f 77 42 79 74 65 73  .      showBytes
4160: 20 3d 20 30 3b 0a 20 20 20 20 7d 65 6c 73 65 7b   = 0;.    }else{
4170: 0a 20 20 20 20 20 20 6e 41 72 67 20 3d 20 74 6f  .      nArg = to
4180: 6b 65 6e 69 7a 65 5f 6c 69 6e 65 28 7a 4c 69 6e  kenize_line(zLin
4190: 65 2c 20 73 69 7a 65 6f 66 28 61 7a 41 72 67 29  e, sizeof(azArg)
41a0: 2f 73 69 7a 65 6f 66 28 61 7a 41 72 67 5b 30 5d  /sizeof(azArg[0]
41b0: 29 2c 20 61 7a 41 72 67 29 3b 0a 20 20 20 20 20  ), azArg);.     
41c0: 20 66 6f 72 28 69 3d 30 3b 20 69 3c 6e 41 72 67   for(i=0; i<nArg
41d0: 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 20 20 20 20  ; i++){.        
41e0: 69 6e 74 20 63 20 3d 20 74 6f 6c 6f 77 65 72 28  int c = tolower(
41f0: 61 7a 41 72 67 5b 69 5d 5b 30 5d 29 3b 0a 20 20  azArg[i][0]);.  
4200: 20 20 20 20 20 20 69 66 28 20 63 3d 3d 27 63 27        if( c=='c'
4210: 20 26 26 20 73 74 72 69 63 6d 70 28 61 7a 41 72   && stricmp(azAr
4220: 67 5b 69 5d 2c 22 63 6f 6e 74 65 6e 74 2d 64 69  g[i],"content-di
4230: 73 70 6f 73 69 74 69 6f 6e 3a 22 29 3d 3d 30 20  sposition:")==0 
4240: 29 7b 0a 20 20 20 20 20 20 20 20 20 20 69 2b 2b  ){.          i++
4250: 3b 0a 20 20 20 20 20 20 20 20 7d 65 6c 73 65 20  ;.        }else 
4260: 69 66 28 20 63 3d 3d 27 6e 27 20 26 26 20 73 74  if( c=='n' && st
4270: 72 69 63 6d 70 28 61 7a 41 72 67 5b 69 5d 2c 22  ricmp(azArg[i],"
4280: 6e 61 6d 65 3d 22 29 3d 3d 30 20 29 7b 0a 20 20  name=")==0 ){.  
4290: 20 20 20 20 20 20 20 20 7a 4e 61 6d 65 20 3d 20          zName = 
42a0: 61 7a 41 72 67 5b 2b 2b 69 5d 3b 0a 20 20 20 20  azArg[++i];.    
42b0: 20 20 20 20 7d 65 6c 73 65 20 69 66 28 20 63 3d      }else if( c=
42c0: 3d 27 66 27 20 26 26 20 73 74 72 69 63 6d 70 28  ='f' && stricmp(
42d0: 61 7a 41 72 67 5b 69 5d 2c 22 66 69 6c 65 6e 61  azArg[i],"filena
42e0: 6d 65 3d 22 29 3d 3d 30 20 29 7b 0a 20 20 20 20  me=")==0 ){.    
42f0: 20 20 20 20 20 20 63 68 61 72 20 2a 7a 20 3d 20        char *z = 
4300: 61 7a 41 72 67 5b 2b 2b 69 5d 3b 0a 20 20 20 20  azArg[++i];.    
4310: 20 20 20 20 20 20 69 66 28 20 7a 4e 61 6d 65 20        if( zName 
4320: 26 26 20 7a 20 26 26 20 69 73 6c 6f 77 65 72 28  && z && islower(
4330: 7a 4e 61 6d 65 5b 30 5d 29 20 29 7b 0a 20 20 20  zName[0]) ){.   
4340: 20 20 20 20 20 20 20 20 20 63 67 69 5f 73 65 74           cgi_set
4350: 5f 70 61 72 61 6d 65 74 65 72 5f 6e 6f 63 6f 70  _parameter_nocop
4360: 79 28 6d 70 72 69 6e 74 66 28 22 25 73 3a 66 69  y(mprintf("%s:fi
4370: 6c 65 6e 61 6d 65 22 2c 7a 4e 61 6d 65 29 2c 20  lename",zName), 
4380: 7a 29 3b 0a 20 20 20 20 20 20 20 20 20 20 7d 0a  z);.          }.
4390: 20 20 20 20 20 20 20 20 20 20 73 68 6f 77 42 79            showBy
43a0: 74 65 73 20 3d 20 31 3b 0a 20 20 20 20 20 20 20  tes = 1;.       
43b0: 20 7d 65 6c 73 65 20 69 66 28 20 63 3d 3d 27 63   }else if( c=='c
43c0: 27 20 26 26 20 73 74 72 69 63 6d 70 28 61 7a 41  ' && stricmp(azA
43d0: 72 67 5b 69 5d 2c 22 63 6f 6e 74 65 6e 74 2d 74  rg[i],"content-t
43e0: 79 70 65 3a 22 29 3d 3d 30 20 29 7b 0a 20 20 20  ype:")==0 ){.   
43f0: 20 20 20 20 20 20 20 63 68 61 72 20 2a 7a 20 3d         char *z =
4400: 20 61 7a 41 72 67 5b 2b 2b 69 5d 3b 0a 20 20 20   azArg[++i];.   
4410: 20 20 20 20 20 20 20 69 66 28 20 7a 4e 61 6d 65         if( zName
4420: 20 26 26 20 7a 20 26 26 20 69 73 6c 6f 77 65 72   && z && islower
4430: 28 7a 4e 61 6d 65 5b 30 5d 29 20 29 7b 0a 20 20  (zName[0]) ){.  
4440: 20 20 20 20 20 20 20 20 20 20 63 67 69 5f 73 65            cgi_se
4450: 74 5f 70 61 72 61 6d 65 74 65 72 5f 6e 6f 63 6f  t_parameter_noco
4460: 70 79 28 6d 70 72 69 6e 74 66 28 22 25 73 3a 6d  py(mprintf("%s:m
4470: 69 6d 65 74 79 70 65 22 2c 7a 4e 61 6d 65 29 2c  imetype",zName),
4480: 20 7a 29 3b 0a 20 20 20 20 20 20 20 20 20 20 7d   z);.          }
4490: 0a 20 20 20 20 20 20 20 20 7d 0a 20 20 20 20 20  .        }.     
44a0: 20 7d 0a 20 20 20 20 7d 0a 20 20 7d 20 20 20 20   }.    }.  }    
44b0: 20 20 20 20 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 49 6e      .}../*.** In
44c0: 69 74 69 61 6c 69 7a 65 20 74 68 65 20 71 75 65  itialize the que
44d0: 72 79 20 70 61 72 61 6d 65 74 65 72 20 64 61 74  ry parameter dat
44e0: 61 62 61 73 65 2e 20 20 49 6e 66 6f 72 6d 61 74  abase.  Informat
44f0: 69 6f 6e 20 69 73 20 70 75 6c 6c 65 64 20 66 72  ion is pulled fr
4500: 6f 6d 0a 2a 2a 20 74 68 65 20 51 55 45 52 59 5f  om.** the QUERY_
4510: 53 54 52 49 4e 47 20 65 6e 76 69 72 6f 6e 6d 65  STRING environme
4520: 6e 74 20 76 61 72 69 61 62 6c 65 20 28 69 66 20  nt variable (if 
4530: 69 74 20 65 78 69 73 74 73 29 2c 20 66 72 6f 6d  it exists), from
4540: 20 73 74 61 6e 64 61 72 64 0a 2a 2a 20 69 6e 70   standard.** inp
4550: 75 74 20 69 66 20 74 68 65 72 65 20 69 73 20 50  ut if there is P
4560: 4f 53 54 20 64 61 74 61 2c 20 61 6e 64 20 66 72  OST data, and fr
4570: 6f 6d 20 48 54 54 50 5f 43 4f 4f 4b 49 45 2e 0a  om HTTP_COOKIE..
4580: 2a 2f 0a 76 6f 69 64 20 63 67 69 5f 69 6e 69 74  */.void cgi_init
4590: 28 76 6f 69 64 29 7b 0a 20 20 63 68 61 72 20 2a  (void){.  char *
45a0: 7a 3b 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20  z;.  const char 
45b0: 2a 7a 54 79 70 65 3b 0a 20 20 69 6e 74 20 6c 65  *zType;.  int le
45c0: 6e 3b 0a 20 20 7a 20 3d 20 28 63 68 61 72 2a 29  n;.  z = (char*)
45d0: 50 28 22 51 55 45 52 59 5f 53 54 52 49 4e 47 22  P("QUERY_STRING"
45e0: 29 3b 0a 20 20 69 66 28 20 7a 20 29 7b 0a 20 20  );.  if( z ){.  
45f0: 20 20 7a 20 3d 20 6d 70 72 69 6e 74 66 28 22 25    z = mprintf("%
4600: 73 22 2c 7a 29 3b 0a 20 20 20 20 61 64 64 5f 70  s",z);.    add_p
4610: 61 72 61 6d 5f 6c 69 73 74 28 7a 2c 20 27 26 27  aram_list(z, '&'
4620: 29 3b 0a 20 20 7d 0a 0a 20 20 6c 65 6e 20 3d 20  );.  }..  len = 
4630: 61 74 6f 69 28 50 44 28 22 43 4f 4e 54 45 4e 54  atoi(PD("CONTENT
4640: 5f 4c 45 4e 47 54 48 22 2c 20 22 30 22 29 29 3b  _LENGTH", "0"));
4650: 0a 20 20 67 2e 7a 43 6f 6e 74 65 6e 74 54 79 70  .  g.zContentTyp
4660: 65 20 3d 20 7a 54 79 70 65 20 3d 20 50 28 22 43  e = zType = P("C
4670: 4f 4e 54 45 4e 54 5f 54 59 50 45 22 29 3b 0a 20  ONTENT_TYPE");. 
4680: 20 69 66 28 20 6c 65 6e 3e 30 20 26 26 20 7a 54   if( len>0 && zT
4690: 79 70 65 20 29 7b 0a 20 20 20 20 62 6c 6f 62 5f  ype ){.    blob_
46a0: 7a 65 72 6f 28 26 67 2e 63 67 69 49 6e 29 3b 0a  zero(&g.cgiIn);.
46b0: 20 20 20 20 69 66 28 20 73 74 72 63 6d 70 28 7a      if( strcmp(z
46c0: 54 79 70 65 2c 22 61 70 70 6c 69 63 61 74 69 6f  Type,"applicatio
46d0: 6e 2f 78 2d 77 77 77 2d 66 6f 72 6d 2d 75 72 6c  n/x-www-form-url
46e0: 65 6e 63 6f 64 65 64 22 29 3d 3d 30 20 0a 20 20  encoded")==0 .  
46f0: 20 20 20 20 20 20 20 7c 7c 20 73 74 72 6e 63 6d         || strncm
4700: 70 28 7a 54 79 70 65 2c 22 6d 75 6c 74 69 70 61  p(zType,"multipa
4710: 72 74 2f 66 6f 72 6d 2d 64 61 74 61 22 2c 31 39  rt/form-data",19
4720: 29 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 7a 20  )==0 ){.      z 
4730: 3d 20 6d 61 6c 6c 6f 63 28 20 6c 65 6e 2b 31 20  = malloc( len+1 
4740: 29 3b 0a 20 20 20 20 20 20 69 66 28 20 7a 3d 3d  );.      if( z==
4750: 30 20 29 20 65 78 69 74 28 31 29 3b 0a 20 20 20  0 ) exit(1);.   
4760: 20 20 20 6c 65 6e 20 3d 20 66 72 65 61 64 28 7a     len = fread(z
4770: 2c 20 31 2c 20 6c 65 6e 2c 20 73 74 64 69 6e 29  , 1, len, stdin)
4780: 3b 0a 20 20 20 20 20 20 7a 5b 6c 65 6e 5d 20 3d  ;.      z[len] =
4790: 20 30 3b 0a 20 20 20 20 20 20 69 66 28 20 7a 54   0;.      if( zT
47a0: 79 70 65 5b 30 5d 3d 3d 27 61 27 20 29 7b 0a 20  ype[0]=='a' ){. 
47b0: 20 20 20 20 20 20 20 61 64 64 5f 70 61 72 61 6d         add_param
47c0: 5f 6c 69 73 74 28 7a 2c 20 27 26 27 29 3b 0a 20  _list(z, '&');. 
47d0: 20 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20       }else{.    
47e0: 20 20 20 20 70 72 6f 63 65 73 73 5f 6d 75 6c 74      process_mult
47f0: 69 70 61 72 74 5f 66 6f 72 6d 5f 64 61 74 61 28  ipart_form_data(
4800: 7a 2c 20 6c 65 6e 29 3b 0a 20 20 20 20 20 20 7d  z, len);.      }
4810: 0a 20 20 20 20 7d 65 6c 73 65 20 69 66 28 20 73  .    }else if( s
4820: 74 72 63 6d 70 28 7a 54 79 70 65 2c 20 22 61 70  trcmp(zType, "ap
4830: 70 6c 69 63 61 74 69 6f 6e 2f 78 2d 66 6f 73 73  plication/x-foss
4840: 69 6c 22 29 3d 3d 30 20 29 7b 0a 20 20 20 20 20  il")==0 ){.     
4850: 20 62 6c 6f 62 5f 72 65 61 64 5f 66 72 6f 6d 5f   blob_read_from_
4860: 63 68 61 6e 6e 65 6c 28 26 67 2e 63 67 69 49 6e  channel(&g.cgiIn
4870: 2c 20 73 74 64 69 6e 2c 20 6c 65 6e 29 3b 0a 20  , stdin, len);. 
4880: 20 20 20 20 20 62 6c 6f 62 5f 75 6e 63 6f 6d 70       blob_uncomp
4890: 72 65 73 73 28 26 67 2e 63 67 69 49 6e 2c 20 26  ress(&g.cgiIn, &
48a0: 67 2e 63 67 69 49 6e 29 3b 0a 20 20 20 20 7d 65  g.cgiIn);.    }e
48b0: 6c 73 65 20 69 66 28 20 73 74 72 63 6d 70 28 7a  lse if( strcmp(z
48c0: 54 79 70 65 2c 20 22 61 70 70 6c 69 63 61 74 69  Type, "applicati
48d0: 6f 6e 2f 78 2d 66 6f 73 73 69 6c 2d 64 65 62 75  on/x-fossil-debu
48e0: 67 22 29 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20  g")==0 ){.      
48f0: 62 6c 6f 62 5f 72 65 61 64 5f 66 72 6f 6d 5f 63  blob_read_from_c
4900: 68 61 6e 6e 65 6c 28 26 67 2e 63 67 69 49 6e 2c  hannel(&g.cgiIn,
4910: 20 73 74 64 69 6e 2c 20 6c 65 6e 29 3b 0a 20 20   stdin, len);.  
4920: 20 20 7d 0a 20 20 7d 0a 0a 20 20 7a 20 3d 20 28    }.  }..  z = (
4930: 63 68 61 72 2a 29 50 28 22 48 54 54 50 5f 43 4f  char*)P("HTTP_CO
4940: 4f 4b 49 45 22 29 3b 0a 20 20 69 66 28 20 7a 20  OKIE");.  if( z 
4950: 29 7b 0a 20 20 20 20 7a 20 3d 20 6d 70 72 69 6e  ){.    z = mprin
4960: 74 66 28 22 25 73 22 2c 7a 29 3b 0a 20 20 20 20  tf("%s",z);.    
4970: 61 64 64 5f 70 61 72 61 6d 5f 6c 69 73 74 28 7a  add_param_list(z
4980: 2c 20 27 3b 27 29 3b 0a 20 20 7d 0a 7d 0a 0a 2f  , ';');.  }.}../
4990: 2a 0a 2a 2a 20 54 68 69 73 20 69 73 20 74 68 65  *.** This is the
49a0: 20 63 6f 6d 70 61 72 69 73 6f 6e 20 66 75 6e 63   comparison func
49b0: 74 69 6f 6e 20 75 73 65 64 20 74 6f 20 73 6f 72  tion used to sor
49c0: 74 20 74 68 65 20 61 50 61 72 61 6d 51 50 5b 5d  t the aParamQP[]
49d0: 20 61 72 72 61 79 20 6f 66 0a 2a 2a 20 71 75 65   array of.** que
49e0: 72 79 20 70 61 72 61 6d 65 74 65 72 73 20 61 6e  ry parameters an
49f0: 64 20 63 6f 6f 6b 69 65 73 2e 0a 2a 2f 0a 73 74  d cookies..*/.st
4a00: 61 74 69 63 20 69 6e 74 20 71 70 61 72 61 6d 5f  atic int qparam_
4a10: 63 6f 6d 70 61 72 65 28 63 6f 6e 73 74 20 76 6f  compare(const vo
4a20: 69 64 20 2a 61 2c 20 63 6f 6e 73 74 20 76 6f 69  id *a, const voi
4a30: 64 20 2a 62 29 7b 0a 20 20 73 74 72 75 63 74 20  d *b){.  struct 
4a40: 51 50 61 72 61 6d 20 2a 70 41 20 3d 20 28 73 74  QParam *pA = (st
4a50: 72 75 63 74 20 51 50 61 72 61 6d 2a 29 61 3b 0a  ruct QParam*)a;.
4a60: 20 20 73 74 72 75 63 74 20 51 50 61 72 61 6d 20    struct QParam 
4a70: 2a 70 42 20 3d 20 28 73 74 72 75 63 74 20 51 50  *pB = (struct QP
4a80: 61 72 61 6d 2a 29 62 3b 0a 20 20 69 6e 74 20 63  aram*)b;.  int c
4a90: 3b 0a 20 20 63 20 3d 20 73 74 72 63 6d 70 28 70  ;.  c = strcmp(p
4aa0: 41 2d 3e 7a 4e 61 6d 65 2c 20 70 42 2d 3e 7a 4e  A->zName, pB->zN
4ab0: 61 6d 65 29 3b 0a 20 20 69 66 28 20 63 3d 3d 30  ame);.  if( c==0
4ac0: 20 29 7b 0a 20 20 20 20 63 20 3d 20 70 41 2d 3e   ){.    c = pA->
4ad0: 73 65 71 20 2d 20 70 42 2d 3e 73 65 71 3b 0a 20  seq - pB->seq;. 
4ae0: 20 7d 0a 20 20 72 65 74 75 72 6e 20 63 3b 0a 7d   }.  return c;.}
4af0: 0a 0a 2f 2a 0a 2a 2a 20 52 65 74 75 72 6e 20 74  ../*.** Return t
4b00: 68 65 20 76 61 6c 75 65 20 6f 66 20 61 20 71 75  he value of a qu
4b10: 65 72 79 20 70 61 72 61 6d 65 74 65 72 20 6f 72  ery parameter or
4b20: 20 63 6f 6f 6b 69 65 20 77 68 6f 73 65 20 6e 61   cookie whose na
4b30: 6d 65 20 69 73 20 7a 4e 61 6d 65 2e 0a 2a 2a 20  me is zName..** 
4b40: 49 66 20 74 68 65 72 65 20 69 73 20 6e 6f 20 71  If there is no q
4b50: 75 65 72 79 20 70 61 72 61 6d 65 74 65 72 20 6f  uery parameter o
4b60: 72 20 63 6f 6f 6b 69 65 20 6e 61 6d 65 64 20 7a  r cookie named z
4b70: 4e 61 6d 65 20 61 6e 64 20 74 68 65 20 66 69 72  Name and the fir
4b80: 73 74 0a 2a 2a 20 63 68 61 72 61 63 74 65 72 20  st.** character 
4b90: 6f 66 20 7a 4e 61 6d 65 20 69 73 20 75 70 70 65  of zName is uppe
4ba0: 72 63 61 73 65 2c 20 74 68 65 6e 20 63 68 65 63  rcase, then chec
4bb0: 6b 20 74 6f 20 73 65 65 20 69 66 20 74 68 65 72  k to see if ther
4bc0: 65 20 69 73 20 61 6e 0a 2a 2a 20 65 6e 76 69 72  e is an.** envir
4bd0: 6f 6e 6d 65 6e 74 20 76 61 72 69 61 62 6c 65 20  onment variable 
4be0: 62 79 20 74 68 61 74 20 6e 61 6d 65 20 61 6e 64  by that name and
4bf0: 20 72 65 74 75 72 6e 20 69 74 20 69 66 20 74 68   return it if th
4c00: 65 72 65 20 69 73 2e 20 20 41 73 0a 2a 2a 20 61  ere is.  As.** a
4c10: 20 6c 61 73 74 20 72 65 73 6f 72 74 20 77 68 65   last resort whe
4c20: 6e 20 6e 6f 74 68 69 6e 67 20 65 6c 73 65 20 6d  n nothing else m
4c30: 61 74 63 68 65 73 2c 20 72 65 74 75 72 6e 20 7a  atches, return z
4c40: 44 65 66 61 75 6c 74 2e 0a 2a 2f 0a 63 6f 6e 73  Default..*/.cons
4c50: 74 20 63 68 61 72 20 2a 63 67 69 5f 70 61 72 61  t char *cgi_para
4c60: 6d 65 74 65 72 28 63 6f 6e 73 74 20 63 68 61 72  meter(const char
4c70: 20 2a 7a 4e 61 6d 65 2c 20 63 6f 6e 73 74 20 63   *zName, const c
4c80: 68 61 72 20 2a 7a 44 65 66 61 75 6c 74 29 7b 0a  har *zDefault){.
4c90: 20 20 69 6e 74 20 6c 6f 2c 20 68 69 2c 20 6d 69    int lo, hi, mi
4ca0: 64 2c 20 63 3b 0a 0a 20 20 2f 2a 20 54 68 65 20  d, c;..  /* The 
4cb0: 73 6f 72 74 51 50 20 66 6c 61 67 20 69 73 20 73  sortQP flag is s
4cc0: 65 74 20 77 68 65 6e 65 76 65 72 20 61 20 6e 65  et whenever a ne
4cd0: 77 20 71 75 65 72 79 20 70 61 72 61 6d 65 74 65  w query paramete
4ce0: 72 20 69 73 20 69 6e 73 65 72 74 65 64 2e 0a 20  r is inserted.. 
4cf0: 20 2a 2a 20 49 74 20 69 6e 64 69 63 61 74 65 73   ** It indicates
4d00: 20 74 68 61 74 20 77 65 20 6e 65 65 64 20 74 6f   that we need to
4d10: 20 72 65 73 6f 72 74 20 74 68 65 20 71 75 65 72   resort the quer
4d20: 79 20 70 61 72 61 6d 65 74 65 72 73 2e 0a 20 20  y parameters..  
4d30: 2a 2f 0a 20 20 69 66 28 20 73 6f 72 74 51 50 20  */.  if( sortQP 
4d40: 29 7b 0a 20 20 20 20 69 6e 74 20 69 2c 20 6a 3b  ){.    int i, j;
4d50: 0a 20 20 20 20 71 73 6f 72 74 28 61 50 61 72 61  .    qsort(aPara
4d60: 6d 51 50 2c 20 6e 55 73 65 64 51 50 2c 20 73 69  mQP, nUsedQP, si
4d70: 7a 65 6f 66 28 61 50 61 72 61 6d 51 50 5b 30 5d  zeof(aParamQP[0]
4d80: 29 2c 20 71 70 61 72 61 6d 5f 63 6f 6d 70 61 72  ), qparam_compar
4d90: 65 29 3b 0a 20 20 20 20 73 6f 72 74 51 50 20 3d  e);.    sortQP =
4da0: 20 30 3b 0a 20 20 20 20 2f 2a 20 41 66 74 65 72   0;.    /* After
4db0: 20 73 6f 72 74 69 6e 67 2c 20 72 65 6d 6f 76 65   sorting, remove
4dc0: 20 64 75 70 6c 69 63 61 74 65 20 70 61 72 61 6d   duplicate param
4dd0: 65 74 65 72 73 2e 20 20 54 68 65 20 73 65 63 6f  eters.  The seco
4de0: 6e 64 61 72 79 20 73 6f 72 74 0a 20 20 20 20 2a  ndary sort.    *
4df0: 2a 20 6b 65 79 20 69 73 20 61 50 61 72 61 6d 51  * key is aParamQ
4e00: 50 5b 5d 2e 73 65 71 20 61 6e 64 20 77 65 20 6b  P[].seq and we k
4e10: 65 65 70 20 74 68 65 20 66 69 72 73 74 20 65 6e  eep the first en
4e20: 74 72 79 2e 20 20 54 68 61 74 20 6d 65 61 6e 73  try.  That means
4e30: 0a 20 20 20 20 2a 2a 20 77 69 74 68 20 64 75 70  .    ** with dup
4e40: 6c 69 63 61 74 65 20 63 61 6c 6c 73 20 74 6f 20  licate calls to 
4e50: 63 67 69 5f 73 65 74 5f 70 61 72 61 6d 65 74 65  cgi_set_paramete
4e60: 72 28 29 20 74 68 65 20 73 65 63 6f 6e 64 20 61  r() the second a
4e70: 6e 64 0a 20 20 20 20 2a 2a 20 73 75 62 73 65 71  nd.    ** subseq
4e80: 75 65 6e 74 20 63 61 6c 6c 73 20 61 72 65 20 65  uent calls are e
4e90: 66 66 65 63 74 69 76 65 6c 79 20 6e 6f 2d 6f 70  ffectively no-op
4ea0: 73 2e 20 2a 2f 0a 20 20 20 20 66 6f 72 28 69 3d  s. */.    for(i=
4eb0: 6a 3d 31 3b 20 69 3c 6e 55 73 65 64 51 50 3b 20  j=1; i<nUsedQP; 
4ec0: 69 2b 2b 29 7b 0a 20 20 20 20 20 20 69 66 28 20  i++){.      if( 
4ed0: 73 74 72 63 6d 70 28 61 50 61 72 61 6d 51 50 5b  strcmp(aParamQP[
4ee0: 69 5d 2e 7a 4e 61 6d 65 2c 61 50 61 72 61 6d 51  i].zName,aParamQ
4ef0: 50 5b 69 2d 31 5d 2e 7a 4e 61 6d 65 29 3d 3d 30  P[i-1].zName)==0
4f00: 20 29 7b 0a 20 20 20 20 20 20 20 20 63 6f 6e 74   ){.        cont
4f10: 69 6e 75 65 3b 0a 20 20 20 20 20 20 7d 0a 20 20  inue;.      }.  
4f20: 20 20 20 20 69 66 28 20 6a 3c 69 20 29 7b 0a 20      if( j<i ){. 
4f30: 20 20 20 20 20 20 20 6d 65 6d 63 70 79 28 26 61         memcpy(&a
4f40: 50 61 72 61 6d 51 50 5b 6a 5d 2c 20 26 61 50 61  ParamQP[j], &aPa
4f50: 72 61 6d 51 50 5b 69 5d 2c 20 73 69 7a 65 6f 66  ramQP[i], sizeof
4f60: 28 61 50 61 72 61 6d 51 50 5b 6a 5d 29 29 3b 0a  (aParamQP[j]));.
4f70: 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 6a 2b        }.      j+
4f80: 2b 3b 0a 20 20 20 20 7d 0a 20 20 20 20 6e 55 73  +;.    }.    nUs
4f90: 65 64 51 50 20 3d 20 6a 3b 0a 20 20 7d 0a 0a 20  edQP = j;.  }.. 
4fa0: 20 2f 2a 20 44 6f 20 61 20 62 69 6e 61 72 79 20   /* Do a binary 
4fb0: 73 65 61 72 63 68 20 66 6f 72 20 61 20 6d 61 74  search for a mat
4fc0: 63 68 69 6e 67 20 71 75 65 72 79 20 70 61 72 61  ching query para
4fd0: 6d 65 74 65 72 20 2a 2f 0a 20 20 6c 6f 20 3d 20  meter */.  lo = 
4fe0: 30 3b 0a 20 20 68 69 20 3d 20 6e 55 73 65 64 51  0;.  hi = nUsedQ
4ff0: 50 2d 31 3b 0a 20 20 77 68 69 6c 65 28 20 6c 6f  P-1;.  while( lo
5000: 3c 3d 68 69 20 29 7b 0a 20 20 20 20 6d 69 64 20  <=hi ){.    mid 
5010: 3d 20 28 6c 6f 2b 68 69 29 2f 32 3b 0a 20 20 20  = (lo+hi)/2;.   
5020: 20 63 20 3d 20 73 74 72 63 6d 70 28 61 50 61 72   c = strcmp(aPar
5030: 61 6d 51 50 5b 6d 69 64 5d 2e 7a 4e 61 6d 65 2c  amQP[mid].zName,
5040: 20 7a 4e 61 6d 65 29 3b 0a 20 20 20 20 69 66 28   zName);.    if(
5050: 20 63 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 43   c==0 ){.      C
5060: 47 49 44 45 42 55 47 28 28 22 6d 65 6d 2d 6d 61  GIDEBUG(("mem-ma
5070: 74 63 68 20 5b 25 73 5d 20 3d 20 5b 25 73 5d 5c  tch [%s] = [%s]\
5080: 6e 22 2c 20 7a 4e 61 6d 65 2c 20 61 50 61 72 61  n", zName, aPara
5090: 6d 51 50 5b 6d 69 64 5d 2e 7a 56 61 6c 75 65 29  mQP[mid].zValue)
50a0: 29 3b 0a 20 20 20 20 20 20 72 65 74 75 72 6e 20  );.      return 
50b0: 61 50 61 72 61 6d 51 50 5b 6d 69 64 5d 2e 7a 56  aParamQP[mid].zV
50c0: 61 6c 75 65 3b 0a 20 20 20 20 7d 65 6c 73 65 20  alue;.    }else 
50d0: 69 66 28 20 63 3e 30 20 29 7b 0a 20 20 20 20 20  if( c>0 ){.     
50e0: 20 68 69 20 3d 20 6d 69 64 2d 31 3b 0a 20 20 20   hi = mid-1;.   
50f0: 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 6c 6f   }else{.      lo
5100: 20 3d 20 6d 69 64 2b 31 3b 0a 20 20 20 20 7d 0a   = mid+1;.    }.
5110: 20 20 7d 0a 0a 20 20 2f 2a 20 49 66 20 6e 6f 20    }..  /* If no 
5120: 6d 61 74 63 68 20 69 73 20 66 6f 75 6e 64 20 61  match is found a
5130: 6e 64 20 74 68 65 20 6e 61 6d 65 20 62 65 67 69  nd the name begi
5140: 6e 73 20 77 69 74 68 20 61 6e 20 75 70 70 65 72  ns with an upper
5150: 2d 63 61 73 65 0a 20 20 2a 2a 20 6c 65 74 74 65  -case.  ** lette
5160: 72 2c 20 74 68 65 6e 20 63 68 65 63 6b 20 74 6f  r, then check to
5170: 20 73 65 65 20 69 66 20 74 68 65 72 65 20 69 73   see if there is
5180: 20 61 6e 20 65 6e 76 69 72 6f 6e 6d 65 6e 74 20   an environment 
5190: 76 61 72 69 61 62 6c 65 0a 20 20 2a 2a 20 77 69  variable.  ** wi
51a0: 74 68 20 74 68 65 20 67 69 76 65 6e 20 6e 61 6d  th the given nam
51b0: 65 2e 0a 20 20 2a 2f 0a 20 20 69 66 28 20 69 73  e..  */.  if( is
51c0: 75 70 70 65 72 28 7a 4e 61 6d 65 5b 30 5d 29 20  upper(zName[0]) 
51d0: 29 7b 0a 20 20 20 20 63 6f 6e 73 74 20 63 68 61  ){.    const cha
51e0: 72 20 2a 7a 56 61 6c 75 65 20 3d 20 67 65 74 65  r *zValue = gete
51f0: 6e 76 28 7a 4e 61 6d 65 29 3b 0a 20 20 20 20 69  nv(zName);.    i
5200: 66 28 20 7a 56 61 6c 75 65 20 29 7b 0a 20 20 20  f( zValue ){.   
5210: 20 20 20 63 67 69 5f 73 65 74 5f 70 61 72 61 6d     cgi_set_param
5220: 65 74 65 72 5f 6e 6f 63 6f 70 79 28 7a 4e 61 6d  eter_nocopy(zNam
5230: 65 2c 20 7a 56 61 6c 75 65 29 3b 0a 20 20 20 20  e, zValue);.    
5240: 20 20 43 47 49 44 45 42 55 47 28 28 22 65 6e 76    CGIDEBUG(("env
5250: 2d 6d 61 74 63 68 20 5b 25 73 5d 20 3d 20 5b 25  -match [%s] = [%
5260: 73 5d 5c 6e 22 2c 20 7a 4e 61 6d 65 2c 20 7a 56  s]\n", zName, zV
5270: 61 6c 75 65 29 29 3b 0a 20 20 20 20 20 20 72 65  alue));.      re
5280: 74 75 72 6e 20 7a 56 61 6c 75 65 3b 0a 20 20 20  turn zValue;.   
5290: 20 7d 0a 20 20 7d 0a 20 20 43 47 49 44 45 42 55   }.  }.  CGIDEBU
52a0: 47 28 28 22 6e 6f 2d 6d 61 74 63 68 20 5b 25 73  G(("no-match [%s
52b0: 5d 5c 6e 22 2c 20 7a 4e 61 6d 65 29 29 3b 0a 20  ]\n", zName));. 
52c0: 20 72 65 74 75 72 6e 20 7a 44 65 66 61 75 6c 74   return zDefault
52d0: 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 50 72 69 6e 74  ;.}../*.** Print
52e0: 20 43 47 49 20 64 65 62 75 67 67 69 6e 67 20 6d   CGI debugging m
52f0: 65 73 73 61 67 65 73 2e 0a 2a 2f 0a 76 6f 69 64  essages..*/.void
5300: 20 63 67 69 5f 64 65 62 75 67 28 63 6f 6e 73 74   cgi_debug(const
5310: 20 63 68 61 72 20 2a 7a 46 6f 72 6d 61 74 2c 20   char *zFormat, 
5320: 2e 2e 2e 29 7b 0a 20 20 76 61 5f 6c 69 73 74 20  ...){.  va_list 
5330: 61 70 3b 0a 20 20 69 66 28 20 67 2e 66 44 65 62  ap;.  if( g.fDeb
5340: 75 67 20 29 7b 0a 20 20 20 20 76 61 5f 73 74 61  ug ){.    va_sta
5350: 72 74 28 61 70 2c 20 7a 46 6f 72 6d 61 74 29 3b  rt(ap, zFormat);
5360: 0a 20 20 20 20 76 66 70 72 69 6e 74 66 28 67 2e  .    vfprintf(g.
5370: 66 44 65 62 75 67 2c 20 7a 46 6f 72 6d 61 74 2c  fDebug, zFormat,
5380: 20 61 70 29 3b 0a 20 20 20 20 76 61 5f 65 6e 64   ap);.    va_end
5390: 28 61 70 29 3b 0a 20 20 20 20 66 66 6c 75 73 68  (ap);.    fflush
53a0: 28 67 2e 66 44 65 62 75 67 29 3b 0a 20 20 7d 0a  (g.fDebug);.  }.
53b0: 7d 0a 0a 2f 2a 0a 2a 2a 20 52 65 74 75 72 6e 20  }../*.** Return 
53c0: 74 72 75 65 20 69 66 20 61 6e 79 20 6f 66 20 74  true if any of t
53d0: 68 65 20 71 75 65 72 79 20 70 61 72 61 6d 65 74  he query paramet
53e0: 65 72 73 20 69 6e 20 74 68 65 20 61 72 67 75 6d  ers in the argum
53f0: 65 6e 74 0a 2a 2a 20 6c 69 73 74 20 61 72 65 20  ent.** list are 
5400: 64 65 66 69 6e 65 64 2e 0a 2a 2f 0a 69 6e 74 20  defined..*/.int 
5410: 63 67 69 5f 61 6e 79 28 63 6f 6e 73 74 20 63 68  cgi_any(const ch
5420: 61 72 20 2a 7a 2c 20 2e 2e 2e 29 7b 0a 20 20 76  ar *z, ...){.  v
5430: 61 5f 6c 69 73 74 20 61 70 3b 0a 20 20 63 68 61  a_list ap;.  cha
5440: 72 20 2a 7a 32 3b 0a 20 20 69 66 28 20 63 67 69  r *z2;.  if( cgi
5450: 5f 70 61 72 61 6d 65 74 65 72 28 7a 2c 30 29 21  _parameter(z,0)!
5460: 3d 30 20 29 20 72 65 74 75 72 6e 20 31 3b 0a 20  =0 ) return 1;. 
5470: 20 76 61 5f 73 74 61 72 74 28 61 70 2c 20 7a 29   va_start(ap, z)
5480: 3b 0a 20 20 77 68 69 6c 65 28 20 28 7a 32 20 3d  ;.  while( (z2 =
5490: 20 76 61 5f 61 72 67 28 61 70 2c 20 63 68 61 72   va_arg(ap, char
54a0: 2a 29 29 21 3d 30 20 29 7b 0a 20 20 20 20 69 66  *))!=0 ){.    if
54b0: 28 20 63 67 69 5f 70 61 72 61 6d 65 74 65 72 28  ( cgi_parameter(
54c0: 7a 32 2c 30 29 21 3d 30 20 29 20 72 65 74 75 72  z2,0)!=0 ) retur
54d0: 6e 20 31 3b 0a 20 20 7d 0a 20 20 76 61 5f 65 6e  n 1;.  }.  va_en
54e0: 64 28 61 70 29 3b 0a 20 20 72 65 74 75 72 6e 20  d(ap);.  return 
54f0: 30 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 52 65 74 75  0;.}../*.** Retu
5500: 72 6e 20 74 72 75 65 20 69 66 20 61 6c 6c 20 6f  rn true if all o
5510: 66 20 74 68 65 20 71 75 65 72 79 20 70 61 72 61  f the query para
5520: 6d 65 74 65 72 73 20 69 6e 20 74 68 65 20 61 72  meters in the ar
5530: 67 75 6d 65 6e 74 20 6c 69 73 74 0a 2a 2a 20 61  gument list.** a
5540: 72 65 20 64 65 66 69 6e 65 64 2e 0a 2a 2f 0a 69  re defined..*/.i
5550: 6e 74 20 63 67 69 5f 61 6c 6c 28 63 6f 6e 73 74  nt cgi_all(const
5560: 20 63 68 61 72 20 2a 7a 2c 20 2e 2e 2e 29 7b 0a   char *z, ...){.
5570: 20 20 76 61 5f 6c 69 73 74 20 61 70 3b 0a 20 20    va_list ap;.  
5580: 63 68 61 72 20 2a 7a 32 3b 0a 20 20 69 66 28 20  char *z2;.  if( 
5590: 63 67 69 5f 70 61 72 61 6d 65 74 65 72 28 7a 2c  cgi_parameter(z,
55a0: 30 29 3d 3d 30 20 29 20 72 65 74 75 72 6e 20 30  0)==0 ) return 0
55b0: 3b 0a 20 20 76 61 5f 73 74 61 72 74 28 61 70 2c  ;.  va_start(ap,
55c0: 20 7a 29 3b 0a 20 20 77 68 69 6c 65 28 20 28 7a   z);.  while( (z
55d0: 32 20 3d 20 76 61 5f 61 72 67 28 61 70 2c 20 63  2 = va_arg(ap, c
55e0: 68 61 72 2a 29 29 3d 3d 30 20 29 7b 0a 20 20 20  har*))==0 ){.   
55f0: 20 69 66 28 20 63 67 69 5f 70 61 72 61 6d 65 74   if( cgi_paramet
5600: 65 72 28 7a 32 2c 30 29 3d 3d 30 20 29 20 72 65  er(z2,0)==0 ) re
5610: 74 75 72 6e 20 30 3b 0a 20 20 7d 0a 20 20 76 61  turn 0;.  }.  va
5620: 5f 65 6e 64 28 61 70 29 3b 0a 20 20 72 65 74 75  _end(ap);.  retu
5630: 72 6e 20 31 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 50  rn 1;.}../*.** P
5640: 72 69 6e 74 20 61 6c 6c 20 71 75 65 72 79 20 70  rint all query p
5650: 61 72 61 6d 65 74 65 72 73 20 6f 6e 20 73 74 61  arameters on sta
5660: 6e 64 61 72 64 20 6f 75 74 70 75 74 2e 20 20 46  ndard output.  F
5670: 6f 72 6d 61 74 20 74 68 65 0a 2a 2a 20 70 61 72  ormat the.** par
5680: 61 6d 65 74 65 72 73 20 61 73 20 48 54 4d 4c 2e  ameters as HTML.
5690: 20 20 54 68 69 73 20 69 73 20 75 73 65 64 20 66    This is used f
56a0: 6f 72 20 74 65 73 74 69 6e 67 20 61 6e 64 20 64  or testing and d
56b0: 65 62 75 67 67 69 6e 67 2e 0a 2a 2f 0a 76 6f 69  ebugging..*/.voi
56c0: 64 20 63 67 69 5f 70 72 69 6e 74 5f 61 6c 6c 28  d cgi_print_all(
56d0: 76 6f 69 64 29 7b 0a 20 20 69 6e 74 20 69 3b 0a  void){.  int i;.
56e0: 20 20 63 67 69 5f 70 61 72 61 6d 65 74 65 72 28    cgi_parameter(
56f0: 22 22 2c 22 22 29 3b 20 20 2f 2a 20 46 6f 72 63  "","");  /* Forc
5700: 65 20 74 68 65 20 70 61 72 61 6d 65 74 65 72 73  e the parameters
5710: 20 69 6e 74 6f 20 73 6f 72 74 65 64 20 6f 72 64   into sorted ord
5720: 65 72 20 2a 2f 0a 20 20 66 6f 72 28 69 3d 30 3b  er */.  for(i=0;
5730: 20 69 3c 6e 55 73 65 64 51 50 3b 20 69 2b 2b 29   i<nUsedQP; i++)
5740: 7b 0a 20 20 20 20 63 67 69 5f 70 72 69 6e 74 66  {.    cgi_printf
5750: 28 22 25 73 20 3d 20 25 73 20 20 3c 62 72 20 2f  ("%s = %s  <br /
5760: 3e 5c 6e 22 2c 0a 20 20 20 20 20 20 20 68 74 6d  >\n",.       htm
5770: 6c 69 7a 65 28 61 50 61 72 61 6d 51 50 5b 69 5d  lize(aParamQP[i]
5780: 2e 7a 4e 61 6d 65 2c 20 2d 31 29 2c 20 68 74 6d  .zName, -1), htm
5790: 6c 69 7a 65 28 61 50 61 72 61 6d 51 50 5b 69 5d  lize(aParamQP[i]
57a0: 2e 7a 56 61 6c 75 65 2c 20 2d 31 29 29 3b 0a 20  .zValue, -1));. 
57b0: 20 7d 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 57 72 69 74   }.}../*.** Writ
57c0: 65 20 48 54 4d 4c 20 74 65 78 74 20 66 6f 72 20  e HTML text for 
57d0: 61 6e 20 6f 70 74 69 6f 6e 20 6d 65 6e 75 20 74  an option menu t
57e0: 6f 20 73 74 61 6e 64 61 72 64 20 6f 75 74 70 75  o standard outpu
57f0: 74 2e 20 20 7a 50 61 72 61 6d 0a 2a 2a 20 69 73  t.  zParam.** is
5800: 20 74 68 65 20 71 75 65 72 79 20 70 61 72 61 6d   the query param
5810: 65 74 65 72 20 74 68 61 74 20 74 68 65 20 6f 70  eter that the op
5820: 74 69 6f 6e 20 6d 65 6e 75 20 73 65 74 73 2e 20  tion menu sets. 
5830: 20 7a 44 66 6c 74 20 69 73 20 74 68 65 0a 2a 2a   zDflt is the.**
5840: 20 69 6e 69 74 69 61 6c 20 76 61 6c 75 65 20 6f   initial value o
5850: 66 20 74 68 65 20 6f 70 74 69 6f 6e 20 6d 65 6e  f the option men
5860: 75 2e 20 20 41 64 64 69 74 69 6f 6e 20 61 72 67  u.  Addition arg
5870: 75 6d 65 6e 74 73 20 61 72 65 20 6e 61 6d 65 2f  uments are name/
5880: 76 61 6c 75 65 0a 2a 2a 20 70 61 69 72 73 20 74  value.** pairs t
5890: 68 61 74 20 64 65 66 69 6e 65 20 76 61 6c 75 65  hat define value
58a0: 73 20 6f 6e 20 74 68 65 20 6d 65 6e 75 2e 20 20  s on the menu.  
58b0: 54 68 65 20 6c 69 73 74 20 69 73 20 74 65 72 6d  The list is term
58c0: 69 6e 61 74 65 64 20 77 69 74 68 0a 2a 2a 20 61  inated with.** a
58d0: 20 73 69 6e 67 6c 65 20 4e 55 4c 4c 20 61 72 67   single NULL arg
58e0: 75 6d 65 6e 74 2e 0a 2a 2f 0a 76 6f 69 64 20 63  ument..*/.void c
58f0: 67 69 5f 6f 70 74 69 6f 6e 6d 65 6e 75 28 69 6e  gi_optionmenu(in
5900: 74 20 69 6e 2c 20 63 6f 6e 73 74 20 63 68 61 72  t in, const char
5910: 20 2a 7a 50 2c 20 63 6f 6e 73 74 20 63 68 61 72   *zP, const char
5920: 20 2a 7a 44 2c 20 2e 2e 2e 29 7b 0a 20 20 76 61   *zD, ...){.  va
5930: 5f 6c 69 73 74 20 61 70 3b 0a 20 20 63 68 61 72  _list ap;.  char
5940: 20 2a 7a 4e 61 6d 65 2c 20 2a 7a 56 61 6c 3b 0a   *zName, *zVal;.
5950: 20 20 69 6e 74 20 64 66 6c 74 53 65 65 6e 20 3d    int dfltSeen =
5960: 20 30 3b 0a 20 20 63 67 69 5f 70 72 69 6e 74 66   0;.  cgi_printf
5970: 28 22 25 2a 73 3c 73 65 6c 65 63 74 20 73 69 7a  ("%*s<select siz
5980: 65 3d 31 20 6e 61 6d 65 3d 5c 22 25 73 5c 22 3e  e=1 name=\"%s\">
5990: 5c 6e 22 2c 20 69 6e 2c 20 22 22 2c 20 7a 50 29  \n", in, "", zP)
59a0: 3b 0a 20 20 76 61 5f 73 74 61 72 74 28 61 70 2c  ;.  va_start(ap,
59b0: 20 7a 44 29 3b 0a 20 20 77 68 69 6c 65 28 20 28   zD);.  while( (
59c0: 7a 4e 61 6d 65 20 3d 20 76 61 5f 61 72 67 28 61  zName = va_arg(a
59d0: 70 2c 20 63 68 61 72 2a 29 29 21 3d 30 20 26 26  p, char*))!=0 &&
59e0: 20 28 7a 56 61 6c 20 3d 20 76 61 5f 61 72 67 28   (zVal = va_arg(
59f0: 61 70 2c 20 63 68 61 72 2a 29 29 21 3d 30 20 29  ap, char*))!=0 )
5a00: 7b 0a 20 20 20 20 69 66 28 20 73 74 72 63 6d 70  {.    if( strcmp
5a10: 28 7a 56 61 6c 2c 7a 44 29 3d 3d 30 20 29 7b 20  (zVal,zD)==0 ){ 
5a20: 64 66 6c 74 53 65 65 6e 20 3d 20 31 3b 20 62 72  dfltSeen = 1; br
5a30: 65 61 6b 3b 20 7d 0a 20 20 7d 0a 20 20 76 61 5f  eak; }.  }.  va_
5a40: 65 6e 64 28 61 70 29 3b 0a 20 20 69 66 28 20 21  end(ap);.  if( !
5a50: 64 66 6c 74 53 65 65 6e 20 29 7b 0a 20 20 20 20  dfltSeen ){.    
5a60: 69 66 28 20 7a 44 5b 30 5d 20 29 7b 0a 20 20 20  if( zD[0] ){.   
5a70: 20 20 20 63 67 69 5f 70 72 69 6e 74 66 28 22 25     cgi_printf("%
5a80: 2a 73 3c 6f 70 74 69 6f 6e 20 76 61 6c 75 65 3d  *s<option value=
5a90: 5c 22 25 68 5c 22 20 73 65 6c 65 63 74 65 64 3e  \"%h\" selected>
5aa0: 25 68 3c 2f 6f 70 74 69 6f 6e 3e 5c 6e 22 2c 0a  %h</option>\n",.
5ab0: 20 20 20 20 20 20 20 20 69 6e 2b 32 2c 20 22 22          in+2, ""
5ac0: 2c 20 7a 44 2c 20 7a 44 29 3b 0a 20 20 20 20 7d  , zD, zD);.    }
5ad0: 65 6c 73 65 7b 0a 20 20 20 20 20 20 63 67 69 5f  else{.      cgi_
5ae0: 70 72 69 6e 74 66 28 22 25 2a 73 3c 6f 70 74 69  printf("%*s<opti
5af0: 6f 6e 20 76 61 6c 75 65 3d 5c 22 5c 22 20 73 65  on value=\"\" se
5b00: 6c 65 63 74 65 64 3e 26 6e 62 73 70 3b 3c 2f 6f  lected>&nbsp;</o
5b10: 70 74 69 6f 6e 3e 5c 6e 22 2c 20 69 6e 2b 32 2c  ption>\n", in+2,
5b20: 20 22 22 29 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a   "");.    }.  }.
5b30: 20 20 76 61 5f 73 74 61 72 74 28 61 70 2c 20 7a    va_start(ap, z
5b40: 44 29 3b 0a 20 20 77 68 69 6c 65 28 20 28 7a 4e  D);.  while( (zN
5b50: 61 6d 65 20 3d 20 76 61 5f 61 72 67 28 61 70 2c  ame = va_arg(ap,
5b60: 20 63 68 61 72 2a 29 29 21 3d 30 20 26 26 20 28   char*))!=0 && (
5b70: 7a 56 61 6c 20 3d 20 76 61 5f 61 72 67 28 61 70  zVal = va_arg(ap
5b80: 2c 20 63 68 61 72 2a 29 29 21 3d 30 20 29 7b 0a  , char*))!=0 ){.
5b90: 20 20 20 20 69 66 28 20 7a 4e 61 6d 65 5b 30 5d      if( zName[0]
5ba0: 20 29 7b 0a 20 20 20 20 20 20 63 67 69 5f 70 72   ){.      cgi_pr
5bb0: 69 6e 74 66 28 22 25 2a 73 3c 6f 70 74 69 6f 6e  intf("%*s<option
5bc0: 20 76 61 6c 75 65 3d 5c 22 25 68 5c 22 25 73 3e   value=\"%h\"%s>
5bd0: 25 68 3c 2f 6f 70 74 69 6f 6e 3e 5c 6e 22 2c 0a  %h</option>\n",.
5be0: 20 20 20 20 20 20 20 20 69 6e 2b 32 2c 20 22 22          in+2, ""
5bf0: 2c 0a 20 20 20 20 20 20 20 20 7a 56 61 6c 2c 0a  ,.        zVal,.
5c00: 20 20 20 20 20 20 20 20 73 74 72 63 6d 70 28 7a          strcmp(z
5c10: 56 61 6c 2c 20 7a 44 29 20 3f 20 22 22 20 3a 20  Val, zD) ? "" : 
5c20: 22 20 73 65 6c 65 63 74 65 64 22 2c 0a 20 20 20  " selected",.   
5c30: 20 20 20 20 20 7a 4e 61 6d 65 0a 20 20 20 20 20       zName.     
5c40: 20 29 3b 0a 20 20 20 20 7d 65 6c 73 65 7b 0a 20   );.    }else{. 
5c50: 20 20 20 20 20 63 67 69 5f 70 72 69 6e 74 66 28       cgi_printf(
5c60: 22 25 2a 73 3c 6f 70 74 69 6f 6e 20 76 61 6c 75  "%*s<option valu
5c70: 65 3d 5c 22 5c 22 25 73 3e 26 6e 62 73 70 3b 3c  e=\"\"%s>&nbsp;<
5c80: 2f 6f 70 74 69 6f 6e 3e 5c 6e 22 2c 0a 20 20 20  /option>\n",.   
5c90: 20 20 20 20 20 69 6e 2b 32 2c 20 22 22 2c 0a 20       in+2, "",. 
5ca0: 20 20 20 20 20 20 20 73 74 72 63 6d 70 28 7a 56         strcmp(zV
5cb0: 61 6c 2c 20 7a 44 29 20 3f 20 22 22 20 3a 20 22  al, zD) ? "" : "
5cc0: 20 73 65 6c 65 63 74 65 64 22 0a 20 20 20 20 20   selected".     
5cd0: 20 29 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20   );.    }.  }.  
5ce0: 76 61 5f 65 6e 64 28 61 70 29 3b 0a 20 20 63 67  va_end(ap);.  cg
5cf0: 69 5f 70 72 69 6e 74 66 28 22 25 2a 73 3c 2f 73  i_printf("%*s</s
5d00: 65 6c 65 63 74 3e 5c 6e 22 2c 20 69 6e 2c 20 22  elect>\n", in, "
5d10: 22 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54 68 69  ");.}../*.** Thi
5d20: 73 20 72 6f 75 74 69 6e 65 20 77 6f 72 6b 73 20  s routine works 
5d30: 61 20 6c 6f 74 20 6c 69 6b 65 20 63 67 69 5f 6f  a lot like cgi_o
5d40: 70 74 69 6f 6e 6d 65 6e 75 28 29 20 65 78 63 65  ptionmenu() exce
5d50: 70 74 20 74 68 61 74 20 74 68 65 20 6c 69 73 74  pt that the list
5d60: 20 6f 66 0a 2a 2a 20 76 61 6c 75 65 73 20 69 73   of.** values is
5d70: 20 63 6f 6e 74 61 69 6e 65 64 20 69 6e 20 61 6e   contained in an
5d80: 20 61 72 72 61 79 2e 20 20 41 6c 73 6f 2c 20 74   array.  Also, t
5d90: 68 65 20 76 61 6c 75 65 73 20 61 72 65 20 6a 75  he values are ju
5da0: 73 74 20 76 61 6c 75 65 73 2c 20 6e 6f 74 0a 2a  st values, not.*
5db0: 2a 20 6e 61 6d 65 2f 76 61 6c 75 65 20 70 61 69  * name/value pai
5dc0: 72 73 20 61 73 20 69 6e 20 63 67 69 5f 6f 70 74  rs as in cgi_opt
5dd0: 69 6f 6e 6d 65 6e 75 2e 0a 2a 2f 0a 76 6f 69 64  ionmenu..*/.void
5de0: 20 63 67 69 5f 76 5f 6f 70 74 69 6f 6e 6d 65 6e   cgi_v_optionmen
5df0: 75 28 0a 20 20 69 6e 74 20 69 6e 2c 20 20 20 20  u(.  int in,    
5e00: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 49 6e 64            /* Ind
5e10: 65 6e 74 20 62 79 20 74 68 69 73 20 61 6d 6f 75  ent by this amou
5e20: 6e 74 20 2a 2f 0a 20 20 63 6f 6e 73 74 20 63 68  nt */.  const ch
5e30: 61 72 20 2a 7a 50 2c 20 20 20 20 20 20 2f 2a 20  ar *zP,      /* 
5e40: 54 68 65 20 71 75 65 72 79 20 70 61 72 61 6d 65  The query parame
5e50: 74 65 72 20 6e 61 6d 65 20 2a 2f 0a 20 20 63 6f  ter name */.  co
5e60: 6e 73 74 20 63 68 61 72 20 2a 7a 44 2c 20 20 20  nst char *zD,   
5e70: 20 20 20 2f 2a 20 44 65 66 61 75 6c 74 20 76 61     /* Default va
5e80: 6c 75 65 20 2a 2f 0a 20 20 63 6f 6e 73 74 20 63  lue */.  const c
5e90: 68 61 72 20 2a 2a 61 7a 20 20 20 20 20 20 2f 2a  har **az      /*
5ea0: 20 4e 55 4c 4c 2d 74 65 72 6d 69 6e 61 74 65 64   NULL-terminated
5eb0: 20 6c 69 73 74 20 6f 66 20 61 6c 6c 6f 77 65 64   list of allowed
5ec0: 20 76 61 6c 75 65 73 20 2a 2f 0a 29 7b 0a 20 20   values */.){.  
5ed0: 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 56 61 6c  const char *zVal
5ee0: 3b 0a 20 20 69 6e 74 20 69 3b 0a 20 20 63 67 69  ;.  int i;.  cgi
5ef0: 5f 70 72 69 6e 74 66 28 22 25 2a 73 3c 73 65 6c  _printf("%*s<sel
5f00: 65 63 74 20 73 69 7a 65 3d 31 20 6e 61 6d 65 3d  ect size=1 name=
5f10: 5c 22 25 73 5c 22 3e 5c 6e 22 2c 20 69 6e 2c 20  \"%s\">\n", in, 
5f20: 22 22 2c 20 7a 50 29 3b 0a 20 20 66 6f 72 28 69  "", zP);.  for(i
5f30: 3d 30 3b 20 61 7a 5b 69 5d 3b 20 69 2b 2b 29 7b  =0; az[i]; i++){
5f40: 0a 20 20 20 20 69 66 28 20 73 74 72 63 6d 70 28  .    if( strcmp(
5f50: 61 7a 5b 69 5d 2c 7a 44 29 3d 3d 30 20 29 20 62  az[i],zD)==0 ) b
5f60: 72 65 61 6b 3b 0a 20 20 7d 0a 20 20 69 66 28 20  reak;.  }.  if( 
5f70: 61 7a 5b 69 5d 3d 3d 30 20 29 7b 0a 20 20 20 20  az[i]==0 ){.    
5f80: 69 66 28 20 7a 44 5b 30 5d 3d 3d 30 20 29 7b 0a  if( zD[0]==0 ){.
5f90: 20 20 20 20 20 20 63 67 69 5f 70 72 69 6e 74 66        cgi_printf
5fa0: 28 22 25 2a 73 3c 6f 70 74 69 6f 6e 20 76 61 6c  ("%*s<option val
5fb0: 75 65 3d 5c 22 5c 22 20 73 65 6c 65 63 74 65 64  ue=\"\" selected
5fc0: 3e 26 6e 62 73 70 3b 3c 2f 6f 70 74 69 6f 6e 3e  >&nbsp;</option>
5fd0: 5c 6e 22 2c 0a 20 20 20 20 20 20 20 69 6e 2b 32  \n",.       in+2
5fe0: 2c 20 22 22 29 3b 0a 20 20 20 20 7d 65 6c 73 65  , "");.    }else
5ff0: 7b 0a 20 20 20 20 20 20 63 67 69 5f 70 72 69 6e  {.      cgi_prin
6000: 74 66 28 22 25 2a 73 3c 6f 70 74 69 6f 6e 20 76  tf("%*s<option v
6010: 61 6c 75 65 3d 5c 22 25 68 5c 22 20 73 65 6c 65  alue=\"%h\" sele
6020: 63 74 65 64 3e 25 68 3c 2f 6f 70 74 69 6f 6e 3e  cted>%h</option>
6030: 5c 6e 22 2c 0a 20 20 20 20 20 20 20 69 6e 2b 32  \n",.       in+2
6040: 2c 20 22 22 2c 20 7a 44 2c 20 7a 44 29 3b 0a 20  , "", zD, zD);. 
6050: 20 20 20 7d 0a 20 20 7d 0a 20 20 77 68 69 6c 65     }.  }.  while
6060: 28 20 28 7a 56 61 6c 20 3d 20 2a 28 61 7a 2b 2b  ( (zVal = *(az++
6070: 29 29 21 3d 30 20 20 29 7b 0a 20 20 20 20 69 66  ))!=0  ){.    if
6080: 28 20 7a 56 61 6c 5b 30 5d 20 29 7b 0a 20 20 20  ( zVal[0] ){.   
6090: 20 20 20 63 67 69 5f 70 72 69 6e 74 66 28 22 25     cgi_printf("%
60a0: 2a 73 3c 6f 70 74 69 6f 6e 20 76 61 6c 75 65 3d  *s<option value=
60b0: 5c 22 25 68 5c 22 25 73 3e 25 68 3c 2f 6f 70 74  \"%h\"%s>%h</opt
60c0: 69 6f 6e 3e 5c 6e 22 2c 0a 20 20 20 20 20 20 20  ion>\n",.       
60d0: 20 69 6e 2b 32 2c 20 22 22 2c 0a 20 20 20 20 20   in+2, "",.     
60e0: 20 20 20 7a 56 61 6c 2c 0a 20 20 20 20 20 20 20     zVal,.       
60f0: 20 73 74 72 63 6d 70 28 7a 56 61 6c 2c 20 7a 44   strcmp(zVal, zD
6100: 29 20 3f 20 22 22 20 3a 20 22 20 73 65 6c 65 63  ) ? "" : " selec
6110: 74 65 64 22 2c 0a 20 20 20 20 20 20 20 20 7a 56  ted",.        zV
6120: 61 6c 0a 20 20 20 20 20 20 29 3b 0a 20 20 20 20  al.      );.    
6130: 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 63 67 69  }else{.      cgi
6140: 5f 70 72 69 6e 74 66 28 22 25 2a 73 3c 6f 70 74  _printf("%*s<opt
6150: 69 6f 6e 20 76 61 6c 75 65 3d 5c 22 5c 22 25 73  ion value=\"\"%s
6160: 3e 26 6e 62 73 70 3b 3c 2f 6f 70 74 69 6f 6e 3e  >&nbsp;</option>
6170: 5c 6e 22 2c 0a 20 20 20 20 20 20 20 20 69 6e 2b  \n",.        in+
6180: 32 2c 20 22 22 2c 0a 20 20 20 20 20 20 20 20 73  2, "",.        s
6190: 74 72 63 6d 70 28 7a 56 61 6c 2c 20 7a 44 29 20  trcmp(zVal, zD) 
61a0: 3f 20 22 22 20 3a 20 22 20 73 65 6c 65 63 74 65  ? "" : " selecte
61b0: 64 22 0a 20 20 20 20 20 20 29 3b 0a 20 20 20 20  d".      );.    
61c0: 7d 0a 20 20 7d 0a 20 20 63 67 69 5f 70 72 69 6e  }.  }.  cgi_prin
61d0: 74 66 28 22 25 2a 73 3c 2f 73 65 6c 65 63 74 3e  tf("%*s</select>
61e0: 5c 6e 22 2c 20 69 6e 2c 20 22 22 29 3b 0a 7d 0a  \n", in, "");.}.
61f0: 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20 72 6f 75 74  ./*.** This rout
6200: 69 6e 65 20 77 6f 72 6b 73 20 61 20 6c 6f 74 20  ine works a lot 
6210: 6c 69 6b 65 20 63 67 69 5f 76 5f 6f 70 74 69 6f  like cgi_v_optio
6220: 6e 6d 65 6e 75 28 29 20 65 78 63 65 70 74 20 74  nmenu() except t
6230: 68 61 74 20 74 68 65 20 6c 69 73 74 0a 2a 2a 20  hat the list.** 
6240: 69 73 20 61 20 6c 69 73 74 20 6f 66 20 70 61 69  is a list of pai
6250: 72 73 2e 20 20 54 68 65 20 66 69 72 73 74 20 65  rs.  The first e
6260: 6c 65 6d 65 6e 74 20 6f 66 20 65 61 63 68 20 70  lement of each p
6270: 61 69 72 20 69 73 20 74 68 65 20 76 61 6c 75 65  air is the value
6280: 20 75 73 65 64 0a 2a 2a 20 69 6e 74 65 72 6e 61   used.** interna
6290: 6c 6c 79 20 61 6e 64 20 74 68 65 20 73 65 63 6f  lly and the seco
62a0: 6e 64 20 65 6c 65 6d 65 6e 74 20 69 73 20 74 68  nd element is th
62b0: 65 20 76 61 6c 75 65 20 64 69 73 70 6c 61 79 65  e value displaye
62c0: 64 20 74 6f 20 74 68 65 20 75 73 65 72 2e 0a 2a  d to the user..*
62d0: 2f 0a 76 6f 69 64 20 63 67 69 5f 76 5f 6f 70 74  /.void cgi_v_opt
62e0: 69 6f 6e 6d 65 6e 75 32 28 0a 20 20 69 6e 74 20  ionmenu2(.  int 
62f0: 69 6e 2c 20 20 20 20 20 20 20 20 20 20 20 20 20  in,             
6300: 20 2f 2a 20 49 6e 64 65 6e 74 20 62 79 20 74 68   /* Indent by th
6310: 69 73 20 61 6d 6f 75 6e 74 20 2a 2f 0a 20 20 63  is amount */.  c
6320: 6f 6e 73 74 20 63 68 61 72 20 2a 7a 50 2c 20 20  onst char *zP,  
6330: 20 20 20 20 2f 2a 20 54 68 65 20 71 75 65 72 79      /* The query
6340: 20 70 61 72 61 6d 65 74 65 72 20 6e 61 6d 65 20   parameter name 
6350: 2a 2f 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20  */.  const char 
6360: 2a 7a 44 2c 20 20 20 20 20 20 2f 2a 20 44 65 66  *zD,      /* Def
6370: 61 75 6c 74 20 76 61 6c 75 65 20 2a 2f 0a 20 20  ault value */.  
6380: 63 6f 6e 73 74 20 63 68 61 72 20 2a 2a 61 7a 20  const char **az 
6390: 20 20 20 20 20 2f 2a 20 4e 55 4c 4c 2d 74 65 72       /* NULL-ter
63a0: 6d 69 6e 61 74 65 64 20 6c 69 73 74 20 6f 66 20  minated list of 
63b0: 61 6c 6c 6f 77 65 64 20 76 61 6c 75 65 73 20 2a  allowed values *
63c0: 2f 0a 29 7b 0a 20 20 63 6f 6e 73 74 20 63 68 61  /.){.  const cha
63d0: 72 20 2a 7a 56 61 6c 3b 0a 20 20 69 6e 74 20 69  r *zVal;.  int i
63e0: 3b 0a 20 20 63 67 69 5f 70 72 69 6e 74 66 28 22  ;.  cgi_printf("
63f0: 25 2a 73 3c 73 65 6c 65 63 74 20 73 69 7a 65 3d  %*s<select size=
6400: 31 20 6e 61 6d 65 3d 5c 22 25 73 5c 22 3e 5c 6e  1 name=\"%s\">\n
6410: 22 2c 20 69 6e 2c 20 22 22 2c 20 7a 50 29 3b 0a  ", in, "", zP);.
6420: 20 20 66 6f 72 28 69 3d 30 3b 20 61 7a 5b 69 5d    for(i=0; az[i]
6430: 3b 20 69 2b 3d 32 29 7b 0a 20 20 20 20 69 66 28  ; i+=2){.    if(
6440: 20 73 74 72 63 6d 70 28 61 7a 5b 69 5d 2c 7a 44   strcmp(az[i],zD
6450: 29 3d 3d 30 20 29 20 62 72 65 61 6b 3b 0a 20 20  )==0 ) break;.  
6460: 7d 0a 20 20 69 66 28 20 61 7a 5b 69 5d 3d 3d 30  }.  if( az[i]==0
6470: 20 29 7b 0a 20 20 20 20 69 66 28 20 7a 44 5b 30   ){.    if( zD[0
6480: 5d 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 63 67  ]==0 ){.      cg
6490: 69 5f 70 72 69 6e 74 66 28 22 25 2a 73 3c 6f 70  i_printf("%*s<op
64a0: 74 69 6f 6e 20 76 61 6c 75 65 3d 5c 22 5c 22 20  tion value=\"\" 
64b0: 73 65 6c 65 63 74 65 64 3e 26 6e 62 73 70 3b 3c  selected>&nbsp;<
64c0: 2f 6f 70 74 69 6f 6e 3e 5c 6e 22 2c 0a 20 20 20  /option>\n",.   
64d0: 20 20 20 20 69 6e 2b 32 2c 20 22 22 29 3b 0a 20      in+2, "");. 
64e0: 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20     }else{.      
64f0: 63 67 69 5f 70 72 69 6e 74 66 28 22 25 2a 73 3c  cgi_printf("%*s<
6500: 6f 70 74 69 6f 6e 20 76 61 6c 75 65 3d 5c 22 25  option value=\"%
6510: 68 5c 22 20 73 65 6c 65 63 74 65 64 3e 25 68 3c  h\" selected>%h<
6520: 2f 6f 70 74 69 6f 6e 3e 5c 6e 22 2c 0a 20 20 20  /option>\n",.   
6530: 20 20 20 20 69 6e 2b 32 2c 20 22 22 2c 20 7a 44      in+2, "", zD
6540: 2c 20 7a 44 29 3b 0a 20 20 20 20 7d 0a 20 20 7d  , zD);.    }.  }
6550: 0a 20 20 77 68 69 6c 65 28 20 28 7a 56 61 6c 20  .  while( (zVal 
6560: 3d 20 2a 28 61 7a 2b 2b 29 29 21 3d 30 20 20 29  = *(az++))!=0  )
6570: 7b 0a 20 20 20 20 63 6f 6e 73 74 20 63 68 61 72  {.    const char
6580: 20 2a 7a 4e 61 6d 65 20 3d 20 2a 28 61 7a 2b 2b   *zName = *(az++
6590: 29 3b 0a 20 20 20 20 69 66 28 20 7a 4e 61 6d 65  );.    if( zName
65a0: 5b 30 5d 20 29 7b 0a 20 20 20 20 20 20 63 67 69  [0] ){.      cgi
65b0: 5f 70 72 69 6e 74 66 28 22 25 2a 73 3c 6f 70 74  _printf("%*s<opt
65c0: 69 6f 6e 20 76 61 6c 75 65 3d 5c 22 25 68 5c 22  ion value=\"%h\"
65d0: 25 73 3e 25 68 3c 2f 6f 70 74 69 6f 6e 3e 5c 6e  %s>%h</option>\n
65e0: 22 2c 0a 20 20 20 20 20 20 20 20 69 6e 2b 32 2c  ",.        in+2,
65f0: 20 22 22 2c 0a 20 20 20 20 20 20 20 20 7a 56 61   "",.        zVa
6600: 6c 2c 0a 20 20 20 20 20 20 20 20 73 74 72 63 6d  l,.        strcm
6610: 70 28 7a 56 61 6c 2c 20 7a 44 29 20 3f 20 22 22  p(zVal, zD) ? ""
6620: 20 3a 20 22 20 73 65 6c 65 63 74 65 64 22 2c 0a   : " selected",.
6630: 20 20 20 20 20 20 20 20 7a 4e 61 6d 65 0a 20 20          zName.  
6640: 20 20 20 20 29 3b 0a 20 20 20 20 7d 65 6c 73 65      );.    }else
6650: 7b 0a 20 20 20 20 20 20 63 67 69 5f 70 72 69 6e  {.      cgi_prin
6660: 74 66 28 22 25 2a 73 3c 6f 70 74 69 6f 6e 20 76  tf("%*s<option v
6670: 61 6c 75 65 3d 5c 22 25 68 5c 22 25 73 3e 26 6e  alue=\"%h\"%s>&n
6680: 62 73 70 3b 3c 2f 6f 70 74 69 6f 6e 3e 5c 6e 22  bsp;</option>\n"
6690: 2c 0a 20 20 20 20 20 20 20 20 69 6e 2b 32 2c 20  ,.        in+2, 
66a0: 22 22 2c 0a 20 20 20 20 20 20 20 20 7a 56 61 6c  "",.        zVal
66b0: 2c 0a 20 20 20 20 20 20 20 20 73 74 72 63 6d 70  ,.        strcmp
66c0: 28 7a 56 61 6c 2c 20 7a 44 29 20 3f 20 22 22 20  (zVal, zD) ? "" 
66d0: 3a 20 22 20 73 65 6c 65 63 74 65 64 22 0a 20 20  : " selected".  
66e0: 20 20 20 20 29 3b 0a 20 20 20 20 7d 0a 20 20 7d      );.    }.  }
66f0: 0a 20 20 63 67 69 5f 70 72 69 6e 74 66 28 22 25  .  cgi_printf("%
6700: 2a 73 3c 2f 73 65 6c 65 63 74 3e 5c 6e 22 2c 20  *s</select>\n", 
6710: 69 6e 2c 20 22 22 29 3b 0a 7d 0a 0a 2f 2a 20 0a  in, "");.}../* .
6720: 2a 2a 20 54 68 69 73 20 66 75 6e 63 74 69 6f 6e  ** This function
6730: 20 69 6d 70 6c 65 6d 65 6e 74 73 20 74 68 65 20   implements the 
6740: 63 61 6c 6c 62 61 63 6b 20 66 72 6f 6d 20 76 78  callback from vx
6750: 70 72 69 6e 74 66 2e 20 0a 2a 2a 0a 2a 2a 20 54  printf. .**.** T
6760: 68 69 73 20 72 6f 75 74 69 6e 65 20 73 65 6e 64  his routine send
6770: 73 20 6e 4e 65 77 43 68 61 72 20 63 68 61 72 61  s nNewChar chara
6780: 63 74 65 72 73 20 6f 66 20 74 65 78 74 20 69 6e  cters of text in
6790: 20 7a 4e 65 77 54 65 78 74 20 74 6f 0a 2a 2a 20   zNewText to.** 
67a0: 43 47 49 20 72 65 70 6c 79 20 63 6f 6e 74 65 6e  CGI reply conten
67b0: 74 20 62 75 66 66 65 72 2e 0a 2a 2f 0a 73 74 61  t buffer..*/.sta
67c0: 74 69 63 20 76 6f 69 64 20 73 6f 75 74 28 76 6f  tic void sout(vo
67d0: 69 64 20 2a 4e 6f 74 55 73 65 64 2c 20 63 6f 6e  id *NotUsed, con
67e0: 73 74 20 63 68 61 72 20 2a 7a 4e 65 77 54 65 78  st char *zNewTex
67f0: 74 2c 20 69 6e 74 20 6e 4e 65 77 43 68 61 72 29  t, int nNewChar)
6800: 7b 0a 20 20 63 67 69 5f 61 70 70 65 6e 64 5f 63  {.  cgi_append_c
6810: 6f 6e 74 65 6e 74 28 7a 4e 65 77 54 65 78 74 2c  ontent(zNewText,
6820: 20 6e 4e 65 77 43 68 61 72 29 3b 0a 7d 0a 0a 2f   nNewChar);.}../
6830: 2a 0a 2a 2a 20 54 68 69 73 20 72 6f 75 74 69 6e  *.** This routin
6840: 65 20 77 6f 72 6b 73 20 6c 69 6b 65 20 22 70 72  e works like "pr
6850: 69 6e 74 66 22 20 65 78 63 65 70 74 20 74 68 61  intf" except tha
6860: 74 20 69 74 20 68 61 73 20 74 68 65 0a 2a 2a 20  t it has the.** 
6870: 65 78 74 72 61 20 66 6f 72 6d 61 74 74 69 6e 67  extra formatting
6880: 20 63 61 70 61 62 69 6c 69 74 69 65 73 20 73 75   capabilities su
6890: 63 68 20 61 73 20 25 68 20 61 6e 64 20 25 74 2e  ch as %h and %t.
68a0: 0a 2a 2f 0a 76 6f 69 64 20 63 67 69 5f 70 72 69  .*/.void cgi_pri
68b0: 6e 74 66 28 63 6f 6e 73 74 20 63 68 61 72 20 2a  ntf(const char *
68c0: 7a 46 6f 72 6d 61 74 2c 20 2e 2e 2e 29 7b 0a 20  zFormat, ...){. 
68d0: 20 76 61 5f 6c 69 73 74 20 61 70 3b 0a 20 20 76   va_list ap;.  v
68e0: 61 5f 73 74 61 72 74 28 61 70 2c 7a 46 6f 72 6d  a_start(ap,zForm
68f0: 61 74 29 3b 0a 20 20 76 78 70 72 69 6e 74 66 28  at);.  vxprintf(
6900: 73 6f 75 74 2c 30 2c 7a 46 6f 72 6d 61 74 2c 61  sout,0,zFormat,a
6910: 70 29 3b 0a 20 20 76 61 5f 65 6e 64 28 61 70 29  p);.  va_end(ap)
6920: 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20  ;.}../*.** This 
6930: 72 6f 75 74 69 6e 65 20 77 6f 72 6b 73 20 6c 69  routine works li
6940: 6b 65 20 22 76 70 72 69 6e 74 66 22 20 65 78 63  ke "vprintf" exc
6950: 65 70 74 20 74 68 61 74 20 69 74 20 68 61 73 20  ept that it has 
6960: 74 68 65 0a 2a 2a 20 65 78 74 72 61 20 66 6f 72  the.** extra for
6970: 6d 61 74 74 69 6e 67 20 63 61 70 61 62 69 6c 69  matting capabili
6980: 74 69 65 73 20 73 75 63 68 20 61 73 20 25 68 20  ties such as %h 
6990: 61 6e 64 20 25 74 2e 0a 2a 2f 0a 76 6f 69 64 20  and %t..*/.void 
69a0: 63 67 69 5f 76 70 72 69 6e 74 66 28 63 6f 6e 73  cgi_vprintf(cons
69b0: 74 20 63 68 61 72 20 2a 7a 46 6f 72 6d 61 74 2c  t char *zFormat,
69c0: 20 76 61 5f 6c 69 73 74 20 61 70 29 7b 0a 20 20   va_list ap){.  
69d0: 76 78 70 72 69 6e 74 66 28 73 6f 75 74 2c 30 2c  vxprintf(sout,0,
69e0: 7a 46 6f 72 6d 61 74 2c 61 70 29 3b 0a 7d 0a 0a  zFormat,ap);.}..
69f0: 0a 2f 2a 0a 2a 2a 20 53 65 6e 64 20 61 20 72 65  ./*.** Send a re
6a00: 70 6c 79 20 69 6e 64 69 63 61 74 69 6e 67 20 74  ply indicating t
6a10: 68 61 74 20 74 68 65 20 48 54 54 50 20 72 65 71  hat the HTTP req
6a20: 75 65 73 74 20 77 61 73 20 6d 61 6c 66 6f 72 6d  uest was malform
6a30: 65 64 0a 2a 2f 0a 73 74 61 74 69 63 20 76 6f 69  ed.*/.static voi
6a40: 64 20 6d 61 6c 66 6f 72 6d 65 64 5f 72 65 71 75  d malformed_requ
6a50: 65 73 74 28 76 6f 69 64 29 7b 0a 20 20 63 67 69  est(void){.  cgi
6a60: 5f 73 65 74 5f 73 74 61 74 75 73 28 35 30 31 2c  _set_status(501,
6a70: 20 22 4e 6f 74 20 49 6d 70 6c 65 6d 65 6e 74 65   "Not Implemente
6a80: 64 22 29 3b 0a 20 20 63 67 69 5f 70 72 69 6e 74  d");.  cgi_print
6a90: 66 28 0a 20 20 20 20 22 3c 68 74 6d 6c 3e 3c 62  f(.    "<html><b
6aa0: 6f 64 79 3e 55 6e 72 65 63 6f 67 6e 69 7a 65 64  ody>Unrecognized
6ab0: 20 48 54 54 50 20 52 65 71 75 65 73 74 3c 2f 62   HTTP Request</b
6ac0: 6f 64 79 3e 3c 2f 68 74 6d 6c 3e 5c 6e 22 0a 20  ody></html>\n". 
6ad0: 20 29 3b 0a 20 20 63 67 69 5f 72 65 70 6c 79 28   );.  cgi_reply(
6ae0: 29 3b 0a 20 20 65 78 69 74 28 30 29 3b 0a 7d 0a  );.  exit(0);.}.
6af0: 0a 2f 2a 0a 2a 2a 20 50 61 6e 69 63 20 61 6e 64  ./*.** Panic and
6b00: 20 64 69 65 20 77 68 69 6c 65 20 70 72 6f 63 65   die while proce
6b10: 73 73 69 6e 67 20 61 20 77 65 62 70 61 67 65 2e  ssing a webpage.
6b20: 0a 2a 2f 0a 76 6f 69 64 20 63 67 69 5f 70 61 6e  .*/.void cgi_pan
6b30: 69 63 28 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a  ic(const char *z
6b40: 46 6f 72 6d 61 74 2c 20 2e 2e 2e 29 7b 0a 20 20  Format, ...){.  
6b50: 76 61 5f 6c 69 73 74 20 61 70 3b 0a 20 20 63 67  va_list ap;.  cg
6b60: 69 5f 72 65 73 65 74 5f 63 6f 6e 74 65 6e 74 28  i_reset_content(
6b70: 29 3b 0a 20 20 63 67 69 5f 73 65 74 5f 73 74 61  );.  cgi_set_sta
6b80: 74 75 73 28 35 30 30 2c 20 22 49 6e 74 65 72 6e  tus(500, "Intern
6b90: 61 6c 20 53 65 72 76 65 72 20 45 72 72 6f 72 22  al Server Error"
6ba0: 29 3b 0a 20 20 63 67 69 5f 70 72 69 6e 74 66 28  );.  cgi_printf(
6bb0: 0a 20 20 20 20 22 3c 68 74 6d 6c 3e 3c 62 6f 64  .    "<html><bod
6bc0: 79 3e 3c 68 31 3e 49 6e 74 65 72 6e 61 6c 20 53  y><h1>Internal S
6bd0: 65 72 76 65 72 20 45 72 72 6f 72 3c 2f 68 31 3e  erver Error</h1>
6be0: 5c 6e 22 0a 20 20 20 20 22 3c 70 6c 61 69 6e 74  \n".    "<plaint
6bf0: 65 78 74 3e 22 0a 20 20 29 3b 0a 20 20 76 61 5f  ext>".  );.  va_
6c00: 73 74 61 72 74 28 61 70 2c 20 7a 46 6f 72 6d 61  start(ap, zForma
6c10: 74 29 3b 0a 20 20 76 78 70 72 69 6e 74 66 28 73  t);.  vxprintf(s
6c20: 6f 75 74 2c 30 2c 7a 46 6f 72 6d 61 74 2c 61 70  out,0,zFormat,ap
6c30: 29 3b 0a 20 20 76 61 5f 65 6e 64 28 61 70 29 3b  );.  va_end(ap);
6c40: 0a 20 20 63 67 69 5f 72 65 70 6c 79 28 29 3b 0a  .  cgi_reply();.
6c50: 20 20 65 78 69 74 28 31 29 3b 0a 7d 0a 0a 2f 2a    exit(1);.}../*
6c60: 0a 2a 2a 20 52 65 6d 6f 76 65 20 74 68 65 20 66  .** Remove the f
6c70: 69 72 73 74 20 73 70 61 63 65 2d 64 65 6c 69 6d  irst space-delim
6c80: 69 74 65 64 20 74 6f 6b 65 6e 20 66 72 6f 6d 20  ited token from 
6c90: 61 20 73 74 72 69 6e 67 20 61 6e 64 20 72 65 74  a string and ret
6ca0: 75 72 6e 0a 2a 2a 20 61 20 70 6f 69 6e 74 65 72  urn.** a pointer
6cb0: 20 74 6f 20 69 74 2e 20 20 41 64 64 20 61 20 4e   to it.  Add a N
6cc0: 55 4c 4c 20 74 6f 20 74 68 65 20 73 74 72 69 6e  ULL to the strin
6cd0: 67 20 74 6f 20 74 65 72 6d 69 6e 61 74 65 20 74  g to terminate t
6ce0: 68 65 20 74 6f 6b 65 6e 2e 0a 2a 2a 20 4d 61 6b  he token..** Mak
6cf0: 65 20 2a 7a 4c 65 66 74 4f 76 65 72 20 70 6f 69  e *zLeftOver poi
6d00: 6e 74 20 74 6f 20 74 68 65 20 73 74 61 72 74 20  nt to the start 
6d10: 6f 66 20 74 68 65 20 6e 65 78 74 20 74 6f 6b 65  of the next toke
6d20: 6e 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 63 68 61  n..*/.static cha
6d30: 72 20 2a 65 78 74 72 61 63 74 5f 74 6f 6b 65 6e  r *extract_token
6d40: 28 63 68 61 72 20 2a 7a 49 6e 70 75 74 2c 20 63  (char *zInput, c
6d50: 68 61 72 20 2a 2a 7a 4c 65 66 74 4f 76 65 72 29  har **zLeftOver)
6d60: 7b 0a 20 20 63 68 61 72 20 2a 7a 52 65 73 75 6c  {.  char *zResul
6d70: 74 20 3d 20 30 3b 0a 20 20 69 66 28 20 7a 49 6e  t = 0;.  if( zIn
6d80: 70 75 74 3d 3d 30 20 29 7b 0a 20 20 20 20 69 66  put==0 ){.    if
6d90: 28 20 7a 4c 65 66 74 4f 76 65 72 20 29 20 2a 7a  ( zLeftOver ) *z
6da0: 4c 65 66 74 4f 76 65 72 20 3d 20 30 3b 0a 20 20  LeftOver = 0;.  
6db0: 20 20 72 65 74 75 72 6e 20 30 3b 0a 20 20 7d 0a    return 0;.  }.
6dc0: 20 20 77 68 69 6c 65 28 20 69 73 73 70 61 63 65    while( isspace
6dd0: 28 2a 7a 49 6e 70 75 74 29 20 29 7b 20 7a 49 6e  (*zInput) ){ zIn
6de0: 70 75 74 2b 2b 3b 20 7d 0a 20 20 7a 52 65 73 75  put++; }.  zResu
6df0: 6c 74 20 3d 20 7a 49 6e 70 75 74 3b 0a 20 20 77  lt = zInput;.  w
6e00: 68 69 6c 65 28 20 2a 7a 49 6e 70 75 74 20 26 26  hile( *zInput &&
6e10: 20 21 69 73 73 70 61 63 65 28 2a 7a 49 6e 70 75   !isspace(*zInpu
6e20: 74 29 20 29 7b 20 7a 49 6e 70 75 74 2b 2b 3b 20  t) ){ zInput++; 
6e30: 7d 0a 20 20 69 66 28 20 2a 7a 49 6e 70 75 74 20  }.  if( *zInput 
6e40: 29 7b 0a 20 20 20 20 2a 7a 49 6e 70 75 74 20 3d  ){.    *zInput =
6e50: 20 30 3b 0a 20 20 20 20 7a 49 6e 70 75 74 2b 2b   0;.    zInput++
6e60: 3b 0a 20 20 20 20 77 68 69 6c 65 28 20 69 73 73  ;.    while( iss
6e70: 70 61 63 65 28 2a 7a 49 6e 70 75 74 29 20 29 7b  pace(*zInput) ){
6e80: 20 7a 49 6e 70 75 74 2b 2b 3b 20 7d 0a 20 20 7d   zInput++; }.  }
6e90: 0a 20 20 69 66 28 20 7a 4c 65 66 74 4f 76 65 72  .  if( zLeftOver
6ea0: 20 29 7b 20 2a 7a 4c 65 66 74 4f 76 65 72 20 3d   ){ *zLeftOver =
6eb0: 20 7a 49 6e 70 75 74 3b 20 7d 0a 20 20 72 65 74   zInput; }.  ret
6ec0: 75 72 6e 20 7a 52 65 73 75 6c 74 3b 0a 7d 0a 0a  urn zResult;.}..
6ed0: 2f 2a 0a 2a 2a 20 54 68 69 73 20 72 6f 75 74 69  /*.** This routi
6ee0: 6e 65 20 68 61 6e 64 6c 65 73 20 61 20 73 69 6e  ne handles a sin
6ef0: 67 6c 65 20 48 54 54 50 20 72 65 71 75 65 73 74  gle HTTP request
6f00: 20 77 68 69 63 68 20 69 73 20 63 6f 6d 69 6e 67   which is coming
6f10: 20 69 6e 20 6f 6e 0a 2a 2a 20 73 74 61 6e 64 61   in on.** standa
6f20: 72 64 20 69 6e 70 75 74 20 61 6e 64 20 77 68 69  rd input and whi
6f30: 63 68 20 72 65 70 6c 69 65 73 20 6f 6e 20 73 74  ch replies on st
6f40: 61 6e 64 61 72 64 20 6f 75 74 70 75 74 2e 0a 2a  andard output..*
6f50: 2a 0a 2a 2a 20 54 68 65 20 48 54 54 50 20 72 65  *.** The HTTP re
6f60: 71 75 65 73 74 20 69 73 20 72 65 61 64 20 66 72  quest is read fr
6f70: 6f 6d 20 73 74 61 6e 64 61 72 64 20 69 6e 70 75  om standard inpu
6f80: 74 20 61 6e 64 20 69 73 20 75 73 65 64 20 74 6f  t and is used to
6f90: 20 69 6e 69 74 69 61 6c 69 7a 65 0a 2a 2a 20 65   initialize.** e
6fa0: 6e 76 69 72 6f 6e 6d 65 6e 74 20 76 61 72 69 61  nvironment varia
6fb0: 62 6c 65 73 20 61 73 20 70 65 72 20 43 47 49 2e  bles as per CGI.
6fc0: 20 20 54 68 65 20 63 67 69 5f 69 6e 69 74 28 29    The cgi_init()
6fd0: 20 72 6f 75 74 69 6e 65 20 74 6f 20 63 6f 6d 70   routine to comp
6fe0: 6c 65 74 65 0a 2a 2a 20 74 68 65 20 73 65 74 75  lete.** the setu
6ff0: 70 2e 20 20 4f 6e 63 65 20 61 6c 6c 20 74 68 65  p.  Once all the
7000: 20 73 65 74 75 70 20 69 73 20 66 69 6e 69 73 68   setup is finish
7010: 65 64 2c 20 74 68 69 73 20 70 72 6f 63 65 64 75  ed, this procedu
7020: 72 65 20 72 65 74 75 72 6e 73 0a 2a 2a 20 61 6e  re returns.** an
7030: 64 20 73 75 62 73 65 71 75 65 6e 74 20 63 6f 64  d subsequent cod
7040: 65 20 68 61 6e 64 6c 65 73 20 74 68 65 20 61 63  e handles the ac
7050: 74 75 61 6c 20 67 65 6e 65 72 61 74 69 6f 6e 20  tual generation 
7060: 6f 66 20 74 68 65 20 77 65 62 70 61 67 65 2e 0a  of the webpage..
7070: 2a 2f 0a 76 6f 69 64 20 63 67 69 5f 68 61 6e 64  */.void cgi_hand
7080: 6c 65 5f 68 74 74 70 5f 72 65 71 75 65 73 74 28  le_http_request(
7090: 76 6f 69 64 29 7b 0a 20 20 63 68 61 72 20 2a 7a  void){.  char *z
70a0: 2c 20 2a 7a 54 6f 6b 65 6e 3b 0a 20 20 69 6e 74  , *zToken;.  int
70b0: 20 69 3b 0a 20 20 73 74 72 75 63 74 20 73 6f 63   i;.  struct soc
70c0: 6b 61 64 64 72 5f 69 6e 20 72 65 6d 6f 74 65 4e  kaddr_in remoteN
70d0: 61 6d 65 3b 0a 20 20 73 69 7a 65 5f 74 20 73 69  ame;.  size_t si
70e0: 7a 65 20 3d 20 73 69 7a 65 6f 66 28 73 74 72 75  ze = sizeof(stru
70f0: 63 74 20 73 6f 63 6b 61 64 64 72 5f 69 6e 29 3b  ct sockaddr_in);
7100: 0a 20 20 63 68 61 72 20 7a 4c 69 6e 65 5b 32 30  .  char zLine[20
7110: 30 30 5d 3b 20 20 20 20 20 2f 2a 20 41 20 73 69  00];     /* A si
7120: 6e 67 6c 65 20 6c 69 6e 65 20 6f 66 20 69 6e 70  ngle line of inp
7130: 75 74 2e 20 2a 2f 0a 0a 20 20 66 75 6c 6c 48 74  ut. */..  fullHt
7140: 74 70 52 65 70 6c 79 20 3d 20 31 3b 0a 20 20 69  tpReply = 1;.  i
7150: 66 28 20 66 67 65 74 73 28 7a 4c 69 6e 65 2c 20  f( fgets(zLine, 
7160: 73 69 7a 65 6f 66 28 7a 4c 69 6e 65 29 2c 20 73  sizeof(zLine), s
7170: 74 64 69 6e 29 3d 3d 30 20 29 7b 0a 20 20 20 20  tdin)==0 ){.    
7180: 6d 61 6c 66 6f 72 6d 65 64 5f 72 65 71 75 65 73  malformed_reques
7190: 74 28 29 3b 0a 20 20 7d 0a 20 20 7a 54 6f 6b 65  t();.  }.  zToke
71a0: 6e 20 3d 20 65 78 74 72 61 63 74 5f 74 6f 6b 65  n = extract_toke
71b0: 6e 28 7a 4c 69 6e 65 2c 20 26 7a 29 3b 0a 20 20  n(zLine, &z);.  
71c0: 69 66 28 20 7a 54 6f 6b 65 6e 3d 3d 30 20 29 7b  if( zToken==0 ){
71d0: 0a 20 20 20 20 6d 61 6c 66 6f 72 6d 65 64 5f 72  .    malformed_r
71e0: 65 71 75 65 73 74 28 29 3b 0a 20 20 7d 0a 20 20  equest();.  }.  
71f0: 69 66 28 20 73 74 72 63 6d 70 28 7a 54 6f 6b 65  if( strcmp(zToke
7200: 6e 2c 22 47 45 54 22 29 21 3d 30 20 26 26 20 73  n,"GET")!=0 && s
7210: 74 72 63 6d 70 28 7a 54 6f 6b 65 6e 2c 22 50 4f  trcmp(zToken,"PO
7220: 53 54 22 29 21 3d 30 0a 20 20 20 20 20 20 26 26  ST")!=0.      &&
7230: 20 73 74 72 63 6d 70 28 7a 54 6f 6b 65 6e 2c 22   strcmp(zToken,"
7240: 48 45 41 44 22 29 21 3d 30 20 29 7b 0a 20 20 20  HEAD")!=0 ){.   
7250: 20 6d 61 6c 66 6f 72 6d 65 64 5f 72 65 71 75 65   malformed_reque
7260: 73 74 28 29 3b 0a 20 20 7d 0a 20 20 63 67 69 5f  st();.  }.  cgi_
7270: 73 65 74 65 6e 76 28 22 47 41 54 45 57 41 59 5f  setenv("GATEWAY_
7280: 49 4e 54 45 52 46 41 43 45 22 2c 22 43 47 49 2f  INTERFACE","CGI/
7290: 31 2e 30 22 29 3b 0a 20 20 63 67 69 5f 73 65 74  1.0");.  cgi_set
72a0: 65 6e 76 28 22 52 45 51 55 45 53 54 5f 4d 45 54  env("REQUEST_MET
72b0: 48 4f 44 22 2c 7a 54 6f 6b 65 6e 29 3b 0a 20 20  HOD",zToken);.  
72c0: 7a 54 6f 6b 65 6e 20 3d 20 65 78 74 72 61 63 74  zToken = extract
72d0: 5f 74 6f 6b 65 6e 28 7a 2c 20 26 7a 29 3b 0a 20  _token(z, &z);. 
72e0: 20 69 66 28 20 7a 54 6f 6b 65 6e 3d 3d 30 20 29   if( zToken==0 )
72f0: 7b 0a 20 20 20 20 6d 61 6c 66 6f 72 6d 65 64 5f  {.    malformed_
7300: 72 65 71 75 65 73 74 28 29 3b 0a 20 20 7d 0a 20  request();.  }. 
7310: 20 63 67 69 5f 73 65 74 65 6e 76 28 22 52 45 51   cgi_setenv("REQ
7320: 55 45 53 54 5f 55 52 49 22 2c 20 7a 54 6f 6b 65  UEST_URI", zToke
7330: 6e 29 3b 0a 20 20 66 6f 72 28 69 3d 30 3b 20 7a  n);.  for(i=0; z
7340: 54 6f 6b 65 6e 5b 69 5d 20 26 26 20 7a 54 6f 6b  Token[i] && zTok
7350: 65 6e 5b 69 5d 21 3d 27 3f 27 3b 20 69 2b 2b 29  en[i]!='?'; i++)
7360: 7b 7d 0a 20 20 69 66 28 20 7a 54 6f 6b 65 6e 5b  {}.  if( zToken[
7370: 69 5d 20 29 20 7a 54 6f 6b 65 6e 5b 69 2b 2b 5d  i] ) zToken[i++]
7380: 20 3d 20 30 3b 0a 20 20 63 67 69 5f 73 65 74 65   = 0;.  cgi_sete
7390: 6e 76 28 22 50 41 54 48 5f 49 4e 46 4f 22 2c 20  nv("PATH_INFO", 
73a0: 7a 54 6f 6b 65 6e 29 3b 0a 20 20 63 67 69 5f 73  zToken);.  cgi_s
73b0: 65 74 65 6e 76 28 22 51 55 45 52 59 5f 53 54 52  etenv("QUERY_STR
73c0: 49 4e 47 22 2c 20 26 7a 54 6f 6b 65 6e 5b 69 5d  ING", &zToken[i]
73d0: 29 3b 0a 20 20 69 66 28 20 67 65 74 70 65 65 72  );.  if( getpeer
73e0: 6e 61 6d 65 28 66 69 6c 65 6e 6f 28 73 74 64 69  name(fileno(stdi
73f0: 6e 29 2c 20 28 73 74 72 75 63 74 20 73 6f 63 6b  n), (struct sock
7400: 61 64 64 72 2a 29 26 72 65 6d 6f 74 65 4e 61 6d  addr*)&remoteNam
7410: 65 2c 20 28 73 6f 63 6b 6c 65 6e 5f 74 2a 29 26  e, (socklen_t*)&
7420: 73 69 7a 65 29 3e 3d 30 20 29 7b 0a 20 20 20 20  size)>=0 ){.    
7430: 63 68 61 72 20 2a 7a 49 70 41 64 64 72 20 3d 20  char *zIpAddr = 
7440: 69 6e 65 74 5f 6e 74 6f 61 28 72 65 6d 6f 74 65  inet_ntoa(remote
7450: 4e 61 6d 65 2e 73 69 6e 5f 61 64 64 72 29 3b 0a  Name.sin_addr);.
7460: 20 20 20 20 63 67 69 5f 73 65 74 65 6e 76 28 22      cgi_setenv("
7470: 52 45 4d 4f 54 45 5f 41 44 44 52 22 2c 20 7a 49  REMOTE_ADDR", zI
7480: 70 41 64 64 72 29 3b 0a 0a 20 20 20 20 2f 2a 20  pAddr);..    /* 
7490: 53 65 74 20 74 68 65 20 47 6c 6f 62 61 6c 2e 7a  Set the Global.z
74a0: 49 70 41 64 64 72 20 76 61 72 69 61 62 6c 65 20  IpAddr variable 
74b0: 74 6f 20 74 68 65 20 73 65 72 76 65 72 20 77 65  to the server we
74c0: 20 61 72 65 20 74 61 6c 6b 69 6e 67 20 74 6f 2e   are talking to.
74d0: 0a 20 20 20 20 2a 2a 20 54 68 69 73 20 69 73 20  .    ** This is 
74e0: 75 73 65 64 20 74 6f 20 70 6f 70 75 6c 61 74 65  used to populate
74f0: 20 74 68 65 20 69 70 61 64 64 72 20 63 6f 6c 75   the ipaddr colu
7500: 6d 6e 20 6f 66 20 74 68 65 20 72 63 76 66 72 6f  mn of the rcvfro
7510: 6d 20 74 61 62 6c 65 2c 0a 20 20 20 20 2a 2a 20  m table,.    ** 
7520: 69 66 20 61 6e 79 20 66 69 6c 65 73 20 61 72 65  if any files are
7530: 20 72 65 63 65 69 76 65 64 20 66 72 6f 6d 20 74   received from t
7540: 68 65 20 63 6f 6e 6e 65 63 74 65 64 20 63 6c 69  he connected cli
7550: 65 6e 74 2e 0a 20 20 20 20 2a 2f 0a 20 20 20 20  ent..    */.    
7560: 67 2e 7a 49 70 41 64 64 72 20 3d 20 6d 70 72 69  g.zIpAddr = mpri
7570: 6e 74 66 28 22 25 73 22 2c 20 7a 49 70 41 64 64  ntf("%s", zIpAdd
7580: 72 29 3b 0a 20 20 7d 0a 20 0a 20 20 2f 2a 20 47  r);.  }. .  /* G
7590: 65 74 20 61 6c 6c 20 74 68 65 20 6f 70 74 69 6f  et all the optio
75a0: 6e 61 6c 20 66 69 65 6c 64 73 20 74 68 61 74 20  nal fields that 
75b0: 66 6f 6c 6c 6f 77 20 74 68 65 20 66 69 72 73 74  follow the first
75c0: 20 6c 69 6e 65 2e 0a 20 20 2a 2f 0a 20 20 77 68   line..  */.  wh
75d0: 69 6c 65 28 20 66 67 65 74 73 28 7a 4c 69 6e 65  ile( fgets(zLine
75e0: 2c 73 69 7a 65 6f 66 28 7a 4c 69 6e 65 29 2c 73  ,sizeof(zLine),s
75f0: 74 64 69 6e 29 20 29 7b 0a 20 20 20 20 63 68 61  tdin) ){.    cha
7600: 72 20 2a 7a 46 69 65 6c 64 4e 61 6d 65 3b 0a 20  r *zFieldName;. 
7610: 20 20 20 63 68 61 72 20 2a 7a 56 61 6c 3b 0a 0a     char *zVal;..
7620: 20 20 20 20 7a 46 69 65 6c 64 4e 61 6d 65 20 3d      zFieldName =
7630: 20 65 78 74 72 61 63 74 5f 74 6f 6b 65 6e 28 7a   extract_token(z
7640: 4c 69 6e 65 2c 26 7a 56 61 6c 29 3b 0a 20 20 20  Line,&zVal);.   
7650: 20 69 66 28 20 7a 46 69 65 6c 64 4e 61 6d 65 3d   if( zFieldName=
7660: 3d 30 20 7c 7c 20 2a 7a 46 69 65 6c 64 4e 61 6d  =0 || *zFieldNam
7670: 65 3d 3d 30 20 29 20 62 72 65 61 6b 3b 0a 20 20  e==0 ) break;.  
7680: 20 20 77 68 69 6c 65 28 20 69 73 73 70 61 63 65    while( isspace
7690: 28 2a 7a 56 61 6c 29 20 29 7b 20 7a 56 61 6c 2b  (*zVal) ){ zVal+
76a0: 2b 3b 20 7d 0a 20 20 20 20 69 20 3d 20 73 74 72  +; }.    i = str
76b0: 6c 65 6e 28 7a 56 61 6c 29 3b 0a 20 20 20 20 77  len(zVal);.    w
76c0: 68 69 6c 65 28 20 69 3e 30 20 26 26 20 69 73 73  hile( i>0 && iss
76d0: 70 61 63 65 28 7a 56 61 6c 5b 69 2d 31 5d 29 20  pace(zVal[i-1]) 
76e0: 29 7b 20 69 2d 2d 3b 20 7d 0a 20 20 20 20 7a 56  ){ i--; }.    zV
76f0: 61 6c 5b 69 5d 20 3d 20 30 3b 0a 20 20 20 20 66  al[i] = 0;.    f
7700: 6f 72 28 69 3d 30 3b 20 7a 46 69 65 6c 64 4e 61  or(i=0; zFieldNa
7710: 6d 65 5b 69 5d 3b 20 69 2b 2b 29 7b 20 7a 46 69  me[i]; i++){ zFi
7720: 65 6c 64 4e 61 6d 65 5b 69 5d 20 3d 20 74 6f 6c  eldName[i] = tol
7730: 6f 77 65 72 28 7a 46 69 65 6c 64 4e 61 6d 65 5b  ower(zFieldName[
7740: 69 5d 29 3b 20 7d 0a 20 20 20 20 69 66 28 20 73  i]); }.    if( s
7750: 74 72 63 6d 70 28 7a 46 69 65 6c 64 4e 61 6d 65  trcmp(zFieldName
7760: 2c 22 75 73 65 72 2d 61 67 65 6e 74 3a 22 29 3d  ,"user-agent:")=
7770: 3d 30 20 29 7b 0a 20 20 20 20 20 20 63 67 69 5f  =0 ){.      cgi_
7780: 73 65 74 65 6e 76 28 22 48 54 54 50 5f 55 53 45  setenv("HTTP_USE
7790: 52 5f 41 47 45 4e 54 22 2c 20 7a 56 61 6c 29 3b  R_AGENT", zVal);
77a0: 0a 20 20 20 20 7d 65 6c 73 65 20 69 66 28 20 73  .    }else if( s
77b0: 74 72 63 6d 70 28 7a 46 69 65 6c 64 4e 61 6d 65  trcmp(zFieldName
77c0: 2c 22 63 6f 6e 74 65 6e 74 2d 6c 65 6e 67 74 68  ,"content-length
77d0: 3a 22 29 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20  :")==0 ){.      
77e0: 63 67 69 5f 73 65 74 65 6e 76 28 22 43 4f 4e 54  cgi_setenv("CONT
77f0: 45 4e 54 5f 4c 45 4e 47 54 48 22 2c 20 7a 56 61  ENT_LENGTH", zVa
7800: 6c 29 3b 0a 20 20 20 20 7d 65 6c 73 65 20 69 66  l);.    }else if
7810: 28 20 73 74 72 63 6d 70 28 7a 46 69 65 6c 64 4e  ( strcmp(zFieldN
7820: 61 6d 65 2c 22 72 65 66 65 72 65 72 3a 22 29 3d  ame,"referer:")=
7830: 3d 30 20 29 7b 0a 20 20 20 20 20 20 63 67 69 5f  =0 ){.      cgi_
7840: 73 65 74 65 6e 76 28 22 48 54 54 50 5f 52 45 46  setenv("HTTP_REF
7850: 45 52 45 52 22 2c 20 7a 56 61 6c 29 3b 0a 20 20  ERER", zVal);.  
7860: 20 20 7d 65 6c 73 65 20 69 66 28 20 73 74 72 63    }else if( strc
7870: 6d 70 28 7a 46 69 65 6c 64 4e 61 6d 65 2c 22 68  mp(zFieldName,"h
7880: 6f 73 74 3a 22 29 3d 3d 30 20 29 7b 0a 20 20 20  ost:")==0 ){.   
7890: 20 20 20 63 67 69 5f 73 65 74 65 6e 76 28 22 48     cgi_setenv("H
78a0: 54 54 50 5f 48 4f 53 54 22 2c 20 7a 56 61 6c 29  TTP_HOST", zVal)
78b0: 3b 0a 20 20 20 20 7d 65 6c 73 65 20 69 66 28 20  ;.    }else if( 
78c0: 73 74 72 63 6d 70 28 7a 46 69 65 6c 64 4e 61 6d  strcmp(zFieldNam
78d0: 65 2c 22 63 6f 6e 74 65 6e 74 2d 74 79 70 65 3a  e,"content-type:
78e0: 22 29 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 63  ")==0 ){.      c
78f0: 67 69 5f 73 65 74 65 6e 76 28 22 43 4f 4e 54 45  gi_setenv("CONTE
7900: 4e 54 5f 54 59 50 45 22 2c 20 7a 56 61 6c 29 3b  NT_TYPE", zVal);
7910: 0a 20 20 20 20 7d 65 6c 73 65 20 69 66 28 20 73  .    }else if( s
7920: 74 72 63 6d 70 28 7a 46 69 65 6c 64 4e 61 6d 65  trcmp(zFieldName
7930: 2c 22 63 6f 6f 6b 69 65 3a 22 29 3d 3d 30 20 29  ,"cookie:")==0 )
7940: 7b 0a 20 20 20 20 20 20 63 67 69 5f 73 65 74 65  {.      cgi_sete
7950: 6e 76 28 22 48 54 54 50 5f 43 4f 4f 4b 49 45 22  nv("HTTP_COOKIE"
7960: 2c 20 7a 56 61 6c 29 3b 0a 20 20 20 20 7d 65 6c  , zVal);.    }el
7970: 73 65 20 69 66 28 20 73 74 72 63 6d 70 28 7a 46  se if( strcmp(zF
7980: 69 65 6c 64 4e 61 6d 65 2c 22 69 66 2d 6e 6f 6e  ieldName,"if-non
7990: 65 2d 6d 61 74 63 68 3a 22 29 3d 3d 30 20 29 7b  e-match:")==0 ){
79a0: 0a 20 20 20 20 20 20 63 67 69 5f 73 65 74 65 6e  .      cgi_seten
79b0: 76 28 22 48 54 54 50 5f 49 46 5f 4e 4f 4e 45 5f  v("HTTP_IF_NONE_
79c0: 4d 41 54 43 48 22 2c 20 7a 56 61 6c 29 3b 0a 20  MATCH", zVal);. 
79d0: 20 20 20 7d 65 6c 73 65 20 69 66 28 20 73 74 72     }else if( str
79e0: 63 6d 70 28 7a 46 69 65 6c 64 4e 61 6d 65 2c 22  cmp(zFieldName,"
79f0: 69 66 2d 6d 6f 64 69 66 69 65 64 2d 73 69 6e 63  if-modified-sinc
7a00: 65 3a 22 29 3d 3d 30 20 29 7b 0a 20 20 20 20 20  e:")==0 ){.     
7a10: 20 63 67 69 5f 73 65 74 65 6e 76 28 22 48 54 54   cgi_setenv("HTT
7a20: 50 5f 49 46 5f 4d 4f 44 49 46 49 45 44 5f 53 49  P_IF_MODIFIED_SI
7a30: 4e 43 45 22 2c 20 7a 56 61 6c 29 3b 0a 20 20 20  NCE", zVal);.   
7a40: 20 7d 0a 20 20 7d 0a 0a 20 20 63 67 69 5f 69 6e   }.  }..  cgi_in
7a50: 69 74 28 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 4d  it();.}../*.** M
7a60: 61 78 69 6d 75 6d 20 6e 75 6d 62 65 72 20 6f 66  aximum number of
7a70: 20 63 68 69 6c 64 20 70 72 6f 63 65 73 73 65 73   child processes
7a80: 20 74 68 61 74 20 77 65 20 63 61 6e 20 68 61 76   that we can hav
7a90: 65 20 72 75 6e 6e 69 6e 67 0a 2a 2a 20 61 74 20  e running.** at 
7aa0: 6f 6e 65 20 74 69 6d 65 20 62 65 66 6f 72 65 20  one time before 
7ab0: 77 65 20 73 74 61 72 74 20 73 6c 6f 77 69 6e 67  we start slowing
7ac0: 20 74 68 69 6e 67 73 20 64 6f 77 6e 2e 0a 2a 2f   things down..*/
7ad0: 0a 23 64 65 66 69 6e 65 20 4d 41 58 5f 50 41 52  .#define MAX_PAR
7ae0: 41 4c 4c 45 4c 20 32 0a 0a 2f 2a 0a 2a 2a 20 49  ALLEL 2../*.** I
7af0: 6d 70 6c 65 6d 65 6e 74 20 61 6e 20 48 54 54 50  mplement an HTTP
7b00: 20 73 65 72 76 65 72 20 64 61 65 6d 6f 6e 20 6c   server daemon l
7b10: 69 73 74 65 6e 69 6e 67 20 6f 6e 20 70 6f 72 74  istening on port
7b20: 20 69 50 6f 72 74 2e 0a 2a 2a 0a 2a 2a 20 41 73   iPort..**.** As
7b30: 20 6e 65 77 20 63 6f 6e 6e 65 63 74 69 6f 6e 73   new connections
7b40: 20 61 72 72 69 76 65 2c 20 66 6f 72 6b 20 61 20   arrive, fork a 
7b50: 63 68 69 6c 64 20 61 6e 64 20 6c 65 74 20 63 68  child and let ch
7b60: 69 6c 64 20 72 65 74 75 72 6e 0a 2a 2a 20 6f 75  ild return.** ou
7b70: 74 20 6f 66 20 74 68 69 73 20 70 72 6f 63 65 64  t of this proced
7b80: 75 72 65 20 63 61 6c 6c 2e 20 20 54 68 65 20 63  ure call.  The c
7b90: 68 69 6c 64 20 77 69 6c 6c 20 68 61 6e 64 6c 65  hild will handle
7ba0: 20 74 68 65 20 72 65 71 75 65 73 74 2e 0a 2a 2a   the request..**
7bb0: 20 54 68 65 20 70 61 72 65 6e 74 20 6e 65 76 65   The parent neve
7bc0: 72 20 72 65 74 75 72 6e 73 20 66 72 6f 6d 20 74  r returns from t
7bd0: 68 69 73 20 70 72 6f 63 65 64 75 72 65 2e 0a 2a  his procedure..*
7be0: 2f 0a 76 6f 69 64 20 63 67 69 5f 68 74 74 70 5f  /.void cgi_http_
7bf0: 73 65 72 76 65 72 28 69 6e 74 20 69 50 6f 72 74  server(int iPort
7c00: 29 7b 0a 23 69 66 64 65 66 20 5f 5f 4d 49 4e 47  ){.#ifdef __MING
7c10: 57 33 32 5f 5f 0a 20 20 66 70 72 69 6e 74 66 28  W32__.  fprintf(
7c20: 73 74 64 65 72 72 2c 22 73 65 72 76 65 72 20 6e  stderr,"server n
7c30: 6f 74 20 79 65 74 20 61 76 61 69 6c 61 62 6c 65  ot yet available
7c40: 20 69 6e 20 77 69 6e 64 6f 77 73 20 76 65 72 73   in windows vers
7c50: 69 6f 6e 20 6f 66 20 66 6f 73 73 69 6c 5c 6e 22  ion of fossil\n"
7c60: 29 3b 0a 20 20 65 78 69 74 28 31 29 3b 0a 23 65  );.  exit(1);.#e
7c70: 6c 73 65 0a 20 20 69 6e 74 20 6c 69 73 74 65 6e  lse.  int listen
7c80: 65 72 3b 20 20 20 20 20 20 20 20 20 20 20 20 20  er;             
7c90: 20 20 20 2f 2a 20 54 68 65 20 73 65 72 76 65 72     /* The server
7ca0: 20 73 6f 63 6b 65 74 20 2a 2f 0a 20 20 69 6e 74   socket */.  int
7cb0: 20 63 6f 6e 6e 65 63 74 69 6f 6e 3b 20 20 20 20   connection;    
7cc0: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 41 20 73            /* A s
7cd0: 6f 63 6b 65 74 20 66 6f 72 20 65 61 63 68 20 69  ocket for each i
7ce0: 6e 64 69 76 69 64 75 61 6c 20 63 6f 6e 6e 65 63  ndividual connec
7cf0: 74 69 6f 6e 20 2a 2f 0a 20 20 66 64 5f 73 65 74  tion */.  fd_set
7d00: 20 72 65 61 64 66 64 73 3b 20 20 20 20 20 20 20   readfds;       
7d10: 20 20 20 20 20 20 20 2f 2a 20 53 65 74 20 6f 66         /* Set of
7d20: 20 66 69 6c 65 20 64 65 73 63 72 69 70 74 6f 72   file descriptor
7d30: 73 20 66 6f 72 20 73 65 6c 65 63 74 28 29 20 2a  s for select() *
7d40: 2f 0a 20 20 73 69 7a 65 5f 74 20 6c 65 6e 61 64  /.  size_t lenad
7d50: 64 72 3b 20 20 20 20 20 20 20 20 20 20 20 20 20  dr;             
7d60: 20 2f 2a 20 4c 65 6e 67 74 68 20 6f 66 20 74 68   /* Length of th
7d70: 65 20 69 6e 61 64 64 72 20 73 74 72 75 63 74 75  e inaddr structu
7d80: 72 65 20 2a 2f 0a 20 20 69 6e 74 20 63 68 69 6c  re */.  int chil
7d90: 64 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  d;              
7da0: 20 20 20 20 20 2f 2a 20 50 49 44 20 6f 66 20 74       /* PID of t
7db0: 68 65 20 63 68 69 6c 64 20 70 72 6f 63 65 73 73  he child process
7dc0: 20 2a 2f 0a 20 20 69 6e 74 20 6e 63 68 69 6c 64   */.  int nchild
7dd0: 72 65 6e 20 3d 20 30 3b 20 20 20 20 20 20 20 20  ren = 0;        
7de0: 20 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f 66 20     /* Number of 
7df0: 63 68 69 6c 64 20 70 72 6f 63 65 73 73 65 73 20  child processes 
7e00: 2a 2f 0a 20 20 73 74 72 75 63 74 20 74 69 6d 65  */.  struct time
7e10: 76 61 6c 20 64 65 6c 61 79 3b 20 20 20 20 20 20  val delay;      
7e20: 20 20 2f 2a 20 48 6f 77 20 6c 6f 6e 67 20 74 6f    /* How long to
7e30: 20 77 61 69 74 20 69 6e 73 69 64 65 20 73 65 6c   wait inside sel
7e40: 65 63 74 28 29 20 2a 2f 0a 20 20 73 74 72 75 63  ect() */.  struc
7e50: 74 20 73 6f 63 6b 61 64 64 72 5f 69 6e 20 69 6e  t sockaddr_in in
7e60: 61 64 64 72 3b 20 20 20 2f 2a 20 54 68 65 20 73  addr;   /* The s
7e70: 6f 63 6b 65 74 20 61 64 64 72 65 73 73 20 2a 2f  ocket address */
7e80: 0a 20 20 69 6e 74 20 6f 70 74 20 3d 20 31 3b 20  .  int opt = 1; 
7e90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7ea0: 2f 2a 20 73 65 74 73 6f 63 6b 6f 70 74 20 66 6c  /* setsockopt fl
7eb0: 61 67 20 2a 2f 0a 0a 20 20 6d 65 6d 73 65 74 28  ag */..  memset(
7ec0: 26 69 6e 61 64 64 72 2c 20 30 2c 20 73 69 7a 65  &inaddr, 0, size
7ed0: 6f 66 28 69 6e 61 64 64 72 29 29 3b 0a 20 20 69  of(inaddr));.  i
7ee0: 6e 61 64 64 72 2e 73 69 6e 5f 66 61 6d 69 6c 79  naddr.sin_family
7ef0: 20 3d 20 41 46 5f 49 4e 45 54 3b 0a 20 20 69 6e   = AF_INET;.  in
7f00: 61 64 64 72 2e 73 69 6e 5f 61 64 64 72 2e 73 5f  addr.sin_addr.s_
7f10: 61 64 64 72 20 3d 20 49 4e 41 44 44 52 5f 41 4e  addr = INADDR_AN
7f20: 59 3b 0a 20 20 69 6e 61 64 64 72 2e 73 69 6e 5f  Y;.  inaddr.sin_
7f30: 70 6f 72 74 20 3d 20 68 74 6f 6e 73 28 69 50 6f  port = htons(iPo
7f40: 72 74 29 3b 0a 20 20 6c 69 73 74 65 6e 65 72 20  rt);.  listener 
7f50: 3d 20 73 6f 63 6b 65 74 28 41 46 5f 49 4e 45 54  = socket(AF_INET
7f60: 2c 20 53 4f 43 4b 5f 53 54 52 45 41 4d 2c 20 30  , SOCK_STREAM, 0
7f70: 29 3b 0a 20 20 69 66 28 20 6c 69 73 74 65 6e 65  );.  if( listene
7f80: 72 3c 30 20 29 7b 0a 20 20 20 20 66 70 72 69 6e  r<0 ){.    fprin
7f90: 74 66 28 73 74 64 65 72 72 2c 22 43 61 6e 27 74  tf(stderr,"Can't
7fa0: 20 63 72 65 61 74 65 20 61 20 73 6f 63 6b 65 74   create a socket
7fb0: 5c 6e 22 29 3b 0a 20 20 20 20 65 78 69 74 28 31  \n");.    exit(1
7fc0: 29 3b 0a 20 20 7d 0a 0a 20 20 2f 2a 20 69 66 20  );.  }..  /* if 
7fd0: 77 65 20 63 61 6e 27 74 20 74 65 72 6d 69 6e 61  we can't termina
7fe0: 74 65 20 6e 69 63 65 6c 79 2c 20 61 74 20 6c 65  te nicely, at le
7ff0: 61 73 74 20 61 6c 6c 6f 77 20 74 68 65 20 73 6f  ast allow the so
8000: 63 6b 65 74 20 74 6f 20 62 65 20 72 65 75 73 65  cket to be reuse
8010: 64 20 2a 2f 0a 20 20 73 65 74 73 6f 63 6b 6f 70  d */.  setsockop
8020: 74 28 6c 69 73 74 65 6e 65 72 2c 53 4f 4c 5f 53  t(listener,SOL_S
8030: 4f 43 4b 45 54 2c 53 4f 5f 52 45 55 53 45 41 44  OCKET,SO_REUSEAD
8040: 44 52 2c 26 6f 70 74 2c 73 69 7a 65 6f 66 28 6f  DR,&opt,sizeof(o
8050: 70 74 29 29 3b 0a 0a 20 20 69 66 28 20 62 69 6e  pt));..  if( bin
8060: 64 28 6c 69 73 74 65 6e 65 72 2c 20 28 73 74 72  d(listener, (str
8070: 75 63 74 20 73 6f 63 6b 61 64 64 72 2a 29 26 69  uct sockaddr*)&i
8080: 6e 61 64 64 72 2c 20 73 69 7a 65 6f 66 28 69 6e  naddr, sizeof(in
8090: 61 64 64 72 29 29 3c 30 20 29 7b 0a 20 20 20 20  addr))<0 ){.    
80a0: 66 70 72 69 6e 74 66 28 73 74 64 65 72 72 2c 22  fprintf(stderr,"
80b0: 43 61 6e 27 74 20 62 69 6e 64 20 74 6f 20 70 6f  Can't bind to po
80c0: 72 74 20 25 64 5c 6e 22 2c 20 69 50 6f 72 74 29  rt %d\n", iPort)
80d0: 3b 0a 20 20 20 20 65 78 69 74 28 31 29 3b 0a 20  ;.    exit(1);. 
80e0: 20 7d 0a 20 20 6c 69 73 74 65 6e 28 6c 69 73 74   }.  listen(list
80f0: 65 6e 65 72 2c 31 30 29 3b 0a 20 20 77 68 69 6c  ener,10);.  whil
8100: 65 28 20 31 20 29 7b 0a 20 20 20 20 69 66 28 20  e( 1 ){.    if( 
8110: 6e 63 68 69 6c 64 72 65 6e 3e 4d 41 58 5f 50 41  nchildren>MAX_PA
8120: 52 41 4c 4c 45 4c 20 29 7b 0a 20 20 20 20 20 20  RALLEL ){.      
8130: 2f 2a 20 53 6c 6f 77 20 64 6f 77 6e 20 69 66 20  /* Slow down if 
8140: 63 6f 6e 6e 65 63 74 69 6f 6e 73 20 61 72 65 20  connections are 
8150: 61 72 72 69 76 69 6e 67 20 74 6f 6f 20 66 61 73  arriving too fas
8160: 74 20 2a 2f 0a 20 20 20 20 20 20 73 6c 65 65 70  t */.      sleep
8170: 28 20 6e 63 68 69 6c 64 72 65 6e 2d 4d 41 58 5f  ( nchildren-MAX_
8180: 50 41 52 41 4c 4c 45 4c 20 29 3b 0a 20 20 20 20  PARALLEL );.    
8190: 7d 0a 20 20 20 20 64 65 6c 61 79 2e 74 76 5f 73  }.    delay.tv_s
81a0: 65 63 20 3d 20 36 30 3b 0a 20 20 20 20 64 65 6c  ec = 60;.    del
81b0: 61 79 2e 74 76 5f 75 73 65 63 20 3d 20 30 3b 0a  ay.tv_usec = 0;.
81c0: 20 20 20 20 46 44 5f 5a 45 52 4f 28 26 72 65 61      FD_ZERO(&rea
81d0: 64 66 64 73 29 3b 0a 20 20 20 20 46 44 5f 53 45  dfds);.    FD_SE
81e0: 54 28 20 6c 69 73 74 65 6e 65 72 2c 20 26 72 65  T( listener, &re
81f0: 61 64 66 64 73 29 3b 0a 20 20 20 20 69 66 28 20  adfds);.    if( 
8200: 73 65 6c 65 63 74 28 20 6c 69 73 74 65 6e 65 72  select( listener
8210: 2b 31 2c 20 26 72 65 61 64 66 64 73 2c 20 30 2c  +1, &readfds, 0,
8220: 20 30 2c 20 26 64 65 6c 61 79 29 20 29 7b 0a 20   0, &delay) ){. 
8230: 20 20 20 20 20 6c 65 6e 61 64 64 72 20 3d 20 73       lenaddr = s
8240: 69 7a 65 6f 66 28 69 6e 61 64 64 72 29 3b 0a 20  izeof(inaddr);. 
8250: 20 20 20 20 20 63 6f 6e 6e 65 63 74 69 6f 6e 20       connection 
8260: 3d 20 61 63 63 65 70 74 28 6c 69 73 74 65 6e 65  = accept(listene
8270: 72 2c 20 28 73 74 72 75 63 74 20 73 6f 63 6b 61  r, (struct socka
8280: 64 64 72 2a 29 26 69 6e 61 64 64 72 2c 20 28 73  ddr*)&inaddr, (s
8290: 6f 63 6b 6c 65 6e 5f 74 2a 29 20 26 6c 65 6e 61  ocklen_t*) &lena
82a0: 64 64 72 29 3b 0a 20 20 20 20 20 20 69 66 28 20  ddr);.      if( 
82b0: 63 6f 6e 6e 65 63 74 69 6f 6e 3e 3d 30 20 29 7b  connection>=0 ){
82c0: 0a 20 20 20 20 20 20 20 20 63 68 69 6c 64 20 3d  .        child =
82d0: 20 66 6f 72 6b 28 29 3b 0a 20 20 20 20 20 20 20   fork();.       
82e0: 20 69 66 28 20 63 68 69 6c 64 21 3d 30 20 29 7b   if( child!=0 ){
82f0: 0a 20 20 20 20 20 20 20 20 20 20 69 66 28 20 63  .          if( c
8300: 68 69 6c 64 3e 30 20 29 20 6e 63 68 69 6c 64 72  hild>0 ) nchildr
8310: 65 6e 2b 2b 3b 0a 20 20 20 20 20 20 20 20 20 20  en++;.          
8320: 63 6c 6f 73 65 28 63 6f 6e 6e 65 63 74 69 6f 6e  close(connection
8330: 29 3b 0a 20 20 20 20 20 20 20 20 7d 65 6c 73 65  );.        }else
8340: 7b 0a 20 20 20 20 20 20 20 20 20 20 63 6c 6f 73  {.          clos
8350: 65 28 30 29 3b 0a 20 20 20 20 20 20 20 20 20 20  e(0);.          
8360: 64 75 70 28 63 6f 6e 6e 65 63 74 69 6f 6e 29 3b  dup(connection);
8370: 0a 20 20 20 20 20 20 20 20 20 20 63 6c 6f 73 65  .          close
8380: 28 31 29 3b 0a 20 20 20 20 20 20 20 20 20 20 64  (1);.          d
8390: 75 70 28 63 6f 6e 6e 65 63 74 69 6f 6e 29 3b 0a  up(connection);.
83a0: 20 20 20 20 20 20 20 20 20 20 69 66 28 20 21 67            if( !g
83b0: 2e 66 48 74 74 70 54 72 61 63 65 20 29 7b 0a 20  .fHttpTrace ){. 
83c0: 20 20 20 20 20 20 20 20 20 20 20 63 6c 6f 73 65             close
83d0: 28 32 29 3b 0a 20 20 20 20 20 20 20 20 20 20 20  (2);.           
83e0: 20 64 75 70 28 63 6f 6e 6e 65 63 74 69 6f 6e 29   dup(connection)
83f0: 3b 0a 20 20 20 20 20 20 20 20 20 20 7d 0a 20 20  ;.          }.  
8400: 20 20 20 20 20 20 20 20 63 6c 6f 73 65 28 63 6f          close(co
8410: 6e 6e 65 63 74 69 6f 6e 29 3b 0a 20 20 20 20 20  nnection);.     
8420: 20 20 20 20 20 72 65 74 75 72 6e 3b 0a 20 20 20       return;.   
8430: 20 20 20 20 20 7d 0a 20 20 20 20 20 20 7d 0a 20       }.      }. 
8440: 20 20 20 7d 0a 20 20 20 20 2f 2a 20 42 75 72 79     }.    /* Bury
8450: 20 64 65 61 64 20 63 68 69 6c 64 72 65 6e 20 2a   dead children *
8460: 2f 0a 20 20 20 20 77 68 69 6c 65 28 20 77 61 69  /.    while( wai
8470: 74 70 69 64 28 30 2c 20 30 2c 20 57 4e 4f 48 41  tpid(0, 0, WNOHA
8480: 4e 47 29 3e 30 20 29 7b 0a 20 20 20 20 20 20 6e  NG)>0 ){.      n
8490: 63 68 69 6c 64 72 65 6e 2d 2d 3b 0a 20 20 20 20  children--;.    
84a0: 7d 0a 20 20 7d 0a 20 20 2f 2a 20 4e 4f 54 20 52  }.  }.  /* NOT R
84b0: 45 41 43 48 45 44 20 2a 2f 20 20 0a 20 20 65 78  EACHED */  .  ex
84c0: 69 74 28 31 29 3b 0a 23 65 6e 64 69 66 0a 7d 0a  it(1);.#endif.}.
84d0: 0a 2f 2a 0a 2a 2a 20 4e 61 6d 65 20 6f 66 20 64  ./*.** Name of d
84e0: 61 79 73 20 61 6e 64 20 6d 6f 6e 74 68 73 2e 0a  ays and months..
84f0: 2a 2f 0a 73 74 61 74 69 63 20 63 6f 6e 73 74 20  */.static const 
8500: 63 68 61 72 20 2a 61 7a 44 61 79 73 5b 5d 20 3d  char *azDays[] =
8510: 0a 20 20 20 20 7b 22 53 75 6e 22 2c 20 22 4d 6f  .    {"Sun", "Mo
8520: 6e 22 2c 20 22 54 75 65 22 2c 20 22 57 65 64 22  n", "Tue", "Wed"
8530: 2c 20 22 54 68 75 22 2c 20 22 46 72 69 22 2c 20  , "Thu", "Fri", 
8540: 22 53 61 74 22 2c 20 30 7d 3b 0a 73 74 61 74 69  "Sat", 0};.stati
8550: 63 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 61 7a  c const char *az
8560: 4d 6f 6e 74 68 73 5b 5d 20 3d 0a 20 20 20 20 7b  Months[] =.    {
8570: 22 4a 61 6e 22 2c 20 22 46 65 62 22 2c 20 22 4d  "Jan", "Feb", "M
8580: 61 72 22 2c 20 22 41 70 72 22 2c 20 22 4d 61 79  ar", "Apr", "May
8590: 22 2c 20 22 4a 75 6e 22 2c 0a 20 20 20 20 20 22  ", "Jun",.     "
85a0: 4a 75 6c 22 2c 20 22 41 75 67 22 2c 20 22 53 65  Jul", "Aug", "Se
85b0: 70 22 2c 20 22 4f 63 74 22 2c 20 22 4e 6f 76 22  p", "Oct", "Nov"
85c0: 2c 20 22 44 65 63 22 2c 20 30 7d 3b 0a 0a 0a 2f  , "Dec", 0};.../
85d0: 2a 0a 2a 2a 20 52 65 74 75 72 6e 73 20 61 6e 20  *.** Returns an 
85e0: 52 46 43 38 32 32 2d 66 6f 72 6d 61 74 74 65 64  RFC822-formatted
85f0: 20 74 69 6d 65 20 73 74 72 69 6e 67 20 73 75 69   time string sui
8600: 74 61 62 6c 65 20 66 6f 72 20 48 54 54 50 20 68  table for HTTP h
8610: 65 61 64 65 72 73 2c 20 61 6d 6f 6e 67 0a 2a 2a  eaders, among.**
8620: 20 6f 74 68 65 72 20 74 68 69 6e 67 73 2e 0a 2a   other things..*
8630: 2a 20 52 65 74 75 72 6e 65 64 20 74 69 6d 65 7a  * Returned timez
8640: 6f 6e 65 20 69 73 20 61 6c 77 61 79 73 20 47 4d  one is always GM
8650: 54 20 61 73 20 72 65 71 75 69 72 65 64 20 62 79  T as required by
8660: 20 48 54 54 50 2f 31 2e 31 20 73 70 65 63 69 66   HTTP/1.1 specif
8670: 69 63 61 74 69 6f 6e 2e 0a 2a 2a 0a 2a 2a 20 53  ication..**.** S
8680: 65 65 20 68 74 74 70 3a 2f 2f 77 77 77 2e 66 61  ee http://www.fa
8690: 71 73 2e 6f 72 67 2f 72 66 63 73 2f 72 66 63 38  qs.org/rfcs/rfc8
86a0: 32 32 2e 68 74 6d 6c 2c 20 73 65 63 74 69 6f 6e  22.html, section
86b0: 20 35 0a 2a 2a 20 61 6e 64 20 68 74 74 70 3a 2f   5.** and http:/
86c0: 2f 77 77 77 2e 66 61 71 73 2e 6f 72 67 2f 72 66  /www.faqs.org/rf
86d0: 63 73 2f 72 66 63 32 36 31 36 2e 68 74 6d 6c 2c  cs/rfc2616.html,
86e0: 20 73 65 63 74 69 6f 6e 20 33 2e 33 2e 0a 2a 2f   section 3.3..*/
86f0: 0a 63 68 61 72 20 2a 63 67 69 5f 72 66 63 38 32  .char *cgi_rfc82
8700: 32 5f 64 61 74 65 73 74 61 6d 70 28 74 69 6d 65  2_datestamp(time
8710: 5f 74 20 6e 6f 77 29 7b 0a 20 20 73 74 72 75 63  _t now){.  struc
8720: 74 20 74 6d 20 2a 70 54 6d 3b 0a 20 20 70 54 6d  t tm *pTm;.  pTm
8730: 20 3d 20 67 6d 74 69 6d 65 28 26 6e 6f 77 29 3b   = gmtime(&now);
8740: 0a 20 20 69 66 28 20 70 54 6d 3d 3d 30 20 29 20  .  if( pTm==0 ) 
8750: 72 65 74 75 72 6e 20 22 22 3b 0a 20 20 72 65 74  return "";.  ret
8760: 75 72 6e 20 6d 70 72 69 6e 74 66 28 22 25 73 2c  urn mprintf("%s,
8770: 20 25 64 20 25 73 20 25 30 32 64 20 25 30 32 64   %d %s %02d %02d
8780: 3a 25 30 32 64 3a 25 30 32 64 20 47 4d 54 22 2c  :%02d:%02d GMT",
8790: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
87a0: 20 20 61 7a 44 61 79 73 5b 70 54 6d 2d 3e 74 6d    azDays[pTm->tm
87b0: 5f 77 64 61 79 5d 2c 20 70 54 6d 2d 3e 74 6d 5f  _wday], pTm->tm_
87c0: 6d 64 61 79 2c 20 61 7a 4d 6f 6e 74 68 73 5b 70  mday, azMonths[p
87d0: 54 6d 2d 3e 74 6d 5f 6d 6f 6e 5d 2c 0a 20 20 20  Tm->tm_mon],.   
87e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 70 54                pT
87f0: 6d 2d 3e 74 6d 5f 79 65 61 72 2b 31 39 30 30 2c  m->tm_year+1900,
8800: 20 70 54 6d 2d 3e 74 6d 5f 68 6f 75 72 2c 20 70   pTm->tm_hour, p
8810: 54 6d 2d 3e 74 6d 5f 6d 69 6e 2c 20 70 54 6d 2d  Tm->tm_min, pTm-
8820: 3e 74 6d 5f 73 65 63 29 3b 0a 7d 0a 0a 2f 2a 0a  >tm_sec);.}../*.
8830: 2a 2a 20 50 61 72 73 65 20 61 6e 20 52 46 43 38  ** Parse an RFC8
8840: 32 32 2d 66 6f 72 6d 61 74 74 65 64 20 74 69 6d  22-formatted tim
8850: 65 73 74 61 6d 70 20 61 73 20 77 65 27 64 20 65  estamp as we'd e
8860: 78 70 65 63 74 20 66 72 6f 6d 20 48 54 54 50 20  xpect from HTTP 
8870: 61 6e 64 20 72 65 74 75 72 6e 0a 2a 2a 20 61 20  and return.** a 
8880: 55 6e 69 78 20 65 70 6f 63 68 20 74 69 6d 65 2e  Unix epoch time.
8890: 20 3c 3d 20 7a 65 72 6f 20 69 73 20 72 65 74 75   <= zero is retu
88a0: 72 6e 65 64 20 6f 6e 20 66 61 69 6c 75 72 65 2e  rned on failure.
88b0: 0a 2a 2a 0a 2a 2a 20 4e 6f 74 65 20 74 68 61 74  .**.** Note that
88c0: 20 74 68 69 73 20 77 6f 6e 27 74 20 68 61 6e 64   this won't hand
88d0: 6c 65 20 61 6c 6c 20 74 68 65 20 5f 61 6c 6c 6f  le all the _allo
88e0: 77 65 64 5f 20 48 54 54 50 20 66 6f 72 6d 61 74  wed_ HTTP format
88f0: 73 2c 20 6a 75 73 74 20 74 68 65 0a 2a 2a 20 6d  s, just the.** m
8900: 6f 73 74 20 70 6f 70 75 6c 61 72 20 6f 6e 65 20  ost popular one 
8910: 28 74 68 65 20 6f 6e 65 20 67 65 6e 65 72 61 74  (the one generat
8920: 65 64 20 62 79 20 63 67 69 5f 72 66 63 38 32 32  ed by cgi_rfc822
8930: 5f 64 61 74 65 73 74 61 6d 70 28 29 2c 20 61 63  _datestamp(), ac
8940: 74 75 61 6c 6c 79 29 2e 0a 2a 2f 0a 74 69 6d 65  tually)..*/.time
8950: 5f 74 20 63 67 69 5f 72 66 63 38 32 32 5f 70 61  _t cgi_rfc822_pa
8960: 72 73 65 64 61 74 65 28 63 6f 6e 73 74 20 63 68  rsedate(const ch
8970: 61 72 20 2a 7a 44 61 74 65 29 7b 0a 20 20 73 74  ar *zDate){.  st
8980: 72 75 63 74 20 74 6d 20 74 3b 0a 20 20 63 68 61  ruct tm t;.  cha
8990: 72 20 7a 49 67 6e 6f 72 65 5b 31 36 5d 3b 0a 20  r zIgnore[16];. 
89a0: 20 63 68 61 72 20 7a 4d 6f 6e 74 68 5b 31 36 5d   char zMonth[16]
89b0: 3b 0a 0a 20 20 6d 65 6d 73 65 74 28 26 74 2c 20  ;..  memset(&t, 
89c0: 30 2c 20 73 69 7a 65 6f 66 28 74 29 29 3b 0a 20  0, sizeof(t));. 
89d0: 20 69 66 28 20 37 3d 3d 73 73 63 61 6e 66 28 7a   if( 7==sscanf(z
89e0: 44 61 74 65 2c 20 22 25 31 32 5b 41 2d 5a 61 2d  Date, "%12[A-Za-
89f0: 7a 2c 5d 20 25 64 20 25 31 32 5b 41 2d 5a 61 2d  z,] %d %12[A-Za-
8a00: 7a 5d 20 25 64 20 25 64 3a 25 64 3a 25 64 22 2c  z] %d %d:%d:%d",
8a10: 20 7a 49 67 6e 6f 72 65 2c 0a 20 20 20 20 20 20   zIgnore,.      
8a20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8a30: 20 26 74 2e 74 6d 5f 6d 64 61 79 2c 20 7a 4d 6f   &t.tm_mday, zMo
8a40: 6e 74 68 2c 20 26 74 2e 74 6d 5f 79 65 61 72 2c  nth, &t.tm_year,
8a50: 20 26 74 2e 74 6d 5f 68 6f 75 72 2c 20 26 74 2e   &t.tm_hour, &t.
8a60: 74 6d 5f 6d 69 6e 2c 0a 20 20 20 20 20 20 20 20  tm_min,.        
8a70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 26                 &
8a80: 74 2e 74 6d 5f 73 65 63 29 29 7b 0a 0a 20 20 20  t.tm_sec)){..   
8a90: 20 69 66 28 20 74 2e 74 6d 5f 79 65 61 72 20 3e   if( t.tm_year >
8aa0: 20 31 39 30 30 20 29 20 74 2e 74 6d 5f 79 65 61   1900 ) t.tm_yea
8ab0: 72 20 2d 3d 20 31 39 30 30 3b 0a 20 20 20 20 66  r -= 1900;.    f
8ac0: 6f 72 28 74 2e 74 6d 5f 6d 6f 6e 3d 30 3b 20 61  or(t.tm_mon=0; a
8ad0: 7a 4d 6f 6e 74 68 73 5b 74 2e 74 6d 5f 6d 6f 6e  zMonths[t.tm_mon
8ae0: 5d 3b 20 74 2e 74 6d 5f 6d 6f 6e 2b 2b 29 7b 0a  ]; t.tm_mon++){.
8af0: 20 20 20 20 20 20 69 66 28 20 21 73 74 72 6e 63        if( !strnc
8b00: 61 73 65 63 6d 70 28 20 61 7a 4d 6f 6e 74 68 73  asecmp( azMonths
8b10: 5b 74 2e 74 6d 5f 6d 6f 6e 5d 2c 20 7a 4d 6f 6e  [t.tm_mon], zMon
8b20: 74 68 2c 20 33 20 29 29 7b 0a 20 20 20 20 20 20  th, 3 )){.      
8b30: 20 20 72 65 74 75 72 6e 20 6d 6b 67 6d 74 69 6d    return mkgmtim
8b40: 65 28 26 74 29 3b 0a 20 20 20 20 20 20 7d 0a 20  e(&t);.      }. 
8b50: 20 20 20 7d 0a 20 20 7d 0a 0a 20 20 72 65 74 75     }.  }..  retu
8b60: 72 6e 20 30 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 43  rn 0;.}../*.** C
8b70: 6f 6e 76 65 72 74 20 61 20 73 74 72 75 63 74 20  onvert a struct 
8b80: 74 6d 2a 20 74 68 61 74 20 72 65 70 72 65 73 65  tm* that represe
8b90: 6e 74 73 20 61 20 6d 6f 6d 65 6e 74 20 69 6e 20  nts a moment in 
8ba0: 55 54 43 20 69 6e 74 6f 20 74 68 65 20 6e 75 6d  UTC into the num
8bb0: 62 65 72 0a 2a 2a 20 6f 66 20 73 65 63 6f 6e 64  ber.** of second
8bc0: 73 20 69 6e 20 31 39 37 30 2c 20 55 54 43 2e 0a  s in 1970, UTC..
8bd0: 2a 2f 0a 74 69 6d 65 5f 74 20 6d 6b 67 6d 74 69  */.time_t mkgmti
8be0: 6d 65 28 73 74 72 75 63 74 20 74 6d 20 2a 70 29  me(struct tm *p)
8bf0: 7b 0a 20 20 74 69 6d 65 5f 74 20 74 3b 0a 20 20  {.  time_t t;.  
8c00: 69 6e 74 20 6e 44 61 79 3b 0a 20 20 69 6e 74 20  int nDay;.  int 
8c10: 69 73 4c 65 61 70 59 72 3b 0a 20 20 2f 2a 20 44  isLeapYr;.  /* D
8c20: 61 79 73 20 69 6e 20 65 61 63 68 20 6d 6f 6e 74  ays in each mont
8c30: 68 3a 20 20 20 20 20 20 20 33 31 2c 20 32 38 2c  h:       31, 28,
8c40: 20 33 31 2c 20 33 30 2c 20 33 31 2c 20 33 30 2c   31, 30, 31, 30,
8c50: 20 33 31 2c 20 33 31 2c 20 33 30 2c 20 33 31 2c   31, 31, 30, 31,
8c60: 20 33 30 2c 20 33 31 20 2a 2f 0a 20 20 73 74 61   30, 31 */.  sta
8c70: 74 69 63 20 69 6e 74 20 70 72 69 6f 72 44 61 79  tic int priorDay
8c80: 73 5b 5d 20 20 20 3d 20 7b 20 20 30 2c 20 33 31  s[]   = {  0, 31
8c90: 2c 20 35 39 2c 20 39 30 2c 31 32 30 2c 31 35 31  , 59, 90,120,151
8ca0: 2c 31 38 31 2c 32 31 32 2c 32 34 33 2c 32 37 33  ,181,212,243,273
8cb0: 2c 33 30 34 2c 33 33 34 20 7d 3b 0a 20 20 69 66  ,304,334 };.  if
8cc0: 28 20 70 2d 3e 74 6d 5f 6d 6f 6e 3c 30 20 29 7b  ( p->tm_mon<0 ){
8cd0: 0a 20 20 20 20 69 6e 74 20 6e 59 65 61 72 20 3d  .    int nYear =
8ce0: 20 28 31 31 20 2d 20 70 2d 3e 74 6d 5f 6d 6f 6e   (11 - p->tm_mon
8cf0: 29 2f 31 32 3b 0a 20 20 20 20 70 2d 3e 74 6d 5f  )/12;.    p->tm_
8d00: 79 65 61 72 20 2d 3d 20 6e 59 65 61 72 3b 0a 20  year -= nYear;. 
8d10: 20 20 20 70 2d 3e 74 6d 5f 6d 6f 6e 20 2b 3d 20     p->tm_mon += 
8d20: 6e 59 65 61 72 2a 31 32 3b 0a 20 20 7d 65 6c 73  nYear*12;.  }els
8d30: 65 20 69 66 28 20 70 2d 3e 74 6d 5f 6d 6f 6e 3e  e if( p->tm_mon>
8d40: 31 31 20 29 7b 0a 20 20 20 20 70 2d 3e 74 6d 5f  11 ){.    p->tm_
8d50: 79 65 61 72 20 2b 3d 20 70 2d 3e 74 6d 5f 6d 6f  year += p->tm_mo
8d60: 6e 2f 31 32 3b 0a 20 20 20 20 70 2d 3e 74 6d 5f  n/12;.    p->tm_
8d70: 6d 6f 6e 20 25 3d 20 31 32 3b 0a 20 20 7d 0a 20  mon %= 12;.  }. 
8d80: 20 69 73 4c 65 61 70 59 72 20 3d 20 70 2d 3e 74   isLeapYr = p->t
8d90: 6d 5f 79 65 61 72 25 34 3d 3d 30 20 26 26 20 28  m_year%4==0 && (
8da0: 70 2d 3e 74 6d 5f 79 65 61 72 25 31 30 30 21 3d  p->tm_year%100!=
8db0: 30 20 7c 7c 20 28 70 2d 3e 74 6d 5f 79 65 61 72  0 || (p->tm_year
8dc0: 2b 33 30 30 29 25 34 30 30 3d 3d 30 29 3b 0a 20  +300)%400==0);. 
8dd0: 20 70 2d 3e 74 6d 5f 79 64 61 79 20 3d 20 70 72   p->tm_yday = pr
8de0: 69 6f 72 44 61 79 73 5b 70 2d 3e 74 6d 5f 6d 6f  iorDays[p->tm_mo
8df0: 6e 5d 20 2b 20 70 2d 3e 74 6d 5f 6d 64 61 79 20  n] + p->tm_mday 
8e00: 2d 20 31 3b 0a 20 20 69 66 28 20 69 73 4c 65 61  - 1;.  if( isLea
8e10: 70 59 72 20 26 26 20 70 2d 3e 74 6d 5f 6d 6f 6e  pYr && p->tm_mon
8e20: 3e 31 20 29 20 70 2d 3e 74 6d 5f 79 64 61 79 2b  >1 ) p->tm_yday+
8e30: 2b 3b 0a 20 20 6e 44 61 79 20 3d 20 28 70 2d 3e  +;.  nDay = (p->
8e40: 74 6d 5f 79 65 61 72 2d 37 30 29 2a 33 36 35 20  tm_year-70)*365 
8e50: 2b 20 28 70 2d 3e 74 6d 5f 79 65 61 72 2d 36 39  + (p->tm_year-69
8e60: 29 2f 34 20 2d 70 2d 3e 74 6d 5f 79 65 61 72 2f  )/4 -p->tm_year/
8e70: 31 30 30 20 2b 20 0a 20 20 20 20 20 20 20 20 20  100 + .         
8e80: 28 70 2d 3e 74 6d 5f 79 65 61 72 2b 33 30 30 29  (p->tm_year+300)
8e90: 2f 34 30 30 20 2b 20 70 2d 3e 74 6d 5f 79 64 61  /400 + p->tm_yda
8ea0: 79 3b 0a 20 20 74 20 3d 20 28 28 6e 44 61 79 2a  y;.  t = ((nDay*
8eb0: 32 34 20 2b 20 70 2d 3e 74 6d 5f 68 6f 75 72 29  24 + p->tm_hour)
8ec0: 2a 36 30 20 2b 20 70 2d 3e 74 6d 5f 6d 69 6e 29  *60 + p->tm_min)
8ed0: 2a 36 30 20 2b 20 70 2d 3e 74 6d 5f 73 65 63 3b  *60 + p->tm_sec;
8ee0: 0a 20 20 72 65 74 75 72 6e 20 74 3b 0a 7d 0a 0a  .  return t;.}..
8ef0: 2f 2a 0a 2a 2a 20 43 68 65 63 6b 20 74 68 65 20  /*.** Check the 
8f00: 6f 62 6a 65 63 74 54 69 6d 65 20 61 67 61 69 6e  objectTime again
8f10: 73 74 20 74 68 65 20 49 66 2d 4d 6f 64 69 66 69  st the If-Modifi
8f20: 65 64 2d 53 69 6e 63 65 20 72 65 71 75 65 73 74  ed-Since request
8f30: 20 68 65 61 64 65 72 2e 20 49 66 20 74 68 65 0a   header. If the.
8f40: 2a 2a 20 6f 62 6a 65 63 74 20 74 69 6d 65 20 69  ** object time i
8f50: 73 6e 27 74 20 61 6e 79 20 6e 65 77 65 72 20 74  sn't any newer t
8f60: 68 61 6e 20 74 68 65 20 68 65 61 64 65 72 2c 20  han the header, 
8f70: 77 65 20 69 6d 6d 65 64 69 61 74 65 6c 79 20 73  we immediately s
8f80: 65 6e 64 20 62 61 63 6b 0a 2a 2a 20 61 20 33 30  end back.** a 30
8f90: 34 20 72 65 70 6c 79 20 61 6e 64 20 65 78 69 74  4 reply and exit
8fa0: 2e 0a 2a 2f 0a 76 6f 69 64 20 63 67 69 5f 6d 6f  ..*/.void cgi_mo
8fb0: 64 69 66 69 65 64 5f 73 69 6e 63 65 28 74 69 6d  dified_since(tim
8fc0: 65 5f 74 20 6f 62 6a 65 63 74 54 69 6d 65 29 7b  e_t objectTime){
8fd0: 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a  .  const char *z
8fe0: 49 66 20 3d 20 50 28 22 48 54 54 50 5f 49 46 5f  If = P("HTTP_IF_
8ff0: 4d 4f 44 49 46 49 45 44 5f 53 49 4e 43 45 22 29  MODIFIED_SINCE")
9000: 3b 0a 20 20 69 66 28 20 7a 49 66 3d 3d 30 20 29  ;.  if( zIf==0 )
9010: 20 72 65 74 75 72 6e 3b 0a 20 20 69 66 28 20 6f   return;.  if( o
9020: 62 6a 65 63 74 54 69 6d 65 20 3e 20 63 67 69 5f  bjectTime > cgi_
9030: 72 66 63 38 32 32 5f 70 61 72 73 65 64 61 74 65  rfc822_parsedate
9040: 28 7a 49 66 29 20 29 20 72 65 74 75 72 6e 3b 0a  (zIf) ) return;.
9050: 20 20 63 67 69 5f 73 65 74 5f 73 74 61 74 75 73    cgi_set_status
9060: 28 33 30 34 2c 22 4e 6f 74 20 4d 6f 64 69 66 69  (304,"Not Modifi
9070: 65 64 22 29 3b 0a 20 20 63 67 69 5f 72 65 73 65  ed");.  cgi_rese
9080: 74 5f 63 6f 6e 74 65 6e 74 28 29 3b 0a 20 20 63  t_content();.  c
9090: 67 69 5f 72 65 70 6c 79 28 29 3b 0a 20 20 65 78  gi_reply();.  ex
90a0: 69 74 28 30 29 3b 0a 7d 0a                       it(0);.}.