Fossil

Hex Artifact Content
Login

Artifact b16221ffb736caa21beb8f9b9e09f775251a2846a203f7d30996b1b13eb54ad8:


0000: 2f 2a 0a 2a 2a 20 43 6f 70 79 72 69 67 68 74 20  /*.** Copyright 
0010: 28 63 29 20 32 30 30 37 20 44 2e 20 52 69 63 68  (c) 2007 D. Rich
0020: 61 72 64 20 48 69 70 70 0a 2a 2a 0a 2a 2a 20 54  ard Hipp.**.** T
0030: 68 69 73 20 70 72 6f 67 72 61 6d 20 69 73 20 66  his program is f
0040: 72 65 65 20 73 6f 66 74 77 61 72 65 3b 20 79 6f  ree software; yo
0050: 75 20 63 61 6e 20 72 65 64 69 73 74 72 69 62 75  u can redistribu
0060: 74 65 20 69 74 20 61 6e 64 2f 6f 72 0a 2a 2a 20  te it and/or.** 
0070: 6d 6f 64 69 66 79 20 69 74 20 75 6e 64 65 72 20  modify it under 
0080: 74 68 65 20 74 65 72 6d 73 20 6f 66 20 74 68 65  the terms of the
0090: 20 53 69 6d 70 6c 69 66 69 65 64 20 42 53 44 20   Simplified BSD 
00a0: 4c 69 63 65 6e 73 65 20 28 61 6c 73 6f 0a 2a 2a  License (also.**
00b0: 20 6b 6e 6f 77 6e 20 61 73 20 74 68 65 20 22 32   known as the "2
00c0: 2d 43 6c 61 75 73 65 20 4c 69 63 65 6e 73 65 22  -Clause License"
00d0: 20 6f 72 20 22 46 72 65 65 42 53 44 20 4c 69 63   or "FreeBSD Lic
00e0: 65 6e 73 65 22 2e 29 0a 0a 2a 2a 20 54 68 69 73  ense".)..** This
00f0: 20 70 72 6f 67 72 61 6d 20 69 73 20 64 69 73 74   program is dist
0100: 72 69 62 75 74 65 64 20 69 6e 20 74 68 65 20 68  ributed in the h
0110: 6f 70 65 20 74 68 61 74 20 69 74 20 77 69 6c 6c  ope that it will
0120: 20 62 65 20 75 73 65 66 75 6c 2c 0a 2a 2a 20 62   be useful,.** b
0130: 75 74 20 77 69 74 68 6f 75 74 20 61 6e 79 20 77  ut without any w
0140: 61 72 72 61 6e 74 79 3b 20 77 69 74 68 6f 75 74  arranty; without
0150: 20 65 76 65 6e 20 74 68 65 20 69 6d 70 6c 69 65   even the implie
0160: 64 20 77 61 72 72 61 6e 74 79 20 6f 66 0a 2a 2a  d warranty of.**
0170: 20 6d 65 72 63 68 61 6e 74 61 62 69 6c 69 74 79   merchantability
0180: 20 6f 72 20 66 69 74 6e 65 73 73 20 66 6f 72 20   or fitness for 
0190: 61 20 70 61 72 74 69 63 75 6c 61 72 20 70 75 72  a particular pur
01a0: 70 6f 73 65 2e 0a 2a 2a 0a 2a 2a 20 41 75 74 68  pose..**.** Auth
01b0: 6f 72 20 63 6f 6e 74 61 63 74 20 69 6e 66 6f 72  or contact infor
01c0: 6d 61 74 69 6f 6e 3a 0a 2a 2a 20 20 20 64 72 68  mation:.**   drh
01d0: 40 68 77 61 63 69 2e 63 6f 6d 0a 2a 2a 20 20 20  @hwaci.com.**   
01e0: 68 74 74 70 3a 2f 2f 77 77 77 2e 68 77 61 63 69  http://www.hwaci
01f0: 2e 63 6f 6d 2f 64 72 68 2f 0a 2a 2a 0a 2a 2a 2a  .com/drh/.**.***
0200: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0210: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0220: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0230: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0240: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 0a 2a 2a 0a  ************.**.
0250: 2a 2a 20 54 68 69 73 20 66 69 6c 65 20 63 6f 6e  ** This file con
0260: 74 61 69 6e 73 20 63 6f 64 65 20 66 6f 72 20 67  tains code for g
0270: 65 6e 65 72 61 74 69 6e 67 20 74 68 65 20 6c 6f  enerating the lo
0280: 67 69 6e 20 61 6e 64 20 6c 6f 67 6f 75 74 20 73  gin and logout s
0290: 63 72 65 65 6e 73 2e 0a 2a 2a 0a 2a 2a 20 4e 6f  creens..**.** No
02a0: 74 65 73 3a 0a 2a 2a 0a 2a 2a 20 54 68 65 72 65  tes:.**.** There
02b0: 20 61 72 65 20 66 6f 75 72 20 73 70 65 63 69 61   are four specia
02c0: 6c 2d 63 61 73 65 20 75 73 65 72 2d 69 64 73 3a  l-case user-ids:
02d0: 20 20 22 61 6e 6f 6e 79 6d 6f 75 73 22 2c 20 22    "anonymous", "
02e0: 6e 6f 62 6f 64 79 22 2c 0a 2a 2a 20 22 64 65 76  nobody",.** "dev
02f0: 65 6c 6f 70 65 72 22 20 61 6e 64 20 22 72 65 61  eloper" and "rea
0300: 64 65 72 22 2e 0a 2a 2a 0a 2a 2a 20 54 68 65 20  der"..**.** The 
0310: 63 61 70 61 62 69 6c 69 74 69 65 73 20 6f 66 20  capabilities of 
0320: 74 68 65 20 6e 6f 62 6f 64 79 20 75 73 65 72 20  the nobody user 
0330: 61 72 65 20 61 76 61 69 6c 61 62 6c 65 20 74 6f  are available to
0340: 20 61 6e 79 6f 6e 65 2c 0a 2a 2a 20 72 65 67 61   anyone,.** rega
0350: 72 64 6c 65 73 73 20 6f 66 20 77 68 65 74 68 65  rdless of whethe
0360: 72 20 6f 72 20 6e 6f 74 20 74 68 65 79 20 61 72  r or not they ar
0370: 65 20 6c 6f 67 67 65 64 20 69 6e 2e 20 20 54 68  e logged in.  Th
0380: 65 20 63 61 70 61 62 69 6c 69 74 69 65 73 0a 2a  e capabilities.*
0390: 2a 20 6f 66 20 61 6e 6f 6e 79 6d 6f 75 73 20 61  * of anonymous a
03a0: 72 65 20 6f 6e 6c 79 20 61 76 61 69 6c 61 62 6c  re only availabl
03b0: 65 20 61 66 74 65 72 20 6c 6f 67 67 69 6e 67 20  e after logging 
03c0: 69 6e 2c 20 62 75 74 20 74 68 65 20 6c 6f 67 69  in, but the logi
03d0: 6e 0a 2a 2a 20 73 63 72 65 65 6e 20 64 69 73 70  n.** screen disp
03e0: 6c 61 79 73 20 74 68 65 20 70 61 73 73 77 6f 72  lays the passwor
03f0: 64 20 66 6f 72 20 74 68 65 20 61 6e 6f 6e 79 6d  d for the anonym
0400: 6f 75 73 20 6c 6f 67 69 6e 2c 20 73 6f 20 74 68  ous login, so th
0410: 69 73 0a 2a 2a 20 73 68 6f 75 6c 64 20 6e 6f 74  is.** should not
0420: 20 70 72 65 76 65 6e 74 20 61 20 68 75 6d 61 6e   prevent a human
0430: 20 75 73 65 72 20 66 72 6f 6d 20 64 6f 69 6e 67   user from doing
0440: 20 73 6f 2e 20 20 54 68 65 20 63 61 70 61 62 69   so.  The capabi
0450: 6c 69 74 69 65 73 0a 2a 2a 20 6f 66 20 64 65 76  lities.** of dev
0460: 65 6c 6f 70 65 72 20 61 6e 64 20 72 65 61 64 65  eloper and reade
0470: 72 20 61 72 65 20 69 6e 68 65 72 69 74 65 64 20  r are inherited 
0480: 62 79 20 61 6e 79 20 75 73 65 72 20 74 68 61 74  by any user that
0490: 20 68 61 73 20 74 68 65 0a 2a 2a 20 22 76 22 20   has the.** "v" 
04a0: 61 6e 64 20 22 75 22 20 63 61 70 61 62 69 6c 69  and "u" capabili
04b0: 74 69 65 73 2c 20 72 65 73 70 65 63 74 69 76 65  ties, respective
04c0: 6c 79 2e 0a 2a 2a 0a 2a 2a 20 54 68 65 20 6e 6f  ly..**.** The no
04d0: 62 6f 64 79 20 75 73 65 72 20 68 61 73 20 63 61  body user has ca
04e0: 70 61 62 69 6c 69 74 69 65 73 20 74 68 61 74 20  pabilities that 
04f0: 79 6f 75 20 77 61 6e 74 20 73 70 69 64 65 72 73  you want spiders
0500: 20 74 6f 20 68 61 76 65 2e 0a 2a 2a 20 54 68 65   to have..** The
0510: 20 61 6e 6f 6e 79 6d 6f 75 73 20 75 73 65 72 20   anonymous user 
0520: 68 61 73 20 63 61 70 61 62 69 6c 69 74 69 65 73  has capabilities
0530: 20 74 68 61 74 20 79 6f 75 20 77 61 6e 74 20 70   that you want p
0540: 65 6f 70 6c 65 20 77 69 74 68 6f 75 74 0a 2a 2a  eople without.**
0550: 20 6c 6f 67 69 6e 73 20 74 6f 20 68 61 76 65 2e   logins to have.
0560: 0a 2a 2a 0a 2a 2a 20 4f 66 20 63 6f 75 72 73 65  .**.** Of course
0570: 2c 20 61 20 73 6f 70 68 69 73 74 69 63 61 74 65  , a sophisticate
0580: 64 20 73 70 69 64 65 72 20 63 6f 75 6c 64 20 65  d spider could e
0590: 61 73 69 6c 79 20 63 69 72 63 75 6d 76 65 6e 74  asily circumvent
05a0: 20 74 68 65 0a 2a 2a 20 61 6e 6f 6e 79 6d 6f 75   the.** anonymou
05b0: 73 20 6c 6f 67 69 6e 20 72 65 71 75 69 72 65 6d  s login requirem
05c0: 65 6e 74 20 61 6e 64 20 77 61 6c 6b 20 74 68 65  ent and walk the
05d0: 20 77 65 62 73 69 74 65 2e 20 20 42 75 74 20 74   website.  But t
05e0: 68 61 74 20 69 73 0a 2a 2a 20 6e 6f 74 20 72 65  hat is.** not re
05f0: 61 6c 6c 79 20 74 68 65 20 70 6f 69 6e 74 2e 20  ally the point. 
0600: 20 54 68 65 20 61 6e 6f 6e 79 6d 6f 75 73 20 6c   The anonymous l
0610: 6f 67 69 6e 20 6b 65 65 70 73 20 73 65 61 72 63  ogin keeps searc
0620: 68 2d 65 6e 67 69 6e 65 0a 2a 2a 20 63 72 61 77  h-engine.** craw
0630: 6c 65 72 73 20 61 6e 64 20 73 69 74 65 20 64 6f  lers and site do
0640: 77 6e 6c 6f 61 64 20 74 6f 6f 6c 73 20 6c 69 6b  wnload tools lik
0650: 65 20 77 67 65 74 20 66 72 6f 6d 20 77 61 6c 6b  e wget from walk
0660: 69 6e 67 20 63 68 61 6e 67 65 0a 2a 2a 20 6c 6f  ing change.** lo
0670: 67 73 20 61 6e 64 20 64 6f 77 6e 6c 6f 61 64 69  gs and downloadi
0680: 6e 67 20 64 69 66 66 73 20 6f 66 20 76 65 72 79  ng diffs of very
0690: 20 76 65 72 73 69 6f 6e 20 6f 66 20 74 68 65 20   version of the 
06a0: 61 72 63 68 69 76 65 20 74 68 61 74 0a 2a 2a 20  archive that.** 
06b0: 68 61 73 20 65 76 65 72 20 65 78 69 73 74 65 64  has ever existed
06c0: 2c 20 61 6e 64 20 74 68 69 6e 67 73 20 6c 69 6b  , and things lik
06d0: 65 20 74 68 61 74 2e 0a 2a 2f 0a 23 69 6e 63 6c  e that..*/.#incl
06e0: 75 64 65 20 22 63 6f 6e 66 69 67 2e 68 22 0a 23  ude "config.h".#
06f0: 69 6e 63 6c 75 64 65 20 22 6c 6f 67 69 6e 2e 68  include "login.h
0700: 22 0a 23 69 66 20 64 65 66 69 6e 65 64 28 5f 57  ".#if defined(_W
0710: 49 4e 33 32 29 0a 23 20 20 69 6e 63 6c 75 64 65  IN32).#  include
0720: 20 3c 77 69 6e 64 6f 77 73 2e 68 3e 20 20 20 20   <windows.h>    
0730: 20 20 20 20 20 20 20 2f 2a 20 66 6f 72 20 53 6c         /* for Sl
0740: 65 65 70 20 2a 2f 0a 23 20 20 69 66 20 64 65 66  eep */.#  if def
0750: 69 6e 65 64 28 5f 5f 4d 49 4e 47 57 33 32 5f 5f  ined(__MINGW32__
0760: 29 20 7c 7c 20 64 65 66 69 6e 65 64 28 5f 4d 53  ) || defined(_MS
0770: 43 5f 56 45 52 29 0a 23 20 20 20 20 64 65 66 69  C_VER).#    defi
0780: 6e 65 20 73 6c 65 65 70 20 53 6c 65 65 70 20 20  ne sleep Sleep  
0790: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 77 69 6e            /* win
07a0: 64 6f 77 73 20 64 6f 65 73 20 6e 6f 74 20 68 61  dows does not ha
07b0: 76 65 20 73 6c 65 65 70 2c 20 62 75 74 20 53 6c  ve sleep, but Sl
07c0: 65 65 70 20 2a 2f 0a 23 20 20 65 6e 64 69 66 0a  eep */.#  endif.
07d0: 23 65 6e 64 69 66 0a 23 69 6e 63 6c 75 64 65 20  #endif.#include 
07e0: 3c 74 69 6d 65 2e 68 3e 0a 0a 0a 2f 2a 0a 2a 2a  <time.h>.../*.**
07f0: 20 52 65 74 75 72 6e 20 74 68 65 20 6c 6f 67 69   Return the logi
0800: 6e 2d 67 72 6f 75 70 20 6e 61 6d 65 2e 20 20 4f  n-group name.  O
0810: 72 20 72 65 74 75 72 6e 20 30 20 69 66 20 74 68  r return 0 if th
0820: 69 73 20 72 65 70 6f 73 69 74 6f 72 79 20 69 73  is repository is
0830: 0a 2a 2a 20 6e 6f 74 20 61 20 6d 65 6d 62 65 72  .** not a member
0840: 20 6f 66 20 61 20 6c 6f 67 69 6e 2d 67 72 6f 75   of a login-grou
0850: 70 2e 0a 2a 2f 0a 63 6f 6e 73 74 20 63 68 61 72  p..*/.const char
0860: 20 2a 6c 6f 67 69 6e 5f 67 72 6f 75 70 5f 6e 61   *login_group_na
0870: 6d 65 28 76 6f 69 64 29 7b 0a 20 20 73 74 61 74  me(void){.  stat
0880: 69 63 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a  ic const char *z
0890: 47 72 6f 75 70 20 3d 20 30 3b 0a 20 20 73 74 61  Group = 0;.  sta
08a0: 74 69 63 20 69 6e 74 20 6f 6e 63 65 20 3d 20 31  tic int once = 1
08b0: 3b 0a 20 20 69 66 28 20 6f 6e 63 65 20 29 7b 0a  ;.  if( once ){.
08c0: 20 20 20 20 7a 47 72 6f 75 70 20 3d 20 64 62 5f      zGroup = db_
08d0: 67 65 74 28 22 6c 6f 67 69 6e 2d 67 72 6f 75 70  get("login-group
08e0: 2d 6e 61 6d 65 22 2c 20 30 29 3b 0a 20 20 20 20  -name", 0);.    
08f0: 6f 6e 63 65 20 3d 20 30 3b 0a 20 20 7d 0a 20 20  once = 0;.  }.  
0900: 72 65 74 75 72 6e 20 7a 47 72 6f 75 70 3b 0a 7d  return zGroup;.}
0910: 0a 0a 2f 2a 0a 2a 2a 20 52 65 74 75 72 6e 20 61  ../*.** Return a
0920: 20 70 61 74 68 20 61 70 70 72 6f 70 72 69 61 74   path appropriat
0930: 65 20 66 6f 72 20 73 65 74 74 69 6e 67 20 61 20  e for setting a 
0940: 63 6f 6f 6b 69 65 2e 0a 2a 2a 0a 2a 2a 20 54 68  cookie..**.** Th
0950: 65 20 70 61 74 68 20 69 73 20 67 2e 7a 54 6f 70  e path is g.zTop
0960: 20 66 6f 72 20 73 69 6e 67 6c 65 2d 72 65 70 6f   for single-repo
0970: 20 63 6f 6f 6b 69 65 73 2e 20 20 49 74 20 69 73   cookies.  It is
0980: 20 22 2f 22 20 66 6f 72 0a 2a 2a 20 63 6f 6f 6b   "/" for.** cook
0990: 69 65 73 20 6f 66 20 61 20 6c 6f 67 69 6e 2d 67  ies of a login-g
09a0: 72 6f 75 70 2e 0a 2a 2f 0a 63 6f 6e 73 74 20 63  roup..*/.const c
09b0: 68 61 72 20 2a 6c 6f 67 69 6e 5f 63 6f 6f 6b 69  har *login_cooki
09c0: 65 5f 70 61 74 68 28 76 6f 69 64 29 7b 0a 20 20  e_path(void){.  
09d0: 69 66 28 20 6c 6f 67 69 6e 5f 67 72 6f 75 70 5f  if( login_group_
09e0: 6e 61 6d 65 28 29 3d 3d 30 20 29 7b 0a 20 20 20  name()==0 ){.   
09f0: 20 72 65 74 75 72 6e 20 67 2e 7a 54 6f 70 3b 0a   return g.zTop;.
0a00: 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 72 65 74    }else{.    ret
0a10: 75 72 6e 20 22 2f 22 3b 0a 20 20 7d 0a 7d 0a 0a  urn "/";.  }.}..
0a20: 2f 2a 0a 2a 2a 20 52 65 74 75 72 6e 20 74 68 65  /*.** Return the
0a30: 20 6e 61 6d 65 20 6f 66 20 74 68 65 20 6c 6f 67   name of the log
0a40: 69 6e 20 63 6f 6f 6b 69 65 2e 0a 2a 2a 0a 2a 2a  in cookie..**.**
0a50: 20 54 68 65 20 6c 6f 67 69 6e 20 63 6f 6f 6b 69   The login cooki
0a60: 65 20 6e 61 6d 65 20 69 73 20 61 6c 77 61 79 73  e name is always
0a70: 20 6f 66 20 74 68 65 20 66 6f 72 6d 3a 20 20 66   of the form:  f
0a80: 6f 73 73 69 6c 2d 58 58 58 58 58 58 58 58 58 58  ossil-XXXXXXXXXX
0a90: 58 58 58 58 58 58 0a 2a 2a 20 77 68 65 72 65 20  XXXXXX.** where 
0aa0: 74 68 65 20 58 73 20 61 72 65 20 74 68 65 20 66  the Xs are the f
0ab0: 69 72 73 74 20 31 36 20 63 68 61 72 61 63 74 65  irst 16 characte
0ac0: 72 73 20 6f 66 20 74 68 65 20 6c 6f 67 69 6e 2d  rs of the login-
0ad0: 67 72 6f 75 70 2d 63 6f 64 65 20 6f 72 0a 2a 2a  group-code or.**
0ae0: 20 6f 66 20 74 68 65 20 70 72 6f 6a 65 63 74 2d   of the project-
0af0: 63 6f 64 65 20 69 66 20 77 65 20 61 72 65 20 6e  code if we are n
0b00: 6f 74 20 61 20 6d 65 6d 62 65 72 20 6f 66 20 61  ot a member of a
0b10: 6e 79 20 6c 6f 67 69 6e 2d 67 72 6f 75 70 2e 0a  ny login-group..
0b20: 2a 2f 0a 63 68 61 72 20 2a 6c 6f 67 69 6e 5f 63  */.char *login_c
0b30: 6f 6f 6b 69 65 5f 6e 61 6d 65 28 76 6f 69 64 29  ookie_name(void)
0b40: 7b 0a 20 20 73 74 61 74 69 63 20 63 68 61 72 20  {.  static char 
0b50: 2a 7a 43 6f 6f 6b 69 65 4e 61 6d 65 20 3d 20 30  *zCookieName = 0
0b60: 3b 0a 20 20 69 66 28 20 7a 43 6f 6f 6b 69 65 4e  ;.  if( zCookieN
0b70: 61 6d 65 3d 3d 30 20 29 7b 0a 20 20 20 20 7a 43  ame==0 ){.    zC
0b80: 6f 6f 6b 69 65 4e 61 6d 65 20 3d 20 64 62 5f 74  ookieName = db_t
0b90: 65 78 74 28 30 2c 0a 20 20 20 20 20 20 20 22 53  ext(0,.       "S
0ba0: 45 4c 45 43 54 20 27 66 6f 73 73 69 6c 2d 27 20  ELECT 'fossil-' 
0bb0: 7c 7c 20 73 75 62 73 74 72 28 76 61 6c 75 65 2c  || substr(value,
0bc0: 31 2c 31 36 29 22 0a 20 20 20 20 20 20 20 22 20  1,16)".       " 
0bd0: 20 46 52 4f 4d 20 63 6f 6e 66 69 67 22 0a 20 20   FROM config".  
0be0: 20 20 20 20 20 22 20 57 48 45 52 45 20 6e 61 6d       " WHERE nam
0bf0: 65 20 49 4e 20 28 27 70 72 6f 6a 65 63 74 2d 63  e IN ('project-c
0c00: 6f 64 65 27 2c 27 6c 6f 67 69 6e 2d 67 72 6f 75  ode','login-grou
0c10: 70 2d 63 6f 64 65 27 29 22 0a 20 20 20 20 20 20  p-code')".      
0c20: 20 22 20 4f 52 44 45 52 20 42 59 20 6e 61 6d 65   " ORDER BY name
0c30: 20 2f 2a 73 6f 72 74 2a 2f 22 0a 20 20 20 20 29   /*sort*/".    )
0c40: 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20 7a  ;.  }.  return z
0c50: 43 6f 6f 6b 69 65 4e 61 6d 65 3b 0a 7d 0a 0a 2f  CookieName;.}../
0c60: 2a 0a 2a 2a 20 52 65 64 69 72 65 63 74 20 74 6f  *.** Redirect to
0c70: 20 74 68 65 20 70 61 67 65 20 73 70 65 63 69 66   the page specif
0c80: 69 65 64 20 62 79 20 74 68 65 20 22 67 22 20 71  ied by the "g" q
0c90: 75 65 72 79 20 70 61 72 61 6d 65 74 65 72 2e 0a  uery parameter..
0ca0: 2a 2a 20 4f 72 20 69 66 20 74 68 65 72 65 20 69  ** Or if there i
0cb0: 73 20 6e 6f 20 22 67 22 20 71 75 65 72 79 20 70  s no "g" query p
0cc0: 61 72 61 6d 65 74 65 72 2c 20 72 65 64 69 72 65  arameter, redire
0cd0: 63 74 20 74 6f 20 74 68 65 20 68 6f 6d 65 70 61  ct to the homepa
0ce0: 67 65 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 76 6f  ge..*/.static vo
0cf0: 69 64 20 72 65 64 69 72 65 63 74 5f 74 6f 5f 67  id redirect_to_g
0d00: 28 76 6f 69 64 29 7b 0a 20 20 63 6f 6e 73 74 20  (void){.  const 
0d10: 63 68 61 72 20 2a 7a 47 6f 74 6f 20 3d 20 50 28  char *zGoto = P(
0d20: 22 67 22 29 3b 0a 20 20 69 66 28 20 7a 47 6f 74  "g");.  if( zGot
0d30: 6f 20 29 7b 0a 20 20 20 20 63 67 69 5f 72 65 64  o ){.    cgi_red
0d40: 69 72 65 63 74 28 7a 47 6f 74 6f 29 3b 0a 20 20  irect(zGoto);.  
0d50: 7d 65 6c 73 65 7b 0a 20 20 20 20 66 6f 73 73 69  }else{.    fossi
0d60: 6c 5f 72 65 64 69 72 65 63 74 5f 68 6f 6d 65 28  l_redirect_home(
0d70: 29 3b 0a 20 20 7d 0a 7d 0a 0a 2f 2a 0a 2a 2a 20  );.  }.}../*.** 
0d80: 54 68 65 20 49 50 20 61 64 64 72 65 73 73 20 6f  The IP address o
0d90: 66 20 74 68 65 20 63 6c 69 65 6e 74 20 69 73 20  f the client is 
0da0: 73 74 6f 72 65 64 20 61 73 20 70 61 72 74 20 6f  stored as part o
0db0: 66 20 6c 6f 67 69 6e 20 63 6f 6f 6b 69 65 73 2e  f login cookies.
0dc0: 0a 2a 2a 20 42 75 74 20 73 6f 6d 65 20 63 6c 69  .** But some cli
0dd0: 65 6e 74 73 20 61 72 65 20 62 65 68 69 6e 64 20  ents are behind 
0de0: 66 69 72 65 77 61 6c 6c 73 20 74 68 61 74 20 73  firewalls that s
0df0: 68 69 66 74 20 74 68 65 20 49 50 20 61 64 64 72  hift the IP addr
0e00: 65 73 73 0a 2a 2a 20 77 69 74 68 20 65 61 63 68  ess.** with each
0e10: 20 48 54 54 50 20 72 65 71 75 65 73 74 2e 20 20   HTTP request.  
0e20: 54 6f 20 61 6c 6c 6f 77 20 73 75 63 68 20 28 62  To allow such (b
0e30: 72 6f 6b 65 6e 29 20 63 6c 69 65 6e 74 73 20 74  roken) clients t
0e40: 6f 20 6c 6f 67 20 69 6e 2c 0a 2a 2a 20 65 78 74  o log in,.** ext
0e50: 72 61 63 74 20 6a 75 73 74 20 61 20 70 72 65 66  ract just a pref
0e60: 69 78 20 6f 66 20 74 68 65 20 49 50 20 61 64 64  ix of the IP add
0e70: 72 65 73 73 2e 0a 2a 2f 0a 73 74 61 74 69 63 20  ress..*/.static 
0e80: 63 68 61 72 20 2a 69 70 50 72 65 66 69 78 28 63  char *ipPrefix(c
0e90: 6f 6e 73 74 20 63 68 61 72 20 2a 7a 49 50 29 7b  onst char *zIP){
0ea0: 0a 20 20 69 6e 74 20 69 2c 20 6a 3b 0a 20 20 73  .  int i, j;.  s
0eb0: 74 61 74 69 63 20 69 6e 74 20 69 70 5f 70 72 65  tatic int ip_pre
0ec0: 66 69 78 5f 74 65 72 6d 73 20 3d 20 2d 31 3b 0a  fix_terms = -1;.
0ed0: 20 20 69 66 28 20 69 70 5f 70 72 65 66 69 78 5f    if( ip_prefix_
0ee0: 74 65 72 6d 73 3c 30 20 29 7b 0a 20 20 20 20 69  terms<0 ){.    i
0ef0: 70 5f 70 72 65 66 69 78 5f 74 65 72 6d 73 20 3d  p_prefix_terms =
0f00: 20 64 62 5f 67 65 74 5f 69 6e 74 28 22 69 70 2d   db_get_int("ip-
0f10: 70 72 65 66 69 78 2d 74 65 72 6d 73 22 2c 32 29  prefix-terms",2)
0f20: 3b 0a 20 20 7d 0a 20 20 69 66 28 20 69 70 5f 70  ;.  }.  if( ip_p
0f30: 72 65 66 69 78 5f 74 65 72 6d 73 3d 3d 30 20 29  refix_terms==0 )
0f40: 20 72 65 74 75 72 6e 20 6d 70 72 69 6e 74 66 28   return mprintf(
0f50: 22 30 22 29 3b 0a 20 20 66 6f 72 28 69 3d 6a 3d  "0");.  for(i=j=
0f60: 30 3b 20 7a 49 50 5b 69 5d 3b 20 69 2b 2b 29 7b  0; zIP[i]; i++){
0f70: 0a 20 20 20 20 69 66 28 20 7a 49 50 5b 69 5d 3d  .    if( zIP[i]=
0f80: 3d 27 2e 27 20 29 7b 0a 20 20 20 20 20 20 6a 2b  ='.' ){.      j+
0f90: 2b 3b 0a 20 20 20 20 20 20 69 66 28 20 6a 3d 3d  +;.      if( j==
0fa0: 69 70 5f 70 72 65 66 69 78 5f 74 65 72 6d 73 20  ip_prefix_terms 
0fb0: 29 20 62 72 65 61 6b 3b 0a 20 20 20 20 7d 0a 20  ) break;.    }. 
0fc0: 20 7d 0a 20 20 72 65 74 75 72 6e 20 6d 70 72 69   }.  return mpri
0fd0: 6e 74 66 28 22 25 2e 2a 73 22 2c 20 69 2c 20 7a  ntf("%.*s", i, z
0fe0: 49 50 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 52 65  IP);.}../*.** Re
0ff0: 74 75 72 6e 20 61 6e 20 61 62 62 72 65 76 69 61  turn an abbrevia
1000: 74 65 64 20 70 72 6f 6a 65 63 74 20 63 6f 64 65  ted project code
1010: 2e 20 20 54 68 65 20 61 62 62 72 65 76 69 61 74  .  The abbreviat
1020: 69 6f 6e 20 69 73 20 74 68 65 20 66 69 72 73 74  ion is the first
1030: 0a 2a 2a 20 31 36 20 63 68 61 72 61 63 74 65 72  .** 16 character
1040: 73 20 6f 66 20 74 68 65 20 70 72 6f 6a 65 63 74  s of the project
1050: 20 63 6f 64 65 2e 0a 2a 2a 0a 2a 2a 20 4d 65 6d   code..**.** Mem
1060: 6f 72 79 20 69 73 20 6f 62 74 61 69 6e 65 64 20  ory is obtained 
1070: 66 72 6f 6d 20 6d 61 6c 6c 6f 63 2e 0a 2a 2f 0a  from malloc..*/.
1080: 73 74 61 74 69 63 20 63 68 61 72 20 2a 61 62 62  static char *abb
1090: 72 65 76 69 61 74 65 64 5f 70 72 6f 6a 65 63 74  reviated_project
10a0: 5f 63 6f 64 65 28 63 6f 6e 73 74 20 63 68 61 72  _code(const char
10b0: 20 2a 7a 46 75 6c 6c 43 6f 64 65 29 7b 0a 20 20   *zFullCode){.  
10c0: 72 65 74 75 72 6e 20 6d 70 72 69 6e 74 66 28 22  return mprintf("
10d0: 25 2e 31 36 73 22 2c 20 7a 46 75 6c 6c 43 6f 64  %.16s", zFullCod
10e0: 65 29 3b 0a 7d 0a 0a 0a 2f 2a 0a 2a 2a 20 43 68  e);.}.../*.** Ch
10f0: 65 63 6b 20 74 6f 20 73 65 65 20 69 66 20 74 68  eck to see if th
1100: 65 20 61 6e 6f 6e 79 6d 6f 75 73 20 6c 6f 67 69  e anonymous logi
1110: 6e 20 69 73 20 76 61 6c 69 64 2e 20 20 49 66 20  n is valid.  If 
1120: 69 74 20 69 73 20 76 61 6c 69 64 2c 20 72 65 74  it is valid, ret
1130: 75 72 6e 0a 2a 2a 20 74 68 65 20 75 73 65 72 69  urn.** the useri
1140: 64 20 6f 66 20 74 68 65 20 61 6e 6f 6e 79 6d 6f  d of the anonymo
1150: 75 73 20 75 73 65 72 2e 0a 2a 2a 0a 2a 2a 20 54  us user..**.** T
1160: 68 65 20 7a 43 53 20 70 61 72 61 6d 65 74 65 72  he zCS parameter
1170: 20 69 73 20 74 68 65 20 22 63 61 70 74 63 68 61   is the "captcha
1180: 20 73 65 65 64 22 20 75 73 65 64 20 66 6f 72 20   seed" used for 
1190: 61 20 73 70 65 63 69 66 69 63 0a 2a 2a 20 61 6e  a specific.** an
11a0: 6f 6e 79 6d 6f 75 73 20 6c 6f 67 69 6e 20 72 65  onymous login re
11b0: 71 75 65 73 74 2e 0a 2a 2f 0a 69 6e 74 20 6c 6f  quest..*/.int lo
11c0: 67 69 6e 5f 69 73 5f 76 61 6c 69 64 5f 61 6e 6f  gin_is_valid_ano
11d0: 6e 79 6d 6f 75 73 28 0a 20 20 63 6f 6e 73 74 20  nymous(.  const 
11e0: 63 68 61 72 20 2a 7a 55 73 65 72 6e 61 6d 65 2c  char *zUsername,
11f0: 20 20 2f 2a 20 54 68 65 20 75 73 65 72 6e 61 6d    /* The usernam
1200: 65 2e 20 20 4d 75 73 74 20 62 65 20 22 61 6e 6f  e.  Must be "ano
1210: 6e 79 6d 6f 75 73 22 20 2a 2f 0a 20 20 63 6f 6e  nymous" */.  con
1220: 73 74 20 63 68 61 72 20 2a 7a 50 61 73 73 77 6f  st char *zPasswo
1230: 72 64 2c 20 20 2f 2a 20 54 68 65 20 73 75 70 70  rd,  /* The supp
1240: 6c 69 65 64 20 70 61 73 73 77 6f 72 64 20 2a 2f  lied password */
1250: 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a  .  const char *z
1260: 43 53 20 20 20 20 20 20 20 20 20 2f 2a 20 54 68  CS         /* Th
1270: 65 20 63 61 70 74 63 68 61 20 73 65 65 64 20 76  e captcha seed v
1280: 61 6c 75 65 20 2a 2f 0a 29 7b 0a 20 20 63 6f 6e  alue */.){.  con
1290: 73 74 20 63 68 61 72 20 2a 7a 50 77 3b 20 20 20  st char *zPw;   
12a0: 20 20 20 20 20 2f 2a 20 54 68 65 20 63 6f 72 72       /* The corr
12b0: 65 63 74 20 70 61 73 73 77 6f 72 64 20 73 68 6f  ect password sho
12c0: 77 6e 20 69 6e 20 74 68 65 20 63 61 70 74 63 68  wn in the captch
12d0: 61 20 2a 2f 0a 20 20 69 6e 74 20 75 69 64 3b 20  a */.  int uid; 
12e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f                 /
12f0: 2a 20 54 68 65 20 75 73 65 72 20 49 44 20 6f 66  * The user ID of
1300: 20 61 6e 6f 6e 79 6d 6f 75 73 20 2a 2f 0a 0a 20   anonymous */.. 
1310: 20 69 66 28 20 7a 55 73 65 72 6e 61 6d 65 3d 3d   if( zUsername==
1320: 30 20 29 20 72 65 74 75 72 6e 20 30 3b 0a 20 20  0 ) return 0;.  
1330: 65 6c 73 65 20 69 66 28 20 7a 50 61 73 73 77 6f  else if( zPasswo
1340: 72 64 3d 3d 30 20 29 20 72 65 74 75 72 6e 20 30  rd==0 ) return 0
1350: 3b 0a 20 20 65 6c 73 65 20 69 66 28 20 7a 43 53  ;.  else if( zCS
1360: 3d 3d 30 20 29 20 72 65 74 75 72 6e 20 30 3b 0a  ==0 ) return 0;.
1370: 20 20 65 6c 73 65 20 69 66 28 20 66 6f 73 73 69    else if( fossi
1380: 6c 5f 73 74 72 63 6d 70 28 7a 55 73 65 72 6e 61  l_strcmp(zUserna
1390: 6d 65 2c 22 61 6e 6f 6e 79 6d 6f 75 73 22 29 21  me,"anonymous")!
13a0: 3d 30 20 29 20 72 65 74 75 72 6e 20 30 3b 0a 20  =0 ) return 0;. 
13b0: 20 7a 50 77 20 3d 20 63 61 70 74 63 68 61 5f 64   zPw = captcha_d
13c0: 65 63 6f 64 65 28 28 75 6e 73 69 67 6e 65 64 20  ecode((unsigned 
13d0: 69 6e 74 29 61 74 6f 69 28 7a 43 53 29 29 3b 0a  int)atoi(zCS));.
13e0: 20 20 69 66 28 20 66 6f 73 73 69 6c 5f 73 74 72    if( fossil_str
13f0: 69 63 6d 70 28 7a 50 77 2c 20 7a 50 61 73 73 77  icmp(zPw, zPassw
1400: 6f 72 64 29 21 3d 30 20 29 20 72 65 74 75 72 6e  ord)!=0 ) return
1410: 20 30 3b 0a 20 20 75 69 64 20 3d 20 64 62 5f 69   0;.  uid = db_i
1420: 6e 74 28 30 2c 20 22 53 45 4c 45 43 54 20 75 69  nt(0, "SELECT ui
1430: 64 20 46 52 4f 4d 20 75 73 65 72 20 57 48 45 52  d FROM user WHER
1440: 45 20 6c 6f 67 69 6e 3d 27 61 6e 6f 6e 79 6d 6f  E login='anonymo
1450: 75 73 27 22 0a 20 20 20 20 20 20 20 20 20 20 20  us'".           
1460: 20 20 20 20 20 20 20 22 20 41 4e 44 20 6c 65 6e         " AND len
1470: 67 74 68 28 70 77 29 3e 30 20 41 4e 44 20 6c 65  gth(pw)>0 AND le
1480: 6e 67 74 68 28 63 61 70 29 3e 30 22 29 3b 0a 20  ngth(cap)>0");. 
1490: 20 72 65 74 75 72 6e 20 75 69 64 3b 0a 7d 0a 0a   return uid;.}..
14a0: 2f 2a 0a 2a 2a 20 4d 61 6b 65 20 73 75 72 65 20  /*.** Make sure 
14b0: 74 68 65 20 61 63 63 65 73 73 6c 6f 67 20 74 61  the accesslog ta
14c0: 62 6c 65 20 65 78 69 73 74 73 2e 20 20 43 72 65  ble exists.  Cre
14d0: 61 74 65 20 69 74 20 69 66 20 69 74 20 64 6f 65  ate it if it doe
14e0: 73 20 6e 6f 74 0a 2a 2f 0a 76 6f 69 64 20 63 72  s not.*/.void cr
14f0: 65 61 74 65 5f 61 63 63 65 73 73 6c 6f 67 5f 74  eate_accesslog_t
1500: 61 62 6c 65 28 76 6f 69 64 29 7b 0a 20 20 64 62  able(void){.  db
1510: 5f 6d 75 6c 74 69 5f 65 78 65 63 28 0a 20 20 20  _multi_exec(.   
1520: 20 22 43 52 45 41 54 45 20 54 41 42 4c 45 20 49   "CREATE TABLE I
1530: 46 20 4e 4f 54 20 45 58 49 53 54 53 20 72 65 70  F NOT EXISTS rep
1540: 6f 73 69 74 6f 72 79 2e 61 63 63 65 73 73 6c 6f  ository.accesslo
1550: 67 28 22 0a 20 20 20 20 22 20 20 75 6e 61 6d 65  g(".    "  uname
1560: 20 54 45 58 54 2c 22 0a 20 20 20 20 22 20 20 69   TEXT,".    "  i
1570: 70 61 64 64 72 20 54 45 58 54 2c 22 0a 20 20 20  paddr TEXT,".   
1580: 20 22 20 20 73 75 63 63 65 73 73 20 42 4f 4f 4c   "  success BOOL
1590: 45 41 4e 2c 22 0a 20 20 20 20 22 20 20 6d 74 69  EAN,".    "  mti
15a0: 6d 65 20 54 49 4d 45 53 54 41 4d 50 22 0a 20 20  me TIMESTAMP".  
15b0: 20 20 22 29 3b 22 0a 20 20 29 3b 0a 7d 0a 0a 2f    ");".  );.}../
15c0: 2a 0a 2a 2a 20 4d 61 6b 65 20 61 20 72 65 63 6f  *.** Make a reco
15d0: 72 64 20 6f 66 20 61 20 6c 6f 67 69 6e 20 61 74  rd of a login at
15e0: 74 65 6d 70 74 2c 20 69 66 20 6c 6f 67 69 6e 20  tempt, if login 
15f0: 72 65 63 6f 72 64 20 6b 65 65 70 69 6e 67 20 69  record keeping i
1600: 73 20 65 6e 61 62 6c 65 64 2e 0a 2a 2f 0a 73 74  s enabled..*/.st
1610: 61 74 69 63 20 76 6f 69 64 20 72 65 63 6f 72 64  atic void record
1620: 5f 6c 6f 67 69 6e 5f 61 74 74 65 6d 70 74 28 0a  _login_attempt(.
1630: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 55    const char *zU
1640: 73 65 72 6e 61 6d 65 2c 20 20 20 20 20 2f 2a 20  sername,     /* 
1650: 4e 61 6d 65 20 6f 66 20 75 73 65 72 20 6c 6f 67  Name of user log
1660: 67 69 6e 67 20 69 6e 20 2a 2f 0a 20 20 63 6f 6e  ging in */.  con
1670: 73 74 20 63 68 61 72 20 2a 7a 49 70 41 64 64 72  st char *zIpAddr
1680: 2c 20 20 20 20 20 20 20 2f 2a 20 49 50 20 61 64  ,       /* IP ad
1690: 64 72 65 73 73 20 66 72 6f 6d 20 77 68 69 63 68  dress from which
16a0: 20 74 68 65 79 20 6c 6f 67 67 65 64 20 69 6e 20   they logged in 
16b0: 2a 2f 0a 20 20 69 6e 74 20 62 53 75 63 63 65 73  */.  int bSucces
16c0: 73 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  s               
16d0: 2f 2a 20 54 72 75 65 20 69 66 20 74 68 65 20 61  /* True if the a
16e0: 74 74 65 6d 70 74 20 77 61 73 20 61 20 73 75 63  ttempt was a suc
16f0: 63 65 73 73 20 2a 2f 0a 29 7b 0a 20 20 69 66 28  cess */.){.  if(
1700: 20 21 64 62 5f 67 65 74 5f 62 6f 6f 6c 65 61 6e   !db_get_boolean
1710: 28 22 61 63 63 65 73 73 2d 6c 6f 67 22 2c 20 30  ("access-log", 0
1720: 29 20 29 20 72 65 74 75 72 6e 3b 0a 20 20 63 72  ) ) return;.  cr
1730: 65 61 74 65 5f 61 63 63 65 73 73 6c 6f 67 5f 74  eate_accesslog_t
1740: 61 62 6c 65 28 29 3b 0a 20 20 64 62 5f 6d 75 6c  able();.  db_mul
1750: 74 69 5f 65 78 65 63 28 0a 20 20 20 20 22 49 4e  ti_exec(.    "IN
1760: 53 45 52 54 20 49 4e 54 4f 20 61 63 63 65 73 73  SERT INTO access
1770: 6c 6f 67 28 75 6e 61 6d 65 2c 69 70 61 64 64 72  log(uname,ipaddr
1780: 2c 73 75 63 63 65 73 73 2c 6d 74 69 6d 65 29 22  ,success,mtime)"
1790: 0a 20 20 20 20 22 56 41 4c 55 45 53 28 25 51 2c  .    "VALUES(%Q,
17a0: 25 51 2c 25 64 2c 6a 75 6c 69 61 6e 64 61 79 28  %Q,%d,julianday(
17b0: 27 6e 6f 77 27 29 29 3b 22 2c 0a 20 20 20 20 7a  'now'));",.    z
17c0: 55 73 65 72 6e 61 6d 65 2c 20 7a 49 70 41 64 64  Username, zIpAdd
17d0: 72 2c 20 62 53 75 63 63 65 73 73 0a 20 20 29 3b  r, bSuccess.  );
17e0: 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 53 65 61 72 63 68  .}../*.** Search
17f0: 65 73 20 66 6f 72 20 74 68 65 20 75 73 65 72 20  es for the user 
1800: 49 44 20 6d 61 74 63 68 69 6e 67 20 74 68 65 20  ID matching the 
1810: 67 69 76 65 6e 20 6e 61 6d 65 20 61 6e 64 20 70  given name and p
1820: 61 73 73 77 6f 72 64 2e 0a 2a 2a 20 4f 6e 20 73  assword..** On s
1830: 75 63 63 65 73 73 20 69 74 20 72 65 74 75 72 6e  uccess it return
1840: 73 20 61 20 70 6f 73 69 74 69 76 65 20 76 61 6c  s a positive val
1850: 75 65 2e 20 4f 6e 20 65 72 72 6f 72 20 69 74 20  ue. On error it 
1860: 72 65 74 75 72 6e 73 20 30 2e 0a 2a 2a 20 4f 6e  returns 0..** On
1870: 20 73 65 72 69 6f 75 73 20 28 44 42 2d 6c 65 76   serious (DB-lev
1880: 65 6c 29 20 65 72 72 6f 72 20 69 74 20 77 69 6c  el) error it wil
1890: 6c 20 70 72 6f 62 61 62 6c 79 20 65 78 69 74 2e  l probably exit.
18a0: 0a 2a 2a 0a 2a 2a 20 7a 50 61 73 73 77 6f 72 64  .**.** zPassword
18b0: 20 6d 61 79 20 62 65 20 65 69 74 68 65 72 20 74   may be either t
18c0: 68 65 20 70 6c 61 69 6e 2d 74 65 78 74 20 66 6f  he plain-text fo
18d0: 72 6d 20 6f 72 20 74 68 65 20 65 6e 63 72 79 70  rm or the encryp
18e0: 74 65 64 0a 2a 2a 20 66 6f 72 6d 20 6f 66 20 74  ted.** form of t
18f0: 68 65 20 75 73 65 72 27 73 20 70 61 73 73 77 6f  he user's passwo
1900: 72 64 2e 0a 2a 2f 0a 69 6e 74 20 6c 6f 67 69 6e  rd..*/.int login
1910: 5f 73 65 61 72 63 68 5f 75 69 64 28 63 6f 6e 73  _search_uid(cons
1920: 74 20 63 68 61 72 20 2a 7a 55 73 65 72 6e 61 6d  t char *zUsernam
1930: 65 2c 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a  e, const char *z
1940: 50 61 73 73 77 64 29 7b 0a 20 20 63 68 61 72 20  Passwd){.  char 
1950: 2a 7a 53 68 61 31 50 77 20 3d 20 73 68 61 31 5f  *zSha1Pw = sha1_
1960: 73 68 61 72 65 64 5f 73 65 63 72 65 74 28 7a 50  shared_secret(zP
1970: 61 73 73 77 64 2c 20 7a 55 73 65 72 6e 61 6d 65  asswd, zUsername
1980: 2c 20 30 29 3b 0a 20 20 69 6e 74 20 75 69 64 20  , 0);.  int uid 
1990: 3d 20 64 62 5f 69 6e 74 28 30 2c 0a 20 20 20 20  = db_int(0,.    
19a0: 22 53 45 4c 45 43 54 20 75 69 64 20 46 52 4f 4d  "SELECT uid FROM
19b0: 20 75 73 65 72 22 0a 20 20 20 20 22 20 57 48 45   user".    " WHE
19c0: 52 45 20 6c 6f 67 69 6e 3d 25 51 22 0a 20 20 20  RE login=%Q".   
19d0: 20 22 20 20 20 41 4e 44 20 6c 65 6e 67 74 68 28   "   AND length(
19e0: 63 61 70 29 3e 30 20 41 4e 44 20 6c 65 6e 67 74  cap)>0 AND lengt
19f0: 68 28 70 77 29 3e 30 22 0a 20 20 20 20 22 20 20  h(pw)>0".    "  
1a00: 20 41 4e 44 20 6c 6f 67 69 6e 20 4e 4f 54 20 49   AND login NOT I
1a10: 4e 20 28 27 61 6e 6f 6e 79 6d 6f 75 73 27 2c 27  N ('anonymous','
1a20: 6e 6f 62 6f 64 79 27 2c 27 64 65 76 65 6c 6f 70  nobody','develop
1a30: 65 72 27 2c 27 72 65 61 64 65 72 27 29 22 0a 20  er','reader')". 
1a40: 20 20 20 22 20 20 20 41 4e 44 20 28 70 77 3d 25     "   AND (pw=%
1a50: 51 20 4f 52 20 28 6c 65 6e 67 74 68 28 70 77 29  Q OR (length(pw)
1a60: 3c 3e 34 30 20 41 4e 44 20 70 77 3d 25 51 29 29  <>40 AND pw=%Q))
1a70: 22 0a 20 20 20 20 22 20 20 20 41 4e 44 20 28 69  ".    "   AND (i
1a80: 6e 66 6f 20 4e 4f 54 20 4c 49 4b 45 20 27 25 25  nfo NOT LIKE '%%
1a90: 65 78 70 69 72 65 73 20 32 30 25 25 27 22 0a 20  expires 20%%'". 
1aa0: 20 20 20 22 20 20 20 20 20 20 4f 52 20 73 75 62     "      OR sub
1ab0: 73 74 72 28 69 6e 66 6f 2c 69 6e 73 74 72 28 6c  str(info,instr(l
1ac0: 6f 77 65 72 28 69 6e 66 6f 29 2c 27 65 78 70 69  ower(info),'expi
1ad0: 72 65 73 27 29 2b 38 2c 31 30 29 3e 64 61 74 65  res')+8,10)>date
1ae0: 74 69 6d 65 28 27 6e 6f 77 27 29 29 22 2c 0a 20  time('now'))",. 
1af0: 20 20 20 7a 55 73 65 72 6e 61 6d 65 2c 20 7a 53     zUsername, zS
1b00: 68 61 31 50 77 2c 20 7a 50 61 73 73 77 64 0a 20  ha1Pw, zPasswd. 
1b10: 20 29 3b 0a 0a 20 20 2f 2a 20 49 66 20 77 65 20   );..  /* If we 
1b20: 64 69 64 20 6e 6f 74 20 66 69 6e 64 20 61 20 6c  did not find a l
1b30: 6f 67 69 6e 20 6f 6e 20 74 68 65 20 66 69 72 73  ogin on the firs
1b40: 74 20 61 74 74 65 6d 70 74 2c 20 61 6e 64 20 74  t attempt, and t
1b50: 68 65 20 75 73 65 72 6e 61 6d 65 0a 20 20 2a 2a  he username.  **
1b60: 20 6c 6f 6f 6b 73 20 6c 69 6b 65 20 61 6e 20 65   looks like an e
1b70: 6d 61 69 6c 20 61 64 64 72 65 73 73 2c 20 74 68  mail address, th
1b80: 65 20 70 65 72 68 61 70 73 20 74 68 65 20 75 73  e perhaps the us
1b90: 65 72 20 65 6e 74 69 72 65 64 20 74 68 65 69 72  er entired their
1ba0: 0a 20 20 2a 2a 20 65 6d 61 69 6c 20 61 64 64 72  .  ** email addr
1bb0: 65 73 73 20 69 6e 73 74 65 61 64 20 6f 66 20 74  ess instead of t
1bc0: 68 65 69 72 20 6c 6f 67 69 6e 2e 20 20 54 72 79  heir login.  Try
1bd0: 20 61 67 61 69 6e 20 74 6f 20 6d 61 74 63 68 20   again to match 
1be0: 74 68 65 20 75 73 65 72 0a 20 20 2a 2a 20 61 67  the user.  ** ag
1bf0: 61 69 6e 73 74 20 65 6d 61 69 6c 20 61 64 64 72  ainst email addr
1c00: 65 73 73 65 73 20 63 6f 6e 74 61 69 6e 65 64 20  esses contained 
1c10: 69 6e 20 74 68 65 20 22 69 6e 66 6f 22 20 66 69  in the "info" fi
1c20: 65 6c 64 2e 0a 20 20 2a 2f 0a 20 20 69 66 28 20  eld..  */.  if( 
1c30: 75 69 64 3d 3d 30 20 26 26 20 73 74 72 63 68 72  uid==0 && strchr
1c40: 28 7a 55 73 65 72 6e 61 6d 65 2c 27 40 27 29 21  (zUsername,'@')!
1c50: 3d 30 20 29 7b 0a 20 20 20 20 53 74 6d 74 20 71  =0 ){.    Stmt q
1c60: 3b 0a 20 20 20 20 64 62 5f 70 72 65 70 61 72 65  ;.    db_prepare
1c70: 28 26 71 2c 0a 20 20 20 20 20 20 22 53 45 4c 45  (&q,.      "SELE
1c80: 43 54 20 6c 6f 67 69 6e 20 46 52 4f 4d 20 75 73  CT login FROM us
1c90: 65 72 22 0a 20 20 20 20 20 20 22 20 57 48 45 52  er".      " WHER
1ca0: 45 20 66 69 6e 64 5f 65 6d 61 69 6c 61 64 64 72  E find_emailaddr
1cb0: 28 69 6e 66 6f 29 3d 25 51 22 0a 20 20 20 20 20  (info)=%Q".     
1cc0: 20 22 20 20 20 41 4e 44 20 69 6e 73 74 72 28 6c   "   AND instr(l
1cd0: 6f 67 69 6e 2c 27 40 27 29 3d 3d 30 22 2c 0a 20  ogin,'@')==0",. 
1ce0: 20 20 20 20 20 7a 55 73 65 72 6e 61 6d 65 0a 20       zUsername. 
1cf0: 20 20 20 29 3b 0a 20 20 20 20 77 68 69 6c 65 28     );.    while(
1d00: 20 75 69 64 3d 3d 30 20 26 26 20 64 62 5f 73 74   uid==0 && db_st
1d10: 65 70 28 26 71 29 3d 3d 53 51 4c 49 54 45 5f 52  ep(&q)==SQLITE_R
1d20: 4f 57 20 29 7b 0a 20 20 20 20 20 20 20 75 69 64  OW ){.       uid
1d30: 20 3d 20 6c 6f 67 69 6e 5f 73 65 61 72 63 68 5f   = login_search_
1d40: 75 69 64 28 64 62 5f 63 6f 6c 75 6d 6e 5f 74 65  uid(db_column_te
1d50: 78 74 28 26 71 2c 30 29 2c 7a 50 61 73 73 77 64  xt(&q,0),zPasswd
1d60: 29 3b 0a 20 20 20 20 7d 0a 20 20 20 20 64 62 5f  );.    }.    db_
1d70: 66 69 6e 61 6c 69 7a 65 28 26 71 29 3b 0a 20 20  finalize(&q);.  
1d80: 7d 20 20 20 20 0a 20 20 66 72 65 65 28 7a 53 68  }    .  free(zSh
1d90: 61 31 50 77 29 3b 0a 20 20 72 65 74 75 72 6e 20  a1Pw);.  return 
1da0: 75 69 64 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 47 65  uid;.}../*.** Ge
1db0: 6e 65 72 61 74 65 73 20 61 20 6c 6f 67 69 6e 20  nerates a login 
1dc0: 63 6f 6f 6b 69 65 20 76 61 6c 75 65 20 66 6f 72  cookie value for
1dd0: 20 61 20 6e 6f 6e 2d 61 6e 6f 6e 79 6d 6f 75 73   a non-anonymous
1de0: 20 75 73 65 72 2e 0a 2a 2a 0a 2a 2a 20 54 68 65   user..**.** The
1df0: 20 7a 48 61 73 68 20 70 61 72 61 6d 65 74 65 72   zHash parameter
1e00: 20 6d 75 73 74 20 62 65 20 61 20 72 61 6e 64 6f   must be a rando
1e10: 6d 20 76 61 6c 75 65 20 77 68 69 63 68 20 6d 75  m value which mu
1e20: 73 74 20 62 65 0a 2a 2a 20 73 75 62 73 65 71 75  st be.** subsequ
1e30: 65 6e 74 6c 79 20 73 74 6f 72 65 64 20 69 6e 20  ently stored in 
1e40: 75 73 65 72 2e 63 6f 6f 6b 69 65 20 66 6f 72 20  user.cookie for 
1e50: 6c 61 74 65 72 20 76 61 6c 69 64 61 74 69 6f 6e  later validation
1e60: 2e 0a 2a 2a 0a 2a 2a 20 54 68 65 20 72 65 74 75  ..**.** The retu
1e70: 72 6e 65 64 20 6d 65 6d 6f 72 79 20 73 68 6f 75  rned memory shou
1e80: 6c 64 20 62 65 20 66 72 65 65 28 29 64 20 61 66  ld be free()d af
1e90: 74 65 72 20 75 73 65 2e 0a 2a 2f 0a 63 68 61 72  ter use..*/.char
1ea0: 20 2a 6c 6f 67 69 6e 5f 67 65 6e 5f 75 73 65 72   *login_gen_user
1eb0: 5f 63 6f 6f 6b 69 65 5f 76 61 6c 75 65 28 63 6f  _cookie_value(co
1ec0: 6e 73 74 20 63 68 61 72 20 2a 7a 55 73 65 72 6e  nst char *zUsern
1ed0: 61 6d 65 2c 20 63 6f 6e 73 74 20 63 68 61 72 20  ame, const char 
1ee0: 2a 7a 48 61 73 68 29 7b 0a 20 20 63 68 61 72 20  *zHash){.  char 
1ef0: 2a 7a 50 72 6f 6a 43 6f 64 65 20 3d 20 64 62 5f  *zProjCode = db_
1f00: 67 65 74 28 22 70 72 6f 6a 65 63 74 2d 63 6f 64  get("project-cod
1f10: 65 22 2c 4e 55 4c 4c 29 3b 0a 20 20 63 68 61 72  e",NULL);.  char
1f20: 20 2a 7a 43 6f 64 65 20 3d 20 61 62 62 72 65 76   *zCode = abbrev
1f30: 69 61 74 65 64 5f 70 72 6f 6a 65 63 74 5f 63 6f  iated_project_co
1f40: 64 65 28 7a 50 72 6f 6a 43 6f 64 65 29 3b 0a 20  de(zProjCode);. 
1f50: 20 66 72 65 65 28 7a 50 72 6f 6a 43 6f 64 65 29   free(zProjCode)
1f60: 3b 0a 20 20 61 73 73 65 72 74 28 28 7a 55 73 65  ;.  assert((zUse
1f70: 72 6e 61 6d 65 20 26 26 20 2a 7a 55 73 65 72 6e  rname && *zUsern
1f80: 61 6d 65 29 20 26 26 20 22 49 6e 76 61 6c 69 64  ame) && "Invalid
1f90: 20 75 73 65 72 20 64 61 74 61 2e 22 29 3b 0a 20   user data.");. 
1fa0: 20 72 65 74 75 72 6e 20 6d 70 72 69 6e 74 66 28   return mprintf(
1fb0: 22 25 73 2f 25 7a 2f 25 73 22 2c 20 7a 48 61 73  "%s/%z/%s", zHas
1fc0: 68 2c 20 7a 43 6f 64 65 2c 20 7a 55 73 65 72 6e  h, zCode, zUsern
1fd0: 61 6d 65 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 47  ame);.}../*.** G
1fe0: 65 6e 65 72 61 74 65 73 20 61 20 6c 6f 67 69 6e  enerates a login
1ff0: 20 63 6f 6f 6b 69 65 20 66 6f 72 20 4e 4f 4e 2d   cookie for NON-
2000: 41 4e 4f 4e 59 4d 4f 55 53 20 75 73 65 72 73 2e  ANONYMOUS users.
2010: 20 20 4e 6f 74 65 20 74 68 61 74 20 74 68 69 73    Note that this
2020: 0a 2a 2a 20 66 75 6e 63 74 69 6f 6e 20 22 63 6f  .** function "co
2030: 75 6c 64 22 20 66 69 67 75 72 65 20 6f 75 74 20  uld" figure out 
2040: 74 68 65 20 75 69 64 20 62 79 20 69 74 73 65 6c  the uid by itsel
2050: 66 20 62 75 74 20 69 74 20 63 75 72 72 65 6e 74  f but it current
2060: 6c 79 0a 2a 2a 20 64 6f 65 73 6e 27 74 20 62 65  ly.** doesn't be
2070: 63 61 75 73 65 20 74 68 65 20 63 6f 64 65 20 77  cause the code w
2080: 68 69 63 68 20 63 61 6c 6c 73 20 74 68 69 73 20  hich calls this 
2090: 61 6c 72 65 61 64 79 20 68 61 73 20 74 68 65 20  already has the 
20a0: 75 69 64 2e 0a 2a 2a 0a 2a 2a 20 54 68 69 73 20  uid..**.** This 
20b0: 66 75 6e 63 74 69 6f 6e 20 61 6c 73 6f 20 75 70  function also up
20c0: 64 61 74 65 73 20 74 68 65 20 75 73 65 72 2e 63  dates the user.c
20d0: 6f 6f 6b 69 65 2c 20 75 73 65 72 2e 69 70 61 64  ookie, user.ipad
20e0: 64 72 2c 0a 2a 2a 20 61 6e 64 20 75 73 65 72 2e  dr,.** and user.
20f0: 63 65 78 70 69 72 65 20 66 69 65 6c 64 73 20 66  cexpire fields f
2100: 6f 72 20 74 68 65 20 67 69 76 65 6e 20 75 73 65  or the given use
2110: 72 2e 0a 2a 2a 0a 2a 2a 20 49 66 20 7a 44 65 73  r..**.** If zDes
2120: 74 20 69 73 20 6e 6f 74 20 4e 55 4c 4c 20 74 68  t is not NULL th
2130: 65 6e 20 74 68 65 20 67 65 6e 65 72 61 74 65 64  en the generated
2140: 20 63 6f 6f 6b 69 65 20 69 73 20 63 6f 70 69 65   cookie is copie
2150: 64 20 74 6f 0a 2a 2a 20 2a 7a 44 64 65 73 74 20  d to.** *zDdest 
2160: 61 6e 64 20 6f 77 6e 65 72 73 68 69 70 20 69 73  and ownership is
2170: 20 74 72 61 6e 73 66 65 72 65 64 20 74 6f 20 74   transfered to t
2180: 68 65 20 63 61 6c 6c 65 72 20 28 77 68 6f 20 73  he caller (who s
2190: 68 6f 75 6c 64 0a 2a 2a 20 65 76 65 6e 74 75 61  hould.** eventua
21a0: 6c 6c 79 20 70 61 73 73 20 69 74 20 74 6f 20 66  lly pass it to f
21b0: 72 65 65 28 29 29 2e 0a 2a 2f 0a 76 6f 69 64 20  ree())..*/.void 
21c0: 6c 6f 67 69 6e 5f 73 65 74 5f 75 73 65 72 5f 63  login_set_user_c
21d0: 6f 6f 6b 69 65 28 0a 20 20 63 6f 6e 73 74 20 63  ookie(.  const c
21e0: 68 61 72 20 2a 7a 55 73 65 72 6e 61 6d 65 2c 20  har *zUsername, 
21f0: 20 2f 2a 20 55 73 65 72 27 73 20 6e 61 6d 65 20   /* User's name 
2200: 2a 2f 0a 20 20 69 6e 74 20 75 69 64 2c 20 20 20  */.  int uid,   
2210: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
2220: 55 73 65 72 27 73 20 49 44 20 2a 2f 0a 20 20 63  User's ID */.  c
2230: 68 61 72 20 2a 2a 7a 44 65 73 74 20 20 20 20 20  har **zDest     
2240: 20 20 20 20 20 20 20 2f 2a 20 4f 70 74 69 6f 6e         /* Option
2250: 61 6c 3a 20 73 74 6f 72 65 20 67 65 6e 65 72 61  al: store genera
2260: 74 65 64 20 63 6f 6f 6b 69 65 20 76 61 6c 75 65  ted cookie value
2270: 2e 20 2a 2f 0a 29 7b 0a 20 20 63 6f 6e 73 74 20  . */.){.  const 
2280: 63 68 61 72 20 2a 7a 43 6f 6f 6b 69 65 4e 61 6d  char *zCookieNam
2290: 65 20 3d 20 6c 6f 67 69 6e 5f 63 6f 6f 6b 69 65  e = login_cookie
22a0: 5f 6e 61 6d 65 28 29 3b 0a 20 20 63 6f 6e 73 74  _name();.  const
22b0: 20 63 68 61 72 20 2a 7a 45 78 70 69 72 65 20 3d   char *zExpire =
22c0: 20 64 62 5f 67 65 74 28 22 63 6f 6f 6b 69 65 2d   db_get("cookie-
22d0: 65 78 70 69 72 65 22 2c 22 38 37 36 36 22 29 3b  expire","8766");
22e0: 0a 20 20 69 6e 74 20 65 78 70 69 72 65 73 20 3d  .  int expires =
22f0: 20 61 74 6f 69 28 7a 45 78 70 69 72 65 29 2a 33   atoi(zExpire)*3
2300: 36 30 30 3b 0a 20 20 63 68 61 72 20 2a 7a 48 61  600;.  char *zHa
2310: 73 68 3b 0a 20 20 63 68 61 72 20 2a 7a 43 6f 6f  sh;.  char *zCoo
2320: 6b 69 65 3b 0a 20 20 63 6f 6e 73 74 20 63 68 61  kie;.  const cha
2330: 72 20 2a 7a 49 70 41 64 64 72 20 3d 20 50 44 28  r *zIpAddr = PD(
2340: 22 52 45 4d 4f 54 45 5f 41 44 44 52 22 2c 22 6e  "REMOTE_ADDR","n
2350: 69 6c 22 29 3b 20 2f 2a 20 49 50 20 61 64 64 72  il"); /* IP addr
2360: 65 73 73 20 6f 66 20 75 73 65 72 20 2a 2f 0a 20  ess of user */. 
2370: 20 63 68 61 72 20 2a 7a 52 65 6d 6f 74 65 41 64   char *zRemoteAd
2380: 64 72 20 3d 20 69 70 50 72 65 66 69 78 28 7a 49  dr = ipPrefix(zI
2390: 70 41 64 64 72 29 3b 20 20 20 20 20 20 20 20 20  pAddr);         
23a0: 2f 2a 20 41 62 62 72 65 76 69 61 74 65 64 20 49  /* Abbreviated I
23b0: 50 20 61 64 64 72 65 73 73 20 2a 2f 0a 0a 20 20  P address */..  
23c0: 61 73 73 65 72 74 28 28 7a 55 73 65 72 6e 61 6d  assert((zUsernam
23d0: 65 20 26 26 20 2a 7a 55 73 65 72 6e 61 6d 65 29  e && *zUsername)
23e0: 20 26 26 20 28 75 69 64 20 3e 20 30 29 20 26 26   && (uid > 0) &&
23f0: 20 22 49 6e 76 61 6c 69 64 20 75 73 65 72 20 64   "Invalid user d
2400: 61 74 61 2e 22 29 3b 0a 20 20 7a 48 61 73 68 20  ata.");.  zHash 
2410: 3d 20 64 62 5f 74 65 78 74 28 30 2c 0a 20 20 20  = db_text(0,.   
2420: 20 20 20 22 53 45 4c 45 43 54 20 63 6f 6f 6b 69     "SELECT cooki
2430: 65 20 46 52 4f 4d 20 75 73 65 72 22 0a 20 20 20  e FROM user".   
2440: 20 20 20 22 20 57 48 45 52 45 20 75 69 64 3d 25     " WHERE uid=%
2450: 64 22 0a 20 20 20 20 20 20 22 20 20 20 41 4e 44  d".      "   AND
2460: 20 69 70 61 64 64 72 3d 25 51 22 0a 20 20 20 20   ipaddr=%Q".    
2470: 20 20 22 20 20 20 41 4e 44 20 63 65 78 70 69 72    "   AND cexpir
2480: 65 3e 6a 75 6c 69 61 6e 64 61 79 28 27 6e 6f 77  e>julianday('now
2490: 27 29 22 0a 20 20 20 20 20 20 22 20 20 20 41 4e  ')".      "   AN
24a0: 44 20 6c 65 6e 67 74 68 28 63 6f 6f 6b 69 65 29  D length(cookie)
24b0: 3e 33 30 22 2c 0a 20 20 20 20 20 20 75 69 64 2c  >30",.      uid,
24c0: 20 7a 52 65 6d 6f 74 65 41 64 64 72 29 3b 0a 20   zRemoteAddr);. 
24d0: 20 69 66 28 20 7a 48 61 73 68 3d 3d 30 20 29 20   if( zHash==0 ) 
24e0: 7a 48 61 73 68 20 3d 20 64 62 5f 74 65 78 74 28  zHash = db_text(
24f0: 30 2c 20 22 53 45 4c 45 43 54 20 68 65 78 28 72  0, "SELECT hex(r
2500: 61 6e 64 6f 6d 62 6c 6f 62 28 32 35 29 29 22 29  andomblob(25))")
2510: 3b 0a 20 20 7a 43 6f 6f 6b 69 65 20 3d 20 6c 6f  ;.  zCookie = lo
2520: 67 69 6e 5f 67 65 6e 5f 75 73 65 72 5f 63 6f 6f  gin_gen_user_coo
2530: 6b 69 65 5f 76 61 6c 75 65 28 7a 55 73 65 72 6e  kie_value(zUsern
2540: 61 6d 65 2c 20 7a 48 61 73 68 29 3b 0a 20 20 63  ame, zHash);.  c
2550: 67 69 5f 73 65 74 5f 63 6f 6f 6b 69 65 28 7a 43  gi_set_cookie(zC
2560: 6f 6f 6b 69 65 4e 61 6d 65 2c 20 7a 43 6f 6f 6b  ookieName, zCook
2570: 69 65 2c 20 6c 6f 67 69 6e 5f 63 6f 6f 6b 69 65  ie, login_cookie
2580: 5f 70 61 74 68 28 29 2c 20 65 78 70 69 72 65 73  _path(), expires
2590: 29 3b 0a 20 20 72 65 63 6f 72 64 5f 6c 6f 67 69  );.  record_logi
25a0: 6e 5f 61 74 74 65 6d 70 74 28 7a 55 73 65 72 6e  n_attempt(zUsern
25b0: 61 6d 65 2c 20 7a 49 70 41 64 64 72 2c 20 31 29  ame, zIpAddr, 1)
25c0: 3b 0a 20 20 64 62 5f 6d 75 6c 74 69 5f 65 78 65  ;.  db_multi_exe
25d0: 63 28 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  c(.             
25e0: 20 20 20 22 55 50 44 41 54 45 20 75 73 65 72 20     "UPDATE user 
25f0: 53 45 54 20 63 6f 6f 6b 69 65 3d 25 51 2c 20 69  SET cookie=%Q, i
2600: 70 61 64 64 72 3d 25 51 2c 20 22 0a 20 20 20 20  paddr=%Q, ".    
2610: 20 20 20 20 20 20 20 20 20 20 20 20 22 20 20 63              "  c
2620: 65 78 70 69 72 65 3d 6a 75 6c 69 61 6e 64 61 79  expire=julianday
2630: 28 27 6e 6f 77 27 29 2b 25 64 2f 38 36 34 30 30  ('now')+%d/86400
2640: 2e 30 20 57 48 45 52 45 20 75 69 64 3d 25 64 22  .0 WHERE uid=%d"
2650: 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,.              
2660: 20 20 7a 48 61 73 68 2c 20 7a 52 65 6d 6f 74 65    zHash, zRemote
2670: 41 64 64 72 2c 20 65 78 70 69 72 65 73 2c 20 75  Addr, expires, u
2680: 69 64 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  id.             
2690: 20 20 20 29 3b 0a 20 20 66 72 65 65 28 7a 52 65     );.  free(zRe
26a0: 6d 6f 74 65 41 64 64 72 29 3b 0a 20 20 66 72 65  moteAddr);.  fre
26b0: 65 28 7a 48 61 73 68 29 3b 0a 20 20 69 66 28 20  e(zHash);.  if( 
26c0: 7a 44 65 73 74 20 29 7b 0a 20 20 20 20 2a 7a 44  zDest ){.    *zD
26d0: 65 73 74 20 3d 20 7a 43 6f 6f 6b 69 65 3b 0a 20  est = zCookie;. 
26e0: 20 7d 65 6c 73 65 7b 0a 20 20 20 20 66 72 65 65   }else{.    free
26f0: 28 7a 43 6f 6f 6b 69 65 29 3b 0a 20 20 7d 0a 7d  (zCookie);.  }.}
2700: 0a 0a 2f 2a 20 53 65 74 73 20 61 20 63 6f 6f 6b  ../* Sets a cook
2710: 69 65 20 66 6f 72 20 61 6e 20 61 6e 6f 6e 79 6d  ie for an anonym
2720: 6f 75 73 20 75 73 65 72 20 6c 6f 67 69 6e 2c 20  ous user login, 
2730: 77 68 69 63 68 20 6c 6f 6f 6b 73 20 6c 69 6b 65  which looks like
2740: 20 74 68 69 73 3a 0a 2a 2a 0a 2a 2a 20 20 20 20   this:.**.**    
2750: 48 41 53 48 2f 54 49 4d 45 2f 61 6e 6f 6e 79 6d  HASH/TIME/anonym
2760: 6f 75 73 0a 2a 2a 0a 2a 2a 20 57 68 65 72 65 20  ous.**.** Where 
2770: 48 41 53 48 20 69 73 20 74 68 65 20 73 68 61 31  HASH is the sha1
2780: 73 75 6d 20 6f 66 20 54 49 4d 45 2f 49 50 41 44  sum of TIME/IPAD
2790: 44 52 2f 53 45 43 52 45 54 2c 20 69 6e 20 77 68  DR/SECRET, in wh
27a0: 69 63 68 20 49 50 41 44 44 52 0a 2a 2a 20 69 73  ich IPADDR.** is
27b0: 20 74 68 65 20 61 62 62 72 65 76 69 61 74 65 64   the abbreviated
27c0: 20 49 50 20 61 64 64 72 65 73 73 20 61 6e 64 20   IP address and 
27d0: 53 45 43 52 45 54 20 69 73 20 63 61 70 74 63 68  SECRET is captch
27e0: 61 2d 73 65 63 72 65 74 2e 0a 2a 2a 0a 2a 2a 20  a-secret..**.** 
27f0: 49 66 20 65 69 74 68 65 72 20 7a 49 70 41 64 64  If either zIpAdd
2800: 72 20 6f 72 20 7a 52 65 6d 6f 74 65 41 64 64 72  r or zRemoteAddr
2810: 20 61 72 65 20 4e 55 4c 4c 20 74 68 65 6e 20 52   are NULL then R
2820: 45 4d 4f 54 45 5f 41 44 44 52 0a 2a 2a 20 69 73  EMOTE_ADDR.** is
2830: 20 75 73 65 64 2e 0a 2a 2a 0a 2a 2a 20 49 66 20   used..**.** If 
2840: 7a 43 6f 6f 6b 69 65 44 65 73 74 20 69 73 20 6e  zCookieDest is n
2850: 6f 74 20 4e 55 4c 4c 20 74 68 65 6e 20 74 68 65  ot NULL then the
2860: 20 67 65 6e 65 72 61 74 65 64 20 63 6f 6f 6b 69   generated cooki
2870: 65 20 69 73 20 61 73 73 69 67 6e 65 64 20 74 6f  e is assigned to
2880: 0a 2a 2a 20 2a 7a 43 6f 6f 6b 69 65 44 65 73 74  .** *zCookieDest
2890: 20 61 6e 64 20 74 68 65 20 63 61 6c 6c 65 72 20   and the caller 
28a0: 6d 75 73 74 20 65 76 65 6e 74 75 61 6c 6c 79 20  must eventually 
28b0: 66 72 65 65 28 29 20 69 74 2e 0a 2a 2f 0a 76 6f  free() it..*/.vo
28c0: 69 64 20 6c 6f 67 69 6e 5f 73 65 74 5f 61 6e 6f  id login_set_ano
28d0: 6e 5f 63 6f 6f 6b 69 65 28 63 6f 6e 73 74 20 63  n_cookie(const c
28e0: 68 61 72 20 2a 7a 49 70 41 64 64 72 2c 20 63 68  har *zIpAddr, ch
28f0: 61 72 20 2a 2a 7a 43 6f 6f 6b 69 65 44 65 73 74  ar **zCookieDest
2900: 20 29 7b 0a 20 20 63 6f 6e 73 74 20 63 68 61 72   ){.  const char
2910: 20 2a 7a 4e 6f 77 3b 20 20 20 20 20 20 20 20 20   *zNow;         
2920: 20 20 20 2f 2a 20 43 75 72 72 65 6e 74 20 74 69     /* Current ti
2930: 6d 65 20 28 6a 75 6c 69 61 6e 20 64 61 79 20 6e  me (julian day n
2940: 75 6d 62 65 72 29 20 2a 2f 0a 20 20 63 68 61 72  umber) */.  char
2950: 20 2a 7a 43 6f 6f 6b 69 65 3b 20 20 20 20 20 20   *zCookie;      
2960: 20 20 20 20 20 20 20 20 20 2f 2a 20 54 68 65 20           /* The 
2970: 6c 6f 67 69 6e 20 63 6f 6f 6b 69 65 20 2a 2f 0a  login cookie */.
2980: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 43    const char *zC
2990: 6f 6f 6b 69 65 4e 61 6d 65 3b 20 20 20 20 20 2f  ookieName;     /
29a0: 2a 20 4e 61 6d 65 20 6f 66 20 74 68 65 20 6c 6f  * Name of the lo
29b0: 67 69 6e 20 63 6f 6f 6b 69 65 20 2a 2f 0a 20 20  gin cookie */.  
29c0: 42 6c 6f 62 20 62 3b 20 20 20 20 20 20 20 20 20  Blob b;         
29d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
29e0: 42 6c 6f 62 20 75 73 65 64 20 64 75 72 69 6e 67  Blob used during
29f0: 20 63 6f 6f 6b 69 65 20 63 6f 6e 73 74 72 75 63   cookie construc
2a00: 74 69 6f 6e 20 2a 2f 0a 20 20 63 68 61 72 20 2a  tion */.  char *
2a10: 7a 52 65 6d 6f 74 65 41 64 64 72 3b 20 20 20 20  zRemoteAddr;    
2a20: 20 20 20 20 20 20 20 2f 2a 20 41 62 62 72 65 76         /* Abbrev
2a30: 69 61 74 65 64 20 49 50 20 61 64 64 72 65 73 73  iated IP address
2a40: 20 2a 2f 0a 20 20 69 66 28 21 7a 49 70 41 64 64   */.  if(!zIpAdd
2a50: 72 29 7b 0a 20 20 20 20 7a 49 70 41 64 64 72 20  r){.    zIpAddr 
2a60: 3d 20 50 44 28 22 52 45 4d 4f 54 45 5f 41 44 44  = PD("REMOTE_ADD
2a70: 52 22 2c 22 6e 69 6c 22 29 3b 0a 20 20 7d 0a 20  R","nil");.  }. 
2a80: 20 7a 52 65 6d 6f 74 65 41 64 64 72 20 3d 20 69   zRemoteAddr = i
2a90: 70 50 72 65 66 69 78 28 7a 49 70 41 64 64 72 29  pPrefix(zIpAddr)
2aa0: 3b 0a 20 20 7a 43 6f 6f 6b 69 65 4e 61 6d 65 20  ;.  zCookieName 
2ab0: 3d 20 6c 6f 67 69 6e 5f 63 6f 6f 6b 69 65 5f 6e  = login_cookie_n
2ac0: 61 6d 65 28 29 3b 0a 20 20 7a 4e 6f 77 20 3d 20  ame();.  zNow = 
2ad0: 64 62 5f 74 65 78 74 28 22 30 22 2c 20 22 53 45  db_text("0", "SE
2ae0: 4c 45 43 54 20 6a 75 6c 69 61 6e 64 61 79 28 27  LECT julianday('
2af0: 6e 6f 77 27 29 22 29 3b 0a 20 20 61 73 73 65 72  now')");.  asser
2b00: 74 28 20 7a 43 6f 6f 6b 69 65 4e 61 6d 65 20 26  t( zCookieName &
2b10: 26 20 7a 52 65 6d 6f 74 65 41 64 64 72 20 26 26  & zRemoteAddr &&
2b20: 20 7a 49 70 41 64 64 72 20 26 26 20 7a 4e 6f 77   zIpAddr && zNow
2b30: 20 29 3b 0a 20 20 62 6c 6f 62 5f 69 6e 69 74 28   );.  blob_init(
2b40: 26 62 2c 20 7a 4e 6f 77 2c 20 2d 31 29 3b 0a 20  &b, zNow, -1);. 
2b50: 20 62 6c 6f 62 5f 61 70 70 65 6e 64 66 28 26 62   blob_appendf(&b
2b60: 2c 20 22 2f 25 73 2f 25 73 22 2c 20 7a 52 65 6d  , "/%s/%s", zRem
2b70: 6f 74 65 41 64 64 72 2c 20 64 62 5f 67 65 74 28  oteAddr, db_get(
2b80: 22 63 61 70 74 63 68 61 2d 73 65 63 72 65 74 22  "captcha-secret"
2b90: 2c 22 22 29 29 3b 0a 20 20 73 68 61 31 73 75 6d  ,""));.  sha1sum
2ba0: 5f 62 6c 6f 62 28 26 62 2c 20 26 62 29 3b 0a 20  _blob(&b, &b);. 
2bb0: 20 7a 43 6f 6f 6b 69 65 20 3d 20 6d 70 72 69 6e   zCookie = mprin
2bc0: 74 66 28 22 25 73 2f 25 73 2f 61 6e 6f 6e 79 6d  tf("%s/%s/anonym
2bd0: 6f 75 73 22 2c 20 62 6c 6f 62 5f 62 75 66 66 65  ous", blob_buffe
2be0: 72 28 26 62 29 2c 20 7a 4e 6f 77 29 3b 0a 20 20  r(&b), zNow);.  
2bf0: 62 6c 6f 62 5f 72 65 73 65 74 28 26 62 29 3b 0a  blob_reset(&b);.
2c00: 20 20 63 67 69 5f 73 65 74 5f 63 6f 6f 6b 69 65    cgi_set_cookie
2c10: 28 7a 43 6f 6f 6b 69 65 4e 61 6d 65 2c 20 7a 43  (zCookieName, zC
2c20: 6f 6f 6b 69 65 2c 20 6c 6f 67 69 6e 5f 63 6f 6f  ookie, login_coo
2c30: 6b 69 65 5f 70 61 74 68 28 29 2c 20 36 2a 33 36  kie_path(), 6*36
2c40: 30 30 29 3b 0a 20 20 69 66 28 20 7a 43 6f 6f 6b  00);.  if( zCook
2c50: 69 65 44 65 73 74 20 29 7b 0a 20 20 20 20 2a 7a  ieDest ){.    *z
2c60: 43 6f 6f 6b 69 65 44 65 73 74 20 3d 20 7a 43 6f  CookieDest = zCo
2c70: 6f 6b 69 65 3b 0a 20 20 7d 65 6c 73 65 7b 0a 20  okie;.  }else{. 
2c80: 20 20 20 66 72 65 65 28 7a 43 6f 6f 6b 69 65 29     free(zCookie)
2c90: 3b 0a 20 20 7d 0a 0a 7d 0a 0a 2f 2a 0a 2a 2a 20  ;.  }..}../*.** 
2ca0: 22 55 6e 73 65 74 73 22 20 74 68 65 20 6c 6f 67  "Unsets" the log
2cb0: 69 6e 20 63 6f 6f 6b 69 65 20 28 69 6e 73 6f 66  in cookie (insof
2cc0: 61 72 20 61 73 20 63 6f 6f 6b 69 65 73 20 63 61  ar as cookies ca
2cd0: 6e 20 62 65 20 75 6e 73 65 74 29 20 61 6e 64 0a  n be unset) and.
2ce0: 2a 2a 20 63 6c 65 61 72 73 20 74 68 65 20 63 75  ** clears the cu
2cf0: 72 72 65 6e 74 20 75 73 65 72 27 73 20 28 67 2e  rrent user's (g.
2d00: 75 73 65 72 55 69 64 29 20 6c 6f 67 69 6e 20 69  userUid) login i
2d10: 6e 66 6f 72 6d 61 74 69 6f 6e 20 66 72 6f 6d 20  nformation from 
2d20: 74 68 65 0a 2a 2a 20 75 73 65 72 20 74 61 62 6c  the.** user tabl
2d30: 65 2e 20 53 65 74 73 3a 20 75 73 65 72 2e 63 6f  e. Sets: user.co
2d40: 6f 6b 69 65 2c 20 75 73 65 72 2e 69 70 61 64 64  okie, user.ipadd
2d50: 72 2c 20 75 73 65 72 2e 63 65 78 70 69 72 65 2e  r, user.cexpire.
2d60: 0a 2a 2a 0a 2a 2a 20 57 65 20 63 6f 75 6c 64 2f  .**.** We could/
2d70: 73 68 6f 75 6c 64 20 61 72 67 75 61 62 6c 79 20  should arguably 
2d80: 63 6c 65 61 72 20 6f 75 74 20 67 2e 75 73 65 72  clear out g.user
2d90: 55 69 64 20 61 6e 64 20 67 2e 70 65 72 6d 20 68  Uid and g.perm h
2da0: 65 72 65 2c 20 62 75 74 0a 2a 2a 20 77 65 20 64  ere, but.** we d
2db0: 6f 6e 27 74 20 63 75 72 72 65 6e 74 6c 79 20 64  on't currently d
2dc0: 6f 20 6e 6f 74 2e 0a 2a 2a 0a 2a 2a 20 54 68 69  o not..**.** Thi
2dd0: 73 20 69 73 20 61 20 6e 6f 2d 6f 70 20 69 66 20  s is a no-op if 
2de0: 67 2e 75 73 65 72 55 69 64 20 69 73 20 30 2e 0a  g.userUid is 0..
2df0: 2a 2f 0a 76 6f 69 64 20 6c 6f 67 69 6e 5f 63 6c  */.void login_cl
2e00: 65 61 72 5f 6c 6f 67 69 6e 5f 64 61 74 61 28 29  ear_login_data()
2e10: 7b 0a 20 20 69 66 28 21 67 2e 75 73 65 72 55 69  {.  if(!g.userUi
2e20: 64 29 7b 0a 20 20 20 20 72 65 74 75 72 6e 3b 0a  d){.    return;.
2e30: 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 63 6f 6e    }else{.    con
2e40: 73 74 20 63 68 61 72 20 2a 63 6f 6f 6b 69 65 20  st char *cookie 
2e50: 3d 20 6c 6f 67 69 6e 5f 63 6f 6f 6b 69 65 5f 6e  = login_cookie_n
2e60: 61 6d 65 28 29 3b 0a 20 20 20 20 2f 2a 20 54 6f  ame();.    /* To
2e70: 20 6c 6f 67 6f 75 74 2c 20 63 68 61 6e 67 65 20   logout, change 
2e80: 74 68 65 20 63 6f 6f 6b 69 65 20 76 61 6c 75 65  the cookie value
2e90: 20 74 6f 20 61 6e 20 65 6d 70 74 79 20 73 74 72   to an empty str
2ea0: 69 6e 67 20 2a 2f 0a 20 20 20 20 63 67 69 5f 73  ing */.    cgi_s
2eb0: 65 74 5f 63 6f 6f 6b 69 65 28 63 6f 6f 6b 69 65  et_cookie(cookie
2ec0: 2c 20 22 22 2c 0a 20 20 20 20 20 20 20 20 20 20  , "",.          
2ed0: 20 20 20 20 20 20 20 20 20 6c 6f 67 69 6e 5f 63           login_c
2ee0: 6f 6f 6b 69 65 5f 70 61 74 68 28 29 2c 20 2d 38  ookie_path(), -8
2ef0: 36 34 30 30 29 3b 0a 20 20 20 20 64 62 5f 6d 75  6400);.    db_mu
2f00: 6c 74 69 5f 65 78 65 63 28 22 55 50 44 41 54 45  lti_exec("UPDATE
2f10: 20 75 73 65 72 20 53 45 54 20 63 6f 6f 6b 69 65   user SET cookie
2f20: 3d 4e 55 4c 4c 2c 20 69 70 61 64 64 72 3d 4e 55  =NULL, ipaddr=NU
2f30: 4c 4c 2c 20 22 0a 20 20 20 20 20 20 20 20 20 20  LL, ".          
2f40: 20 20 20 20 20 20 20 20 22 20 20 63 65 78 70 69          "  cexpi
2f50: 72 65 3d 30 20 57 48 45 52 45 20 75 69 64 3d 25  re=0 WHERE uid=%
2f60: 64 22 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  d".             
2f70: 20 20 20 20 20 22 20 20 41 4e 44 20 6c 6f 67 69       "  AND logi
2f80: 6e 20 4e 4f 54 20 49 4e 20 28 27 61 6e 6f 6e 79  n NOT IN ('anony
2f90: 6d 6f 75 73 27 2c 27 6e 6f 62 6f 64 79 27 2c 22  mous','nobody',"
2fa0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
2fb0: 20 20 20 22 20 20 27 64 65 76 65 6c 6f 70 65 72     "  'developer
2fc0: 27 2c 27 72 65 61 64 65 72 27 29 22 2c 20 67 2e  ','reader')", g.
2fd0: 75 73 65 72 55 69 64 29 3b 0a 20 20 20 20 63 67  userUid);.    cg
2fe0: 69 5f 72 65 70 6c 61 63 65 5f 70 61 72 61 6d 65  i_replace_parame
2ff0: 74 65 72 28 63 6f 6f 6b 69 65 2c 20 4e 55 4c 4c  ter(cookie, NULL
3000: 29 3b 0a 20 20 20 20 63 67 69 5f 72 65 70 6c 61  );.    cgi_repla
3010: 63 65 5f 70 61 72 61 6d 65 74 65 72 28 22 61 6e  ce_parameter("an
3020: 6f 6e 22 2c 20 4e 55 4c 4c 29 3b 0a 20 20 7d 0a  on", NULL);.  }.
3030: 7d 0a 0a 2f 2a 0a 2a 2a 20 52 65 74 75 72 6e 20  }../*.** Return 
3040: 74 72 75 65 20 69 66 20 74 68 65 20 70 72 65 66  true if the pref
3050: 69 78 20 6f 66 20 7a 53 74 72 20 6d 61 74 63 68  ix of zStr match
3060: 65 73 20 7a 50 61 74 74 65 72 6e 2e 20 20 52 65  es zPattern.  Re
3070: 74 75 72 6e 20 66 61 6c 73 65 20 69 66 0a 2a 2a  turn false if.**
3080: 20 74 68 65 79 20 61 72 65 20 64 69 66 66 65 72   they are differ
3090: 65 6e 74 2e 0a 2a 2a 0a 2a 2a 20 41 20 6c 6f 77  ent..**.** A low
30a0: 65 72 63 61 73 65 20 63 68 61 72 61 63 74 65 72  ercase character
30b0: 20 69 6e 20 7a 50 61 74 74 65 72 6e 20 77 69 6c   in zPattern wil
30c0: 6c 20 6d 61 74 63 68 20 65 69 74 68 65 72 20 75  l match either u
30d0: 70 70 65 72 20 6f 72 20 6c 6f 77 65 72 0a 2a 2a  pper or lower.**
30e0: 20 63 61 73 65 20 69 6e 20 7a 53 74 72 2e 20 20   case in zStr.  
30f0: 42 75 74 20 61 6e 20 75 70 70 65 72 63 61 73 65  But an uppercase
3100: 20 69 6e 20 7a 50 61 74 74 65 72 6e 20 77 69 6c   in zPattern wil
3110: 6c 20 6f 6e 6c 79 20 6d 61 74 63 68 20 61 6e 0a  l only match an.
3120: 2a 2a 20 75 70 70 65 72 63 61 73 65 20 69 6e 20  ** uppercase in 
3130: 7a 53 74 72 2e 0a 2a 2f 0a 73 74 61 74 69 63 20  zStr..*/.static 
3140: 69 6e 74 20 70 72 65 66 69 78 5f 6d 61 74 63 68  int prefix_match
3150: 28 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 50 61  (const char *zPa
3160: 74 74 65 72 6e 2c 20 63 6f 6e 73 74 20 63 68 61  ttern, const cha
3170: 72 20 2a 7a 53 74 72 29 7b 0a 20 20 69 6e 74 20  r *zStr){.  int 
3180: 69 3b 0a 20 20 63 68 61 72 20 63 3b 0a 20 20 66  i;.  char c;.  f
3190: 6f 72 28 69 3d 30 3b 20 28 63 20 3d 20 7a 50 61  or(i=0; (c = zPa
31a0: 74 74 65 72 6e 5b 69 5d 29 21 3d 30 3b 20 69 2b  ttern[i])!=0; i+
31b0: 2b 29 7b 0a 20 20 20 20 69 66 28 20 7a 53 74 72  +){.    if( zStr
31c0: 5b 69 5d 21 3d 63 20 26 26 20 66 6f 73 73 69 6c  [i]!=c && fossil
31d0: 5f 74 6f 6c 6f 77 65 72 28 7a 53 74 72 5b 69 5d  _tolower(zStr[i]
31e0: 29 21 3d 63 20 29 20 72 65 74 75 72 6e 20 30 3b  )!=c ) return 0;
31f0: 0a 20 20 7d 0a 20 20 72 65 74 75 72 6e 20 31 3b  .  }.  return 1;
3200: 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 4c 6f 6f 6b 20 61  .}../*.** Look a
3210: 74 20 74 68 65 20 48 54 54 50 5f 55 53 45 52 5f  t the HTTP_USER_
3220: 41 47 45 4e 54 20 70 61 72 61 6d 65 74 65 72 20  AGENT parameter 
3230: 61 6e 64 20 74 72 79 20 74 6f 20 64 65 74 65 72  and try to deter
3240: 6d 69 6e 65 20 69 66 20 74 68 65 20 75 73 65 72  mine if the user
3250: 20 61 67 65 6e 74 0a 2a 2a 20 69 73 20 61 20 6d   agent.** is a m
3260: 61 6e 75 61 6c 6c 79 20 6f 70 65 72 61 74 65 64  anually operated
3270: 20 62 72 6f 77 73 65 72 20 6f 72 20 61 20 62 6f   browser or a bo
3280: 74 2e 20 20 57 68 65 6e 20 69 6e 20 64 6f 75 62  t.  When in doub
3290: 74 2c 20 61 73 73 75 6d 65 20 61 20 62 6f 74 2e  t, assume a bot.
32a0: 0a 2a 2a 20 52 65 74 75 72 6e 20 74 72 75 65 20  .** Return true 
32b0: 69 66 20 77 65 20 62 65 6c 69 65 76 65 20 74 68  if we believe th
32c0: 65 20 61 67 65 6e 74 20 69 73 20 61 20 72 65 61  e agent is a rea
32d0: 6c 20 70 65 72 73 6f 6e 2e 0a 2a 2f 0a 73 74 61  l person..*/.sta
32e0: 74 69 63 20 69 6e 74 20 69 73 48 75 6d 61 6e 28  tic int isHuman(
32f0: 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 41 67 65  const char *zAge
3300: 6e 74 29 7b 0a 20 20 69 6e 74 20 69 3b 0a 20 20  nt){.  int i;.  
3310: 69 66 28 20 7a 41 67 65 6e 74 3d 3d 30 20 29 20  if( zAgent==0 ) 
3320: 72 65 74 75 72 6e 20 30 3b 20 20 2f 2a 20 49 66  return 0;  /* If
3330: 20 6e 6f 20 55 73 65 72 41 67 65 6e 74 2c 20 74   no UserAgent, t
3340: 68 65 6e 20 70 72 6f 62 61 62 6c 79 20 61 20 62  hen probably a b
3350: 6f 74 20 2a 2f 0a 20 20 66 6f 72 28 69 3d 30 3b  ot */.  for(i=0;
3360: 20 7a 41 67 65 6e 74 5b 69 5d 3b 20 69 2b 2b 29   zAgent[i]; i++)
3370: 7b 0a 20 20 20 20 69 66 28 20 70 72 65 66 69 78  {.    if( prefix
3380: 5f 6d 61 74 63 68 28 22 62 6f 74 22 2c 20 7a 41  _match("bot", zA
3390: 67 65 6e 74 2b 69 29 20 29 20 72 65 74 75 72 6e  gent+i) ) return
33a0: 20 30 3b 0a 20 20 20 20 69 66 28 20 70 72 65 66   0;.    if( pref
33b0: 69 78 5f 6d 61 74 63 68 28 22 73 70 69 64 65 72  ix_match("spider
33c0: 22 2c 20 7a 41 67 65 6e 74 2b 69 29 20 29 20 72  ", zAgent+i) ) r
33d0: 65 74 75 72 6e 20 30 3b 0a 20 20 20 20 69 66 28  eturn 0;.    if(
33e0: 20 70 72 65 66 69 78 5f 6d 61 74 63 68 28 22 63   prefix_match("c
33f0: 72 61 77 6c 22 2c 20 7a 41 67 65 6e 74 2b 69 29  rawl", zAgent+i)
3400: 20 29 20 72 65 74 75 72 6e 20 30 3b 0a 20 20 20   ) return 0;.   
3410: 20 2f 2a 20 49 66 20 61 20 55 52 49 20 61 70 70   /* If a URI app
3420: 65 61 72 73 20 69 6e 20 74 68 65 20 55 73 65 72  ears in the User
3430: 2d 41 67 65 6e 74 2c 20 69 74 20 69 73 20 70 72  -Agent, it is pr
3440: 6f 62 61 62 6c 79 20 61 20 62 6f 74 20 2a 2f 0a  obably a bot */.
3450: 20 20 20 20 69 66 28 20 73 74 72 6e 63 6d 70 28      if( strncmp(
3460: 22 68 74 74 70 22 2c 20 7a 41 67 65 6e 74 2b 69  "http", zAgent+i
3470: 2c 34 29 3d 3d 30 20 29 20 72 65 74 75 72 6e 20  ,4)==0 ) return 
3480: 30 3b 0a 20 20 7d 0a 20 20 69 66 28 20 73 74 72  0;.  }.  if( str
3490: 6e 63 6d 70 28 7a 41 67 65 6e 74 2c 20 22 4d 6f  ncmp(zAgent, "Mo
34a0: 7a 69 6c 6c 61 2f 22 2c 20 38 29 3d 3d 30 20 29  zilla/", 8)==0 )
34b0: 7b 0a 20 20 20 20 69 66 28 20 61 74 6f 69 28 26  {.    if( atoi(&
34c0: 7a 41 67 65 6e 74 5b 38 5d 29 3c 34 20 29 20 72  zAgent[8])<4 ) r
34d0: 65 74 75 72 6e 20 30 3b 20 20 2f 2a 20 4d 61 6e  eturn 0;  /* Man
34e0: 79 20 62 6f 74 73 20 61 64 76 65 72 74 69 73 65  y bots advertise
34f0: 20 61 73 20 4d 6f 7a 69 6c 6c 61 2f 33 20 2a 2f   as Mozilla/3 */
3500: 0a 0a 20 20 20 20 2f 2a 20 32 30 31 36 2d 30 35  ..    /* 2016-05
3510: 2d 33 30 3a 20 20 41 20 70 65 72 6e 69 63 69 6f  -30:  A pernicio
3520: 75 73 20 73 70 69 64 65 72 20 74 68 61 74 20 6c  us spider that l
3530: 69 6b 65 73 20 74 6f 20 77 61 6c 6b 20 46 6f 73  ikes to walk Fos
3540: 73 69 6c 20 74 69 6d 65 6c 69 6e 65 73 20 68 61  sil timelines ha
3550: 73 0a 20 20 20 20 2a 2a 20 62 65 65 6e 20 64 65  s.    ** been de
3560: 74 65 63 74 65 64 20 6f 6e 20 74 68 65 20 53 51  tected on the SQ
3570: 4c 69 74 65 20 77 65 62 73 69 74 65 2e 20 20 54  Lite website.  T
3580: 68 65 20 73 70 69 64 65 72 20 63 68 61 6e 67 65  he spider change
3590: 73 20 69 74 73 20 75 73 65 72 2d 61 67 65 6e 74  s its user-agent
35a0: 0a 20 20 20 20 2a 2a 20 73 74 72 69 6e 67 20 66  .    ** string f
35b0: 72 65 71 75 65 6e 74 6c 79 2c 20 62 75 74 20 69  requently, but i
35c0: 74 20 61 6c 77 61 79 73 20 73 65 65 6d 73 20 74  t always seems t
35d0: 6f 20 69 6e 63 6c 75 64 65 20 74 68 65 20 66 6f  o include the fo
35e0: 6c 6c 6f 77 69 6e 67 20 74 65 78 74 3a 0a 20 20  llowing text:.  
35f0: 20 20 2a 2f 0a 20 20 20 20 69 66 28 20 73 71 6c    */.    if( sql
3600: 69 74 65 33 5f 73 74 72 67 6c 6f 62 28 22 2a 53  ite3_strglob("*S
3610: 61 66 61 72 69 2f 35 33 37 2e 33 36 4d 6f 7a 69  afari/537.36Mozi
3620: 6c 6c 61 2f 35 2e 30 2a 22 2c 20 7a 41 67 65 6e  lla/5.0*", zAgen
3630: 74 29 3d 3d 30 20 29 20 72 65 74 75 72 6e 20 30  t)==0 ) return 0
3640: 3b 0a 0a 20 20 20 20 69 66 28 20 73 71 6c 69 74  ;..    if( sqlit
3650: 65 33 5f 73 74 72 67 6c 6f 62 28 22 2a 46 69 72  e3_strglob("*Fir
3660: 65 66 6f 78 2f 5b 31 2d 39 5d 2a 22 2c 20 7a 41  efox/[1-9]*", zA
3670: 67 65 6e 74 29 3d 3d 30 20 29 20 72 65 74 75 72  gent)==0 ) retur
3680: 6e 20 31 3b 0a 20 20 20 20 69 66 28 20 73 71 6c  n 1;.    if( sql
3690: 69 74 65 33 5f 73 74 72 67 6c 6f 62 28 22 2a 43  ite3_strglob("*C
36a0: 68 72 6f 6d 65 2f 5b 31 2d 39 5d 2a 22 2c 20 7a  hrome/[1-9]*", z
36b0: 41 67 65 6e 74 29 3d 3d 30 20 29 20 72 65 74 75  Agent)==0 ) retu
36c0: 72 6e 20 31 3b 0a 20 20 20 20 69 66 28 20 73 71  rn 1;.    if( sq
36d0: 6c 69 74 65 33 5f 73 74 72 67 6c 6f 62 28 22 2a  lite3_strglob("*
36e0: 28 63 6f 6d 70 61 74 69 62 6c 65 3b 3f 4d 53 49  (compatible;?MSI
36f0: 45 3f 5b 31 37 38 39 5d 2a 22 2c 20 7a 41 67 65  E?[1789]*", zAge
3700: 6e 74 29 3d 3d 30 20 29 20 72 65 74 75 72 6e 20  nt)==0 ) return 
3710: 31 3b 0a 20 20 20 20 69 66 28 20 73 71 6c 69 74  1;.    if( sqlit
3720: 65 33 5f 73 74 72 67 6c 6f 62 28 22 2a 54 72 69  e3_strglob("*Tri
3730: 64 65 6e 74 2f 5b 31 2d 39 5d 2a 3b 3f 72 76 3a  dent/[1-9]*;?rv:
3740: 5b 31 2d 39 5d 2a 22 2c 20 7a 41 67 65 6e 74 29  [1-9]*", zAgent)
3750: 3d 3d 30 20 29 20 72 65 74 75 72 6e 20 31 3b 20  ==0 ) return 1; 
3760: 2f 2a 20 49 45 31 31 2b 20 2a 2f 0a 20 20 20 20  /* IE11+ */.    
3770: 69 66 28 20 73 71 6c 69 74 65 33 5f 73 74 72 67  if( sqlite3_strg
3780: 6c 6f 62 28 22 2a 41 70 70 6c 65 57 65 62 4b 69  lob("*AppleWebKi
3790: 74 2f 5b 31 2d 39 5d 2a 28 4b 48 54 4d 4c 2a 22  t/[1-9]*(KHTML*"
37a0: 2c 20 7a 41 67 65 6e 74 29 3d 3d 30 20 29 20 72  , zAgent)==0 ) r
37b0: 65 74 75 72 6e 20 31 3b 0a 20 20 20 20 72 65 74  eturn 1;.    ret
37c0: 75 72 6e 20 30 3b 0a 20 20 7d 0a 20 20 69 66 28  urn 0;.  }.  if(
37d0: 20 73 74 72 6e 63 6d 70 28 7a 41 67 65 6e 74 2c   strncmp(zAgent,
37e0: 20 22 4f 70 65 72 61 2f 22 2c 20 36 29 3d 3d 30   "Opera/", 6)==0
37f0: 20 29 20 72 65 74 75 72 6e 20 31 3b 0a 20 20 69   ) return 1;.  i
3800: 66 28 20 73 74 72 6e 63 6d 70 28 7a 41 67 65 6e  f( strncmp(zAgen
3810: 74 2c 20 22 53 61 66 61 72 69 2f 22 2c 20 37 29  t, "Safari/", 7)
3820: 3d 3d 30 20 29 20 72 65 74 75 72 6e 20 31 3b 0a  ==0 ) return 1;.
3830: 20 20 69 66 28 20 73 74 72 6e 63 6d 70 28 7a 41    if( strncmp(zA
3840: 67 65 6e 74 2c 20 22 4c 79 6e 78 2f 22 2c 20 35  gent, "Lynx/", 5
3850: 29 3d 3d 30 20 29 20 72 65 74 75 72 6e 20 31 3b  )==0 ) return 1;
3860: 0a 20 20 69 66 28 20 73 74 72 6e 63 6d 70 28 7a  .  if( strncmp(z
3870: 41 67 65 6e 74 2c 20 22 4e 65 74 53 75 72 66 2f  Agent, "NetSurf/
3880: 22 2c 20 38 29 3d 3d 30 20 29 20 72 65 74 75 72  ", 8)==0 ) retur
3890: 6e 20 31 3b 0a 20 20 72 65 74 75 72 6e 20 30 3b  n 1;.  return 0;
38a0: 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 43 4f 4d 4d 41 4e  .}../*.** COMMAN
38b0: 44 3a 20 74 65 73 74 2d 69 73 68 75 6d 61 6e 0a  D: test-ishuman.
38c0: 2a 2a 0a 2a 2a 20 52 65 61 64 20 6c 69 6e 65 73  **.** Read lines
38d0: 20 6f 66 20 74 65 78 74 20 66 72 6f 6d 20 73 74   of text from st
38e0: 61 6e 64 61 72 64 20 69 6e 70 75 74 2e 20 20 49  andard input.  I
38f0: 6e 74 65 72 70 72 65 74 20 65 61 63 68 20 6c 69  nterpret each li
3900: 6e 65 20 6f 66 20 74 65 78 74 0a 2a 2a 20 61 73  ne of text.** as
3910: 20 61 20 55 73 65 72 2d 41 67 65 6e 74 20 73 74   a User-Agent st
3920: 72 69 6e 67 20 66 72 6f 6d 20 61 6e 20 48 54 54  ring from an HTT
3930: 50 20 68 65 61 64 65 72 2e 20 20 4c 61 62 65 6c  P header.  Label
3940: 20 65 61 63 68 20 6c 69 6e 65 20 61 73 20 48 55   each line as HU
3950: 4d 41 4e 0a 2a 2a 20 6f 72 20 52 4f 42 4f 54 2e  MAN.** or ROBOT.
3960: 0a 2a 2f 0a 76 6f 69 64 20 74 65 73 74 5f 69 73  .*/.void test_is
3970: 68 75 6d 61 6e 28 76 6f 69 64 29 7b 0a 20 20 63  human(void){.  c
3980: 68 61 72 20 7a 4c 69 6e 65 5b 33 30 30 30 5d 3b  har zLine[3000];
3990: 0a 20 20 77 68 69 6c 65 28 20 66 67 65 74 73 28  .  while( fgets(
39a0: 7a 4c 69 6e 65 2c 20 73 69 7a 65 6f 66 28 7a 4c  zLine, sizeof(zL
39b0: 69 6e 65 29 2c 20 73 74 64 69 6e 29 20 29 7b 0a  ine), stdin) ){.
39c0: 20 20 20 20 66 6f 73 73 69 6c 5f 70 72 69 6e 74      fossil_print
39d0: 28 22 25 73 20 25 73 22 2c 20 69 73 48 75 6d 61  ("%s %s", isHuma
39e0: 6e 28 7a 4c 69 6e 65 29 20 3f 20 22 48 55 4d 41  n(zLine) ? "HUMA
39f0: 4e 22 20 3a 20 22 52 4f 42 4f 54 22 2c 20 7a 4c  N" : "ROBOT", zL
3a00: 69 6e 65 29 3b 0a 20 20 7d 0a 7d 0a 0a 2f 2a 0a  ine);.  }.}../*.
3a10: 2a 2a 20 53 51 4c 20 66 75 6e 63 74 69 6f 6e 20  ** SQL function 
3a20: 66 6f 72 20 63 6f 6e 73 74 61 6e 74 20 74 69 6d  for constant tim
3a30: 65 20 63 6f 6d 70 61 72 69 73 6f 6e 20 6f 66 20  e comparison of 
3a40: 74 77 6f 20 76 61 6c 75 65 73 2e 0a 2a 2a 20 53  two values..** S
3a50: 65 74 73 20 72 65 73 75 6c 74 20 74 6f 20 30 20  ets result to 0 
3a60: 69 66 20 74 77 6f 20 76 61 6c 75 65 73 20 61 72  if two values ar
3a70: 65 20 65 71 75 61 6c 2e 0a 2a 2f 0a 73 74 61 74  e equal..*/.stat
3a80: 69 63 20 76 6f 69 64 20 63 6f 6e 73 74 61 6e 74  ic void constant
3a90: 5f 74 69 6d 65 5f 63 6d 70 5f 66 75 6e 63 74 69  _time_cmp_functi
3aa0: 6f 6e 28 0a 20 73 71 6c 69 74 65 33 5f 63 6f 6e  on(. sqlite3_con
3ab0: 74 65 78 74 20 2a 63 6f 6e 74 65 78 74 2c 0a 20  text *context,. 
3ac0: 69 6e 74 20 61 72 67 63 2c 0a 20 73 71 6c 69 74  int argc,. sqlit
3ad0: 65 33 5f 76 61 6c 75 65 20 2a 2a 61 72 67 76 0a  e3_value **argv.
3ae0: 29 7b 0a 20 20 63 6f 6e 73 74 20 75 6e 73 69 67  ){.  const unsig
3af0: 6e 65 64 20 63 68 61 72 20 2a 62 75 66 31 2c 20  ned char *buf1, 
3b00: 2a 62 75 66 32 3b 0a 20 20 69 6e 74 20 6c 65 6e  *buf2;.  int len
3b10: 2c 20 69 3b 0a 20 20 75 6e 73 69 67 6e 65 64 20  , i;.  unsigned 
3b20: 63 68 61 72 20 72 63 20 3d 20 30 3b 0a 0a 20 20  char rc = 0;..  
3b30: 61 73 73 65 72 74 28 20 61 72 67 63 3d 3d 32 20  assert( argc==2 
3b40: 29 3b 0a 20 20 6c 65 6e 20 3d 20 73 71 6c 69 74  );.  len = sqlit
3b50: 65 33 5f 76 61 6c 75 65 5f 62 79 74 65 73 28 61  e3_value_bytes(a
3b60: 72 67 76 5b 30 5d 29 3b 0a 20 20 69 66 28 20 6c  rgv[0]);.  if( l
3b70: 65 6e 3d 3d 30 20 7c 7c 20 6c 65 6e 21 3d 73 71  en==0 || len!=sq
3b80: 6c 69 74 65 33 5f 76 61 6c 75 65 5f 62 79 74 65  lite3_value_byte
3b90: 73 28 61 72 67 76 5b 31 5d 29 20 29 7b 0a 20 20  s(argv[1]) ){.  
3ba0: 20 20 72 63 20 3d 20 31 3b 0a 20 20 7d 65 6c 73    rc = 1;.  }els
3bb0: 65 7b 0a 20 20 20 20 62 75 66 31 20 3d 20 73 71  e{.    buf1 = sq
3bc0: 6c 69 74 65 33 5f 76 61 6c 75 65 5f 74 65 78 74  lite3_value_text
3bd0: 28 61 72 67 76 5b 30 5d 29 3b 0a 20 20 20 20 62  (argv[0]);.    b
3be0: 75 66 32 20 3d 20 73 71 6c 69 74 65 33 5f 76 61  uf2 = sqlite3_va
3bf0: 6c 75 65 5f 74 65 78 74 28 61 72 67 76 5b 31 5d  lue_text(argv[1]
3c00: 29 3b 0a 20 20 20 20 66 6f 72 28 20 69 3d 30 3b  );.    for( i=0;
3c10: 20 69 3c 6c 65 6e 3b 20 69 2b 2b 20 29 7b 0a 20   i<len; i++ ){. 
3c20: 20 20 20 20 20 72 63 20 3d 20 72 63 20 7c 20 28       rc = rc | (
3c30: 62 75 66 31 5b 69 5d 20 5e 20 62 75 66 32 5b 69  buf1[i] ^ buf2[i
3c40: 5d 29 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20  ]);.    }.  }.  
3c50: 73 71 6c 69 74 65 33 5f 72 65 73 75 6c 74 5f 69  sqlite3_result_i
3c60: 6e 74 28 63 6f 6e 74 65 78 74 2c 20 72 63 29 3b  nt(context, rc);
3c70: 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 52 65 74 75 72 6e  .}../*.** Return
3c80: 20 74 72 75 65 20 69 66 20 74 68 65 20 63 75 72   true if the cur
3c90: 72 65 6e 74 20 70 61 67 65 20 77 61 73 20 72 65  rent page was re
3ca0: 61 63 68 65 64 20 62 79 20 61 20 72 65 64 69 72  ached by a redir
3cb0: 65 63 74 20 66 72 6f 6d 20 74 68 65 20 2f 6c 6f  ect from the /lo
3cc0: 67 69 6e 0a 2a 2a 20 70 61 67 65 2e 0a 2a 2f 0a  gin.** page..*/.
3cd0: 69 6e 74 20 72 65 66 65 72 72 65 64 5f 66 72 6f  int referred_fro
3ce0: 6d 5f 6c 6f 67 69 6e 28 76 6f 69 64 29 7b 0a 20  m_login(void){. 
3cf0: 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 52 65   const char *zRe
3d00: 66 65 72 65 72 20 3d 20 50 28 22 48 54 54 50 5f  ferer = P("HTTP_
3d10: 52 45 46 45 52 45 52 22 29 3b 0a 20 20 63 68 61  REFERER");.  cha
3d20: 72 20 2a 7a 50 61 74 74 65 72 6e 3b 0a 20 20 69  r *zPattern;.  i
3d30: 6e 74 20 72 63 3b 0a 20 20 69 66 28 20 7a 52 65  nt rc;.  if( zRe
3d40: 66 65 72 65 72 3d 3d 30 20 29 20 72 65 74 75 72  ferer==0 ) retur
3d50: 6e 20 30 3b 0a 20 20 7a 50 61 74 74 65 72 6e 20  n 0;.  zPattern 
3d60: 3d 20 6d 70 72 69 6e 74 66 28 22 25 73 2f 6c 6f  = mprintf("%s/lo
3d70: 67 69 6e 2a 22 2c 20 67 2e 7a 42 61 73 65 55 52  gin*", g.zBaseUR
3d80: 4c 29 3b 0a 20 20 72 63 20 3d 20 73 71 6c 69 74  L);.  rc = sqlit
3d90: 65 33 5f 73 74 72 67 6c 6f 62 28 7a 50 61 74 74  e3_strglob(zPatt
3da0: 65 72 6e 2c 20 7a 52 65 66 65 72 65 72 29 3d 3d  ern, zReferer)==
3db0: 30 3b 0a 20 20 66 6f 73 73 69 6c 5f 66 72 65 65  0;.  fossil_free
3dc0: 28 7a 50 61 74 74 65 72 6e 29 3b 0a 20 20 72 65  (zPattern);.  re
3dd0: 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 0a 2a  turn rc;.}../*.*
3de0: 2a 20 52 65 74 75 72 6e 20 54 52 55 45 20 69 66  * Return TRUE if
3df0: 20 73 65 6c 66 2d 72 65 67 69 73 74 72 61 74 69   self-registrati
3e00: 6f 6e 20 69 73 20 61 76 61 69 6c 61 62 6c 65 2e  on is available.
3e10: 20 20 49 66 20 74 68 65 20 7a 4e 65 65 64 65 64    If the zNeeded
3e20: 0a 2a 2a 20 61 72 67 75 6d 65 6e 74 20 69 73 20  .** argument is 
3e30: 6e 6f 74 20 4e 55 4c 4c 2c 20 74 68 65 6e 20 6f  not NULL, then o
3e40: 6e 6c 79 20 72 65 74 75 72 6e 20 74 72 75 65 20  nly return true 
3e50: 69 66 20 73 65 6c 66 2d 72 65 67 69 73 74 72 61  if self-registra
3e60: 74 69 6f 6e 20 69 73 0a 2a 2a 20 61 76 61 69 6c  tion is.** avail
3e70: 61 62 6c 65 20 61 6e 64 20 61 6e 79 20 6f 66 20  able and any of 
3e80: 74 68 65 20 63 61 70 61 62 69 6c 69 74 69 65 73  the capabilities
3e90: 20 6e 61 6d 65 64 20 69 6e 20 7a 4e 65 65 64 65   named in zNeede
3ea0: 64 20 61 72 65 20 61 76 61 69 6c 61 62 6c 65 0a  d are available.
3eb0: 2a 2a 20 74 6f 20 73 65 6c 66 2d 72 65 67 69 73  ** to self-regis
3ec0: 74 65 72 65 64 20 75 73 65 72 73 2e 0a 2a 2f 0a  tered users..*/.
3ed0: 69 6e 74 20 6c 6f 67 69 6e 5f 73 65 6c 66 5f 72  int login_self_r
3ee0: 65 67 69 73 74 65 72 5f 61 76 61 69 6c 61 62 6c  egister_availabl
3ef0: 65 28 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 4e  e(const char *zN
3f00: 65 65 64 65 64 29 7b 0a 20 20 43 61 70 61 62 69  eeded){.  Capabi
3f10: 6c 69 74 79 53 74 72 69 6e 67 20 2a 70 43 61 70  lityString *pCap
3f20: 3b 0a 20 20 69 6e 74 20 72 63 3b 0a 20 20 69 66  ;.  int rc;.  if
3f30: 28 20 21 64 62 5f 67 65 74 5f 62 6f 6f 6c 65 61  ( !db_get_boolea
3f40: 6e 28 22 73 65 6c 66 2d 72 65 67 69 73 74 65 72  n("self-register
3f50: 22 2c 30 29 20 29 20 72 65 74 75 72 6e 20 30 3b  ",0) ) return 0;
3f60: 0a 20 20 69 66 28 20 7a 4e 65 65 64 65 64 3d 3d  .  if( zNeeded==
3f70: 30 20 29 20 72 65 74 75 72 6e 20 31 3b 0a 20 20  0 ) return 1;.  
3f80: 70 43 61 70 20 3d 20 63 61 70 61 62 69 6c 69 74  pCap = capabilit
3f90: 79 5f 61 64 64 28 30 2c 20 64 62 5f 67 65 74 28  y_add(0, db_get(
3fa0: 22 64 65 66 61 75 6c 74 2d 70 65 72 6d 73 22 2c  "default-perms",
3fb0: 22 22 29 29 3b 0a 20 20 63 61 70 61 62 69 6c 69  ""));.  capabili
3fc0: 74 79 5f 65 78 70 61 6e 64 28 70 43 61 70 29 3b  ty_expand(pCap);
3fd0: 0a 20 20 72 63 20 3d 20 63 61 70 61 62 69 6c 69  .  rc = capabili
3fe0: 74 79 5f 68 61 73 5f 61 6e 79 28 70 43 61 70 2c  ty_has_any(pCap,
3ff0: 20 7a 4e 65 65 64 65 64 29 3b 0a 20 20 63 61 70   zNeeded);.  cap
4000: 61 62 69 6c 69 74 79 5f 66 72 65 65 28 70 43 61  ability_free(pCa
4010: 70 29 3b 0a 20 20 72 65 74 75 72 6e 20 72 63 3b  p);.  return rc;
4020: 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54 68 65 72 65 20  .}../*.** There 
4030: 75 73 65 64 20 74 6f 20 62 65 20 61 20 70 61 67  used to be a pag
4040: 65 20 6e 61 6d 65 64 20 22 6d 79 22 20 74 68 61  e named "my" tha
4050: 74 20 77 61 73 20 64 65 73 69 67 6e 65 64 20 74  t was designed t
4060: 6f 20 73 68 6f 77 20 69 6e 66 6f 72 6d 61 74 69  o show informati
4070: 6f 6e 0a 2a 2a 20 61 62 6f 75 74 20 61 20 73 70  on.** about a sp
4080: 65 63 69 66 69 63 20 75 73 65 72 2e 20 20 54 68  ecific user.  Th
4090: 65 20 22 6d 79 22 20 70 61 67 65 20 77 61 73 20  e "my" page was 
40a0: 6c 69 6e 6b 65 64 20 66 72 6f 6d 20 74 68 65 20  linked from the 
40b0: 22 4c 6f 67 67 65 64 20 69 6e 20 61 73 20 55 53  "Logged in as US
40c0: 45 52 22 0a 2a 2a 20 6c 69 6e 65 20 6f 6e 20 74  ER".** line on t
40d0: 68 65 20 74 69 74 6c 65 20 62 61 72 2e 20 20 54  he title bar.  T
40e0: 68 65 20 22 6d 79 22 20 70 61 67 65 20 77 61 73  he "my" page was
40f0: 20 6e 65 76 65 72 20 63 6f 6d 70 6c 65 74 65 64   never completed
4100: 20 73 6f 20 69 74 20 69 73 20 6e 6f 77 0a 2a 2a   so it is now.**
4110: 20 72 65 6d 6f 76 65 64 2e 20 20 55 73 65 20 74   removed.  Use t
4120: 68 69 73 20 70 61 67 65 20 61 73 20 61 20 70 6c  his page as a pl
4130: 61 63 65 68 6f 6c 64 65 72 20 69 6e 20 6f 6c 64  aceholder in old
4140: 65 72 20 69 6e 73 74 61 6c 6c 61 74 69 6f 6e 73  er installations
4150: 2e 0a 2a 2a 0a 2a 2a 20 57 45 42 50 41 47 45 3a  ..**.** WEBPAGE:
4160: 20 6c 6f 67 69 6e 0a 2a 2a 20 57 45 42 50 41 47   login.** WEBPAG
4170: 45 3a 20 6c 6f 67 6f 75 74 0a 2a 2a 20 57 45 42  E: logout.** WEB
4180: 50 41 47 45 3a 20 6d 79 0a 2a 2a 0a 2a 2a 20 54  PAGE: my.**.** T
4190: 68 65 20 6c 6f 67 69 6e 2f 6c 6f 67 6f 75 74 20  he login/logout 
41a0: 70 61 67 65 2e 20 20 50 61 72 61 6d 65 74 65 72  page.  Parameter
41b0: 73 3a 0a 2a 2a 0a 2a 2a 20 20 20 20 67 3d 55 52  s:.**.**    g=UR
41c0: 4c 20 20 20 20 20 20 20 20 20 20 20 20 20 4a 75  L             Ju
41d0: 6d 70 20 62 61 63 6b 20 74 6f 20 74 68 69 73 20  mp back to this 
41e0: 55 52 4c 20 61 66 74 65 72 20 6c 6f 67 69 6e 20  URL after login 
41f0: 63 6f 6d 70 6c 65 74 65 73 0a 2a 2a 20 20 20 20  completes.**    
4200: 61 6e 6f 6e 20 20 20 20 20 20 20 20 20 20 20 20  anon            
4210: 20 20 54 68 65 20 67 3d 55 52 4c 20 69 73 20 6e    The g=URL is n
4220: 6f 74 20 61 63 63 65 73 73 69 62 6c 65 20 62 79  ot accessible by
4230: 20 22 6e 6f 62 6f 64 79 22 20 62 75 74 20 69 73   "nobody" but is
4240: 0a 2a 2a 20 20 20 20 20 20 20 20 20 20 20 20 20  .**             
4250: 20 20 20 20 20 20 20 20 20 61 63 63 65 73 73 69           accessi
4260: 62 6c 65 20 62 79 20 22 61 6e 6f 6e 79 6d 6f 75  ble by "anonymou
4270: 73 22 0a 2a 2f 0a 76 6f 69 64 20 6c 6f 67 69 6e  s".*/.void login
4280: 5f 70 61 67 65 28 76 6f 69 64 29 7b 0a 20 20 63  _page(void){.  c
4290: 6f 6e 73 74 20 63 68 61 72 20 2a 7a 55 73 65 72  onst char *zUser
42a0: 6e 61 6d 65 2c 20 2a 7a 50 61 73 73 77 64 3b 0a  name, *zPasswd;.
42b0: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 4e    const char *zN
42c0: 65 77 31 2c 20 2a 7a 4e 65 77 32 3b 0a 20 20 63  ew1, *zNew2;.  c
42d0: 6f 6e 73 74 20 63 68 61 72 20 2a 7a 41 6e 6f 6e  onst char *zAnon
42e0: 50 77 20 3d 20 30 3b 0a 20 20 63 6f 6e 73 74 20  Pw = 0;.  const 
42f0: 63 68 61 72 20 2a 7a 47 6f 74 6f 20 3d 20 50 28  char *zGoto = P(
4300: 22 67 22 29 3b 0a 20 20 69 6e 74 20 61 6e 6f 6e  "g");.  int anon
4310: 46 6c 61 67 3b 20 20 20 20 20 20 20 20 20 20 20  Flag;           
4320: 20 20 20 20 20 2f 2a 20 4c 6f 67 69 6e 20 61 73       /* Login as
4330: 20 22 61 6e 6f 6e 79 6d 6f 75 73 22 20 77 6f 75   "anonymous" wou
4340: 6c 64 20 62 65 20 75 73 65 66 75 6c 20 2a 2f 0a  ld be useful */.
4350: 20 20 63 68 61 72 20 2a 7a 45 72 72 4d 73 67 20    char *zErrMsg 
4360: 3d 20 22 22 3b 0a 20 20 69 6e 74 20 75 69 64 3b  = "";.  int uid;
4370: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4380: 20 20 20 20 20 2f 2a 20 55 73 65 72 20 69 64 20       /* User id 
4390: 6c 6f 67 67 65 64 20 69 6e 20 75 73 65 72 20 2a  logged in user *
43a0: 2f 0a 20 20 63 68 61 72 20 2a 7a 53 68 61 31 50  /.  char *zSha1P
43b0: 77 3b 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20  w;.  const char 
43c0: 2a 7a 49 70 41 64 64 72 3b 20 20 20 20 20 20 20  *zIpAddr;       
43d0: 20 20 2f 2a 20 49 50 20 61 64 64 72 65 73 73 20    /* IP address 
43e0: 6f 66 20 72 65 71 75 65 73 74 6f 72 20 2a 2f 0a  of requestor */.
43f0: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 52    const char *zR
4400: 65 66 65 72 65 72 3b 0a 20 20 69 6e 74 20 6e 6f  eferer;.  int no
4410: 41 6e 6f 6e 20 3d 20 50 28 22 6e 6f 61 6e 6f 6e  Anon = P("noanon
4420: 22 29 21 3d 30 3b 0a 0a 20 20 6c 6f 67 69 6e 5f  ")!=0;..  login_
4430: 63 68 65 63 6b 5f 63 72 65 64 65 6e 74 69 61 6c  check_credential
4440: 73 28 29 3b 0a 20 20 69 66 28 20 6c 6f 67 69 6e  s();.  if( login
4450: 5f 77 61 6e 74 73 5f 68 74 74 70 73 5f 72 65 64  _wants_https_red
4460: 69 72 65 63 74 28 29 20 29 7b 0a 20 20 20 20 63  irect() ){.    c
4470: 6f 6e 73 74 20 63 68 61 72 20 2a 7a 51 53 20 3d  onst char *zQS =
4480: 20 50 28 22 51 55 45 52 59 5f 53 54 52 49 4e 47   P("QUERY_STRING
4490: 22 29 3b 0a 20 20 20 20 69 66 28 20 50 28 22 72  ");.    if( P("r
44a0: 65 64 69 72 22 29 21 3d 30 20 29 7b 0a 20 20 20  edir")!=0 ){.   
44b0: 20 20 20 73 74 79 6c 65 5f 68 65 61 64 65 72 28     style_header(
44c0: 22 49 6e 73 65 63 75 72 65 20 43 6f 6e 6e 65 63  "Insecure Connec
44d0: 74 69 6f 6e 22 29 3b 0a 20 20 20 20 20 20 40 20  tion");.      @ 
44e0: 3c 68 31 3e 55 6e 61 62 6c 65 20 54 6f 20 45 73  <h1>Unable To Es
44f0: 74 61 62 6c 69 73 68 20 41 6e 20 45 6e 63 72 79  tablish An Encry
4500: 70 74 65 64 20 43 6f 6e 6e 65 63 74 69 6f 6e 3c  pted Connection<
4510: 2f 68 31 3e 0a 20 20 20 20 20 20 40 20 3c 70 3e  /h1>.      @ <p>
4520: 54 68 69 73 20 77 65 62 73 69 74 65 20 72 65 71  This website req
4530: 75 69 72 65 73 20 74 68 61 74 20 6c 6f 67 69 6e  uires that login
4540: 20 63 72 65 64 65 6e 74 69 61 6c 73 20 62 65 20   credentials be 
4550: 73 65 6e 74 20 6f 76 65 72 0a 20 20 20 20 20 20  sent over.      
4560: 40 20 61 6e 20 65 6e 63 72 79 70 74 65 64 20 63  @ an encrypted c
4570: 6f 6e 6e 65 63 74 69 6f 6e 2e 20 20 54 68 65 20  onnection.  The 
4580: 63 75 72 72 65 6e 74 20 63 6f 6e 6e 65 63 74 69  current connecti
4590: 6f 6e 20 69 73 20 6e 6f 74 20 65 6e 63 72 79 70  on is not encryp
45a0: 74 65 64 0a 20 20 20 20 20 20 40 20 61 63 72 6f  ted.      @ acro
45b0: 73 73 20 74 68 65 20 65 6e 74 69 72 65 20 72 6f  ss the entire ro
45c0: 75 74 65 20 62 65 74 77 65 65 6e 20 79 6f 75 72  ute between your
45d0: 20 62 72 6f 77 73 65 72 20 61 6e 64 20 74 68 65   browser and the
45e0: 20 73 65 72 76 65 72 2e 0a 20 20 20 20 20 20 40   server..      @
45f0: 20 41 6e 20 61 74 74 65 6d 70 74 20 77 61 73 20   An attempt was 
4600: 6d 61 64 65 20 74 6f 20 72 65 64 69 72 65 63 74  made to redirect
4610: 20 74 6f 20 25 68 28 67 2e 7a 48 74 74 70 73 55   to %h(g.zHttpsU
4620: 52 4c 29 20 62 75 74 0a 20 20 20 20 20 20 40 20  RL) but.      @ 
4630: 74 68 65 20 63 6f 6e 6e 65 63 74 69 6f 6e 20 69  the connection i
4640: 73 20 73 74 69 6c 6c 20 69 6e 73 65 63 75 72 65  s still insecure
4650: 20 65 76 65 6e 20 61 66 74 65 72 20 74 68 65 20   even after the 
4660: 72 65 64 69 72 65 63 74 2e 3c 2f 70 3e 0a 20 20  redirect.</p>.  
4670: 20 20 20 20 40 20 3c 70 3e 54 68 69 73 20 69 73      @ <p>This is
4680: 20 70 72 6f 62 61 62 6c 79 20 73 6f 6d 65 20 6b   probably some k
4690: 69 6e 64 20 6f 66 20 63 6f 6e 66 69 67 75 72 61  ind of configura
46a0: 74 69 6f 6e 20 70 72 6f 62 6c 65 6d 2e 20 20 50  tion problem.  P
46b0: 6c 65 61 73 65 0a 20 20 20 20 20 20 40 20 63 6f  lease.      @ co
46c0: 6e 74 61 63 74 20 79 6f 75 72 20 73 79 73 61 64  ntact your sysad
46d0: 6d 69 6e 2e 3c 2f 70 3e 0a 20 20 20 20 20 20 40  min.</p>.      @
46e0: 20 3c 70 3e 53 6f 72 72 79 20 69 74 20 64 69 64   <p>Sorry it did
46f0: 20 6e 6f 74 20 77 6f 72 6b 20 6f 75 74 2e 3c 2f   not work out.</
4700: 70 3e 0a 20 20 20 20 20 20 73 74 79 6c 65 5f 66  p>.      style_f
4710: 6f 6f 74 65 72 28 29 3b 0a 20 20 20 20 20 20 72  ooter();.      r
4720: 65 74 75 72 6e 3b 0a 20 20 20 20 7d 0a 20 20 20  eturn;.    }.   
4730: 20 69 66 28 20 7a 51 53 3d 3d 30 20 29 7b 0a 20   if( zQS==0 ){. 
4740: 20 20 20 20 20 7a 51 53 20 3d 20 22 3f 72 65 64       zQS = "?red
4750: 69 72 3d 31 22 3b 0a 20 20 20 20 7d 65 6c 73 65  ir=1";.    }else
4760: 20 69 66 28 20 7a 51 53 5b 30 5d 21 3d 30 20 29   if( zQS[0]!=0 )
4770: 7b 0a 20 20 20 20 20 20 7a 51 53 20 3d 20 6d 70  {.      zQS = mp
4780: 72 69 6e 74 66 28 22 3f 25 73 26 72 65 64 69 72  rintf("?%s&redir
4790: 3d 31 22 2c 20 7a 51 53 29 3b 0a 20 20 20 20 7d  =1", zQS);.    }
47a0: 0a 20 20 20 20 63 67 69 5f 72 65 64 69 72 65 63  .    cgi_redirec
47b0: 74 66 28 22 25 73 25 54 25 73 22 2c 20 67 2e 7a  tf("%s%T%s", g.z
47c0: 48 74 74 70 73 55 52 4c 2c 20 50 28 22 50 41 54  HttpsURL, P("PAT
47d0: 48 5f 49 4e 46 4f 22 29 2c 20 7a 51 53 29 3b 0a  H_INFO"), zQS);.
47e0: 20 20 20 20 72 65 74 75 72 6e 3b 0a 20 20 7d 0a      return;.  }.
47f0: 20 20 73 71 6c 69 74 65 33 5f 63 72 65 61 74 65    sqlite3_create
4800: 5f 66 75 6e 63 74 69 6f 6e 28 67 2e 64 62 2c 20  _function(g.db, 
4810: 22 63 6f 6e 73 74 61 6e 74 5f 74 69 6d 65 5f 63  "constant_time_c
4820: 6d 70 22 2c 20 32 2c 20 53 51 4c 49 54 45 5f 55  mp", 2, SQLITE_U
4830: 54 46 38 2c 20 30 2c 0a 20 20 20 20 20 20 20 20  TF8, 0,.        
4840: 20 20 20 20 20 20 20 20 20 20 63 6f 6e 73 74 61            consta
4850: 6e 74 5f 74 69 6d 65 5f 63 6d 70 5f 66 75 6e 63  nt_time_cmp_func
4860: 74 69 6f 6e 2c 20 30 2c 20 30 29 3b 0a 20 20 7a  tion, 0, 0);.  z
4870: 55 73 65 72 6e 61 6d 65 20 3d 20 50 28 22 75 22  Username = P("u"
4880: 29 3b 0a 20 20 7a 50 61 73 73 77 64 20 3d 20 50  );.  zPasswd = P
4890: 28 22 70 22 29 3b 0a 20 20 61 6e 6f 6e 46 6c 61  ("p");.  anonFla
48a0: 67 20 3d 20 67 2e 7a 4c 6f 67 69 6e 3d 3d 30 20  g = g.zLogin==0 
48b0: 26 26 20 50 42 28 22 61 6e 6f 6e 22 29 3b 0a 0a  && PB("anon");..
48c0: 20 20 2f 2a 20 48 61 6e 64 6c 65 20 6c 6f 67 2d    /* Handle log-
48d0: 6f 75 74 20 72 65 71 75 65 73 74 73 20 2a 2f 0a  out requests */.
48e0: 20 20 69 66 28 20 50 28 22 6f 75 74 22 29 20 29    if( P("out") )
48f0: 7b 0a 20 20 20 20 6c 6f 67 69 6e 5f 63 6c 65 61  {.    login_clea
4900: 72 5f 6c 6f 67 69 6e 5f 64 61 74 61 28 29 3b 0a  r_login_data();.
4910: 20 20 20 20 72 65 64 69 72 65 63 74 5f 74 6f 5f      redirect_to_
4920: 67 28 29 3b 0a 20 20 20 20 72 65 74 75 72 6e 3b  g();.    return;
4930: 0a 20 20 7d 0a 0a 20 20 2f 2a 20 52 65 64 69 72  .  }..  /* Redir
4940: 65 63 74 20 66 6f 72 20 63 72 65 61 74 65 2d 6e  ect for create-n
4950: 65 77 2d 61 63 63 6f 75 6e 74 20 72 65 71 75 65  ew-account reque
4960: 73 74 73 20 2a 2f 0a 20 20 69 66 28 20 50 28 22  sts */.  if( P("
4970: 73 65 6c 66 22 29 20 29 7b 0a 20 20 20 20 63 67  self") ){.    cg
4980: 69 5f 72 65 64 69 72 65 63 74 66 28 22 25 52 2f  i_redirectf("%R/
4990: 72 65 67 69 73 74 65 72 22 29 3b 0a 20 20 20 20  register");.    
49a0: 72 65 74 75 72 6e 3b 0a 20 20 7d 0a 0a 20 20 2f  return;.  }..  /
49b0: 2a 20 44 65 61 6c 20 77 69 74 68 20 70 61 73 73  * Deal with pass
49c0: 77 6f 72 64 2d 63 68 61 6e 67 65 20 72 65 71 75  word-change requ
49d0: 65 73 74 73 20 2a 2f 0a 20 20 69 66 28 20 67 2e  ests */.  if( g.
49e0: 70 65 72 6d 2e 50 61 73 73 77 6f 72 64 20 26 26  perm.Password &&
49f0: 20 7a 50 61 73 73 77 64 0a 20 20 20 26 26 20 28   zPasswd.   && (
4a00: 7a 4e 65 77 31 20 3d 20 50 28 22 6e 31 22 29 29  zNew1 = P("n1"))
4a10: 21 3d 30 20 26 26 20 28 7a 4e 65 77 32 20 3d 20  !=0 && (zNew2 = 
4a20: 50 28 22 6e 32 22 29 29 21 3d 30 0a 20 20 29 7b  P("n2"))!=0.  ){
4a30: 0a 20 20 20 20 2f 2a 20 49 66 20 74 68 65 72 65  .    /* If there
4a40: 20 69 73 20 6e 6f 74 20 61 20 22 72 65 61 6c 22   is not a "real"
4a50: 20 6c 6f 67 69 6e 2c 20 77 65 20 63 61 6e 6e 6f   login, we canno
4a60: 74 20 63 68 61 6e 67 65 20 61 6e 79 20 70 61 73  t change any pas
4a70: 73 77 6f 72 64 2e 20 2a 2f 0a 20 20 20 20 69 66  sword. */.    if
4a80: 28 20 67 2e 7a 4c 6f 67 69 6e 20 29 7b 0a 20 20  ( g.zLogin ){.  
4a90: 20 20 20 20 2f 2a 20 54 68 65 20 75 73 65 72 20      /* The user 
4aa0: 72 65 71 75 65 73 74 73 20 61 20 70 61 73 73 77  requests a passw
4ab0: 6f 72 64 20 63 68 61 6e 67 65 20 2a 2f 0a 20 20  ord change */.  
4ac0: 20 20 20 20 7a 53 68 61 31 50 77 20 3d 20 73 68      zSha1Pw = sh
4ad0: 61 31 5f 73 68 61 72 65 64 5f 73 65 63 72 65 74  a1_shared_secret
4ae0: 28 7a 50 61 73 73 77 64 2c 20 67 2e 7a 4c 6f 67  (zPasswd, g.zLog
4af0: 69 6e 2c 20 30 29 3b 0a 20 20 20 20 20 20 69 66  in, 0);.      if
4b00: 28 20 64 62 5f 69 6e 74 28 31 2c 20 22 53 45 4c  ( db_int(1, "SEL
4b10: 45 43 54 20 30 20 46 52 4f 4d 20 75 73 65 72 22  ECT 0 FROM user"
4b20: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
4b30: 20 20 20 20 20 22 20 57 48 45 52 45 20 75 69 64       " WHERE uid
4b40: 3d 25 64 22 0a 20 20 20 20 20 20 20 20 20 20 20  =%d".           
4b50: 20 20 20 20 20 20 20 20 20 22 20 41 4e 44 20 28           " AND (
4b60: 63 6f 6e 73 74 61 6e 74 5f 74 69 6d 65 5f 63 6d  constant_time_cm
4b70: 70 28 70 77 2c 25 51 29 3d 30 22 0a 20 20 20 20  p(pw,%Q)=0".    
4b80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4b90: 22 20 20 20 20 20 20 4f 52 20 63 6f 6e 73 74 61  "      OR consta
4ba0: 6e 74 5f 74 69 6d 65 5f 63 6d 70 28 70 77 2c 25  nt_time_cmp(pw,%
4bb0: 51 29 3d 30 29 22 2c 0a 20 20 20 20 20 20 20 20  Q)=0)",.        
4bc0: 20 20 20 20 20 20 20 20 20 20 20 20 67 2e 75 73              g.us
4bd0: 65 72 55 69 64 2c 20 7a 53 68 61 31 50 77 2c 20  erUid, zSha1Pw, 
4be0: 7a 50 61 73 73 77 64 29 20 29 7b 0a 20 20 20 20  zPasswd) ){.    
4bf0: 20 20 20 20 73 6c 65 65 70 28 31 29 3b 0a 20 20      sleep(1);.  
4c00: 20 20 20 20 20 20 7a 45 72 72 4d 73 67 20 3d 0a        zErrMsg =.
4c10: 20 20 20 20 20 20 20 20 20 20 20 40 20 3c 70 3e             @ <p>
4c20: 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6c 6f 67  <span class="log
4c30: 69 6e 45 72 72 6f 72 22 3e 0a 20 20 20 20 20 20  inError">.      
4c40: 20 20 20 20 20 40 20 59 6f 75 20 65 6e 74 65 72       @ You enter
4c50: 65 64 20 61 6e 20 69 6e 63 6f 72 72 65 63 74 20  ed an incorrect 
4c60: 6f 6c 64 20 70 61 73 73 77 6f 72 64 20 77 68 69  old password whi
4c70: 6c 65 20 61 74 74 65 6d 70 74 69 6e 67 20 74 6f  le attempting to
4c80: 20 63 68 61 6e 67 65 0a 20 20 20 20 20 20 20 20   change.        
4c90: 20 20 20 40 20 79 6f 75 72 20 70 61 73 73 77 6f     @ your passwo
4ca0: 72 64 2e 20 20 59 6f 75 72 20 70 61 73 73 77 6f  rd.  Your passwo
4cb0: 72 64 20 69 73 20 75 6e 63 68 61 6e 67 65 64 2e  rd is unchanged.
4cc0: 0a 20 20 20 20 20 20 20 20 20 20 20 40 20 3c 2f  .           @ </
4cd0: 73 70 61 6e 3e 3c 2f 70 3e 0a 20 20 20 20 20 20  span></p>.      
4ce0: 20 20 3b 0a 20 20 20 20 20 20 7d 65 6c 73 65 20    ;.      }else 
4cf0: 69 66 28 20 66 6f 73 73 69 6c 5f 73 74 72 63 6d  if( fossil_strcm
4d00: 70 28 7a 4e 65 77 31 2c 7a 4e 65 77 32 29 21 3d  p(zNew1,zNew2)!=
4d10: 30 20 29 7b 0a 20 20 20 20 20 20 20 20 7a 45 72  0 ){.        zEr
4d20: 72 4d 73 67 20 3d 0a 20 20 20 20 20 20 20 20 20  rMsg =.         
4d30: 20 20 40 20 3c 70 3e 3c 73 70 61 6e 20 63 6c 61    @ <p><span cla
4d40: 73 73 3d 22 6c 6f 67 69 6e 45 72 72 6f 72 22 3e  ss="loginError">
4d50: 0a 20 20 20 20 20 20 20 20 20 20 20 40 20 54 68  .           @ Th
4d60: 65 20 74 77 6f 20 63 6f 70 69 65 73 20 6f 66 20  e two copies of 
4d70: 79 6f 75 72 20 6e 65 77 20 70 61 73 73 77 6f 72  your new passwor
4d80: 64 73 20 64 6f 20 6e 6f 74 20 6d 61 74 63 68 2e  ds do not match.
4d90: 0a 20 20 20 20 20 20 20 20 20 20 20 40 20 59 6f  .           @ Yo
4da0: 75 72 20 70 61 73 73 77 6f 72 64 20 69 73 20 75  ur password is u
4db0: 6e 63 68 61 6e 67 65 64 2e 0a 20 20 20 20 20 20  nchanged..      
4dc0: 20 20 20 20 20 40 20 3c 2f 73 70 61 6e 3e 3c 2f       @ </span></
4dd0: 70 3e 0a 20 20 20 20 20 20 20 20 3b 0a 20 20 20  p>.        ;.   
4de0: 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20     }else{.      
4df0: 20 20 63 68 61 72 20 2a 7a 4e 65 77 50 77 20 3d    char *zNewPw =
4e00: 20 73 68 61 31 5f 73 68 61 72 65 64 5f 73 65 63   sha1_shared_sec
4e10: 72 65 74 28 7a 4e 65 77 31 2c 20 67 2e 7a 4c 6f  ret(zNew1, g.zLo
4e20: 67 69 6e 2c 20 30 29 3b 0a 20 20 20 20 20 20 20  gin, 0);.       
4e30: 20 63 68 61 72 20 2a 7a 43 68 6e 67 50 77 3b 0a   char *zChngPw;.
4e40: 20 20 20 20 20 20 20 20 63 68 61 72 20 2a 7a 45          char *zE
4e50: 72 72 3b 0a 20 20 20 20 20 20 20 20 64 62 5f 6d  rr;.        db_m
4e60: 75 6c 74 69 5f 65 78 65 63 28 0a 20 20 20 20 20  ulti_exec(.     
4e70: 20 20 20 20 20 20 22 55 50 44 41 54 45 20 75 73        "UPDATE us
4e80: 65 72 20 53 45 54 20 70 77 3d 25 51 20 57 48 45  er SET pw=%Q WHE
4e90: 52 45 20 75 69 64 3d 25 64 22 2c 20 7a 4e 65 77  RE uid=%d", zNew
4ea0: 50 77 2c 20 67 2e 75 73 65 72 55 69 64 0a 20 20  Pw, g.userUid.  
4eb0: 20 20 20 20 20 20 29 3b 0a 20 20 20 20 20 20 20        );.       
4ec0: 20 66 6f 73 73 69 6c 5f 66 72 65 65 28 7a 4e 65   fossil_free(zNe
4ed0: 77 50 77 29 3b 0a 20 20 20 20 20 20 20 20 7a 43  wPw);.        zC
4ee0: 68 6e 67 50 77 20 3d 20 6d 70 72 69 6e 74 66 28  hngPw = mprintf(
4ef0: 0a 20 20 20 20 20 20 20 20 20 20 20 22 55 50 44  .           "UPD
4f00: 41 54 45 20 75 73 65 72 22 0a 20 20 20 20 20 20  ATE user".      
4f10: 20 20 20 20 20 22 20 20 20 53 45 54 20 70 77 3d       "   SET pw=
4f20: 73 68 61 72 65 64 5f 73 65 63 72 65 74 28 25 51  shared_secret(%Q
4f30: 2c 25 51 2c 22 0a 20 20 20 20 20 20 20 20 20 20  ,%Q,".          
4f40: 20 22 20 20 20 20 20 20 20 20 28 53 45 4c 45 43   "        (SELEC
4f50: 54 20 76 61 6c 75 65 20 46 52 4f 4d 20 63 6f 6e  T value FROM con
4f60: 66 69 67 20 57 48 45 52 45 20 6e 61 6d 65 3d 27  fig WHERE name='
4f70: 70 72 6f 6a 65 63 74 2d 63 6f 64 65 27 29 29 22  project-code'))"
4f80: 0a 20 20 20 20 20 20 20 20 20 20 20 22 20 57 48  .           " WH
4f90: 45 52 45 20 6c 6f 67 69 6e 3d 25 51 22 2c 0a 20  ERE login=%Q",. 
4fa0: 20 20 20 20 20 20 20 20 20 20 7a 4e 65 77 31 2c            zNew1,
4fb0: 20 67 2e 7a 4c 6f 67 69 6e 2c 20 67 2e 7a 4c 6f   g.zLogin, g.zLo
4fc0: 67 69 6e 0a 20 20 20 20 20 20 20 20 29 3b 0a 20  gin.        );. 
4fd0: 20 20 20 20 20 20 20 69 66 28 20 6c 6f 67 69 6e         if( login
4fe0: 5f 67 72 6f 75 70 5f 73 71 6c 28 7a 43 68 6e 67  _group_sql(zChng
4ff0: 50 77 2c 20 22 3c 70 3e 22 2c 20 22 3c 2f 70 3e  Pw, "<p>", "</p>
5000: 5c 6e 22 2c 20 26 7a 45 72 72 29 20 29 7b 0a 20  \n", &zErr) ){. 
5010: 20 20 20 20 20 20 20 20 20 7a 45 72 72 4d 73 67           zErrMsg
5020: 20 3d 20 6d 70 72 69 6e 74 66 28 22 3c 73 70 61   = mprintf("<spa
5030: 6e 20 63 6c 61 73 73 3d 5c 22 6c 6f 67 69 6e 45  n class=\"loginE
5040: 72 72 6f 72 5c 22 3e 25 73 3c 2f 73 70 61 6e 3e  rror\">%s</span>
5050: 22 2c 20 7a 45 72 72 29 3b 0a 20 20 20 20 20 20  ", zErr);.      
5060: 20 20 20 20 66 6f 73 73 69 6c 5f 66 72 65 65 28      fossil_free(
5070: 7a 45 72 72 29 3b 0a 20 20 20 20 20 20 20 20 7d  zErr);.        }
5080: 65 6c 73 65 7b 0a 20 20 20 20 20 20 20 20 20 20  else{.          
5090: 72 65 64 69 72 65 63 74 5f 74 6f 5f 67 28 29 3b  redirect_to_g();
50a0: 0a 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72  .          retur
50b0: 6e 3b 0a 20 20 20 20 20 20 20 20 7d 0a 20 20 20  n;.        }.   
50c0: 20 20 20 7d 0a 20 20 20 20 7d 65 6c 73 65 7b 0a     }.    }else{.
50d0: 20 20 20 20 20 20 7a 45 72 72 4d 73 67 20 3d 0a        zErrMsg =.
50e0: 20 20 20 20 20 20 20 20 20 40 20 3c 70 3e 3c 73           @ <p><s
50f0: 70 61 6e 20 63 6c 61 73 73 3d 22 6c 6f 67 69 6e  pan class="login
5100: 45 72 72 6f 72 22 3e 0a 20 20 20 20 20 20 20 20  Error">.        
5110: 20 40 20 54 68 65 20 70 61 73 73 77 6f 72 64 20   @ The password 
5120: 63 61 6e 6e 6f 74 20 62 65 20 63 68 61 6e 67 65  cannot be change
5130: 64 20 66 6f 72 20 74 68 69 73 20 74 79 70 65 20  d for this type 
5140: 6f 66 20 6c 6f 67 69 6e 2e 0a 20 20 20 20 20 20  of login..      
5150: 20 20 20 40 20 54 68 65 20 70 61 73 73 77 6f 72     @ The passwor
5160: 64 20 69 73 20 75 6e 63 68 61 6e 67 65 64 2e 0a  d is unchanged..
5170: 20 20 20 20 20 20 20 20 20 40 20 3c 2f 73 70 61           @ </spa
5180: 6e 3e 3c 2f 70 3e 0a 20 20 20 20 20 20 3b 0a 20  n></p>.      ;. 
5190: 20 20 20 7d 0a 20 20 7d 0a 20 20 7a 49 70 41 64     }.  }.  zIpAd
51a0: 64 72 20 3d 20 50 44 28 22 52 45 4d 4f 54 45 5f  dr = PD("REMOTE_
51b0: 41 44 44 52 22 2c 22 6e 69 6c 22 29 3b 20 20 20  ADDR","nil");   
51c0: 2f 2a 20 43 6f 6d 70 6c 65 74 65 20 49 50 20 61  /* Complete IP a
51d0: 64 64 72 65 73 73 20 66 6f 72 20 6c 6f 67 67 69  ddress for loggi
51e0: 6e 67 20 2a 2f 0a 20 20 7a 52 65 66 65 72 65 72  ng */.  zReferer
51f0: 20 3d 20 50 28 22 48 54 54 50 5f 52 45 46 45 52   = P("HTTP_REFER
5200: 45 52 22 29 3b 0a 20 20 75 69 64 20 3d 20 6c 6f  ER");.  uid = lo
5210: 67 69 6e 5f 69 73 5f 76 61 6c 69 64 5f 61 6e 6f  gin_is_valid_ano
5220: 6e 79 6d 6f 75 73 28 7a 55 73 65 72 6e 61 6d 65  nymous(zUsername
5230: 2c 20 7a 50 61 73 73 77 64 2c 20 50 28 22 63 73  , zPasswd, P("cs
5240: 22 29 29 3b 0a 20 20 69 66 28 20 75 69 64 3e 30  "));.  if( uid>0
5250: 20 29 7b 0a 20 20 20 20 6c 6f 67 69 6e 5f 73 65   ){.    login_se
5260: 74 5f 61 6e 6f 6e 5f 63 6f 6f 6b 69 65 28 7a 49  t_anon_cookie(zI
5270: 70 41 64 64 72 2c 20 4e 55 4c 4c 29 3b 0a 20 20  pAddr, NULL);.  
5280: 20 20 72 65 63 6f 72 64 5f 6c 6f 67 69 6e 5f 61    record_login_a
5290: 74 74 65 6d 70 74 28 22 61 6e 6f 6e 79 6d 6f 75  ttempt("anonymou
52a0: 73 22 2c 20 7a 49 70 41 64 64 72 2c 20 31 29 3b  s", zIpAddr, 1);
52b0: 0a 20 20 20 20 72 65 64 69 72 65 63 74 5f 74 6f  .    redirect_to
52c0: 5f 67 28 29 3b 0a 20 20 7d 0a 20 20 69 66 28 20  _g();.  }.  if( 
52d0: 7a 55 73 65 72 6e 61 6d 65 21 3d 30 20 26 26 20  zUsername!=0 && 
52e0: 7a 50 61 73 73 77 64 21 3d 30 20 26 26 20 7a 50  zPasswd!=0 && zP
52f0: 61 73 73 77 64 5b 30 5d 21 3d 30 20 29 7b 0a 20  asswd[0]!=0 ){. 
5300: 20 20 20 2f 2a 20 41 74 74 65 6d 70 74 69 6e 67     /* Attempting
5310: 20 74 6f 20 6c 6f 67 20 69 6e 20 61 73 20 61 20   to log in as a 
5320: 75 73 65 72 20 6f 74 68 65 72 20 74 68 61 6e 20  user other than 
5330: 61 6e 6f 6e 79 6d 6f 75 73 2e 0a 20 20 20 20 2a  anonymous..    *
5340: 2f 0a 20 20 20 20 75 69 64 20 3d 20 6c 6f 67 69  /.    uid = logi
5350: 6e 5f 73 65 61 72 63 68 5f 75 69 64 28 7a 55 73  n_search_uid(zUs
5360: 65 72 6e 61 6d 65 2c 20 7a 50 61 73 73 77 64 29  ername, zPasswd)
5370: 3b 0a 20 20 20 20 69 66 28 20 75 69 64 3c 3d 30  ;.    if( uid<=0
5380: 20 29 7b 0a 20 20 20 20 20 20 73 6c 65 65 70 28   ){.      sleep(
5390: 31 29 3b 0a 20 20 20 20 20 20 7a 45 72 72 4d 73  1);.      zErrMs
53a0: 67 20 3d 0a 20 20 20 20 20 20 20 20 20 40 20 3c  g =.         @ <
53b0: 70 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6c  p><span class="l
53c0: 6f 67 69 6e 45 72 72 6f 72 22 3e 0a 20 20 20 20  oginError">.    
53d0: 20 20 20 20 20 40 20 59 6f 75 20 65 6e 74 65 72       @ You enter
53e0: 65 64 20 61 6e 20 75 6e 6b 6e 6f 77 6e 20 75 73  ed an unknown us
53f0: 65 72 20 6f 72 20 61 6e 20 69 6e 63 6f 72 72 65  er or an incorre
5400: 63 74 20 70 61 73 73 77 6f 72 64 2e 0a 20 20 20  ct password..   
5410: 20 20 20 20 20 20 40 20 3c 2f 73 70 61 6e 3e 3c        @ </span><
5420: 2f 70 3e 0a 20 20 20 20 20 20 3b 0a 20 20 20 20  /p>.      ;.    
5430: 20 20 72 65 63 6f 72 64 5f 6c 6f 67 69 6e 5f 61    record_login_a
5440: 74 74 65 6d 70 74 28 7a 55 73 65 72 6e 61 6d 65  ttempt(zUsername
5450: 2c 20 7a 49 70 41 64 64 72 2c 20 30 29 3b 0a 20  , zIpAddr, 0);. 
5460: 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20     }else{.      
5470: 2f 2a 20 4e 6f 6e 2d 61 6e 6f 6e 79 6d 6f 75 73  /* Non-anonymous
5480: 20 6c 6f 67 69 6e 20 69 73 20 73 75 63 63 65 73   login is succes
5490: 73 66 75 6c 2e 20 20 53 65 74 20 61 20 63 6f 6f  sful.  Set a coo
54a0: 6b 69 65 20 6f 66 20 74 68 65 20 66 6f 72 6d 3a  kie of the form:
54b0: 0a 20 20 20 20 20 20 2a 2a 0a 20 20 20 20 20 20  .      **.      
54c0: 2a 2a 20 20 20 20 48 41 53 48 2f 50 52 4f 4a 45  **    HASH/PROJE
54d0: 43 54 2f 4c 4f 47 49 4e 0a 20 20 20 20 20 20 2a  CT/LOGIN.      *
54e0: 2a 0a 20 20 20 20 20 20 2a 2a 20 77 68 65 72 65  *.      ** where
54f0: 20 48 41 53 48 20 69 73 20 61 20 72 61 6e 64 6f   HASH is a rando
5500: 6d 20 68 65 78 20 6e 75 6d 62 65 72 2c 20 50 52  m hex number, PR
5510: 4f 4a 45 43 54 20 69 73 20 65 69 74 68 65 72 20  OJECT is either 
5520: 70 72 6f 6a 65 63 74 0a 20 20 20 20 20 20 2a 2a  project.      **
5530: 20 63 6f 64 65 20 70 72 65 66 69 78 2c 20 61 6e   code prefix, an
5540: 64 20 4c 4f 47 49 4e 20 69 73 20 74 68 65 20 75  d LOGIN is the u
5550: 73 65 72 20 6e 61 6d 65 2e 0a 20 20 20 20 20 20  ser name..      
5560: 2a 2f 0a 20 20 20 20 20 20 6c 6f 67 69 6e 5f 73  */.      login_s
5570: 65 74 5f 75 73 65 72 5f 63 6f 6f 6b 69 65 28 7a  et_user_cookie(z
5580: 55 73 65 72 6e 61 6d 65 2c 20 75 69 64 2c 20 4e  Username, uid, N
5590: 55 4c 4c 29 3b 0a 20 20 20 20 20 20 72 65 64 69  ULL);.      redi
55a0: 72 65 63 74 5f 74 6f 5f 67 28 29 3b 0a 20 20 20  rect_to_g();.   
55b0: 20 7d 0a 20 20 7d 0a 20 20 73 74 79 6c 65 5f 68   }.  }.  style_h
55c0: 65 61 64 65 72 28 22 4c 6f 67 69 6e 2f 4c 6f 67  eader("Login/Log
55d0: 6f 75 74 22 29 3b 0a 20 20 73 74 79 6c 65 5f 61  out");.  style_a
55e0: 64 75 6e 69 74 5f 63 6f 6e 66 69 67 28 41 44 55  dunit_config(ADU
55f0: 4e 49 54 5f 4f 46 46 29 3b 0a 20 20 40 20 25 73  NIT_OFF);.  @ %s
5600: 28 7a 45 72 72 4d 73 67 29 0a 20 20 69 66 28 20  (zErrMsg).  if( 
5610: 7a 47 6f 74 6f 20 26 26 20 21 6e 6f 41 6e 6f 6e  zGoto && !noAnon
5620: 20 29 7b 0a 20 20 20 20 63 68 61 72 20 2a 7a 41   ){.    char *zA
5630: 62 62 72 65 76 20 3d 20 66 6f 73 73 69 6c 5f 73  bbrev = fossil_s
5640: 74 72 64 75 70 28 7a 47 6f 74 6f 29 3b 0a 20 20  trdup(zGoto);.  
5650: 20 20 69 6e 74 20 69 3b 0a 20 20 20 20 66 6f 72    int i;.    for
5660: 28 69 3d 30 3b 20 7a 41 62 62 72 65 76 5b 69 5d  (i=0; zAbbrev[i]
5670: 20 26 26 20 7a 41 62 62 72 65 76 5b 69 5d 21 3d   && zAbbrev[i]!=
5680: 27 3f 27 3b 20 69 2b 2b 29 7b 7d 0a 20 20 20 20  '?'; i++){}.    
5690: 7a 41 62 62 72 65 76 5b 69 5d 20 3d 20 30 3b 0a  zAbbrev[i] = 0;.
56a0: 20 20 20 20 69 66 28 20 67 2e 7a 4c 6f 67 69 6e      if( g.zLogin
56b0: 20 29 7b 0a 20 20 20 20 20 20 40 20 3c 70 3e 55   ){.      @ <p>U
56c0: 73 65 20 61 20 64 69 66 66 65 72 65 6e 74 20 6c  se a different l
56d0: 6f 67 69 6e 20 77 69 74 68 20 67 72 65 61 74 65  ogin with greate
56e0: 72 20 70 72 69 76 69 6c 65 67 65 20 74 68 61 6e  r privilege than
56f0: 20 3c 62 3e 25 68 28 67 2e 7a 4c 6f 67 69 6e 29   <b>%h(g.zLogin)
5700: 3c 2f 62 3e 0a 20 20 20 20 20 20 40 20 74 6f 20  </b>.      @ to 
5710: 61 63 63 65 73 73 20 3c 62 3e 25 68 28 7a 41 62  access <b>%h(zAb
5720: 62 72 65 76 29 3c 2f 62 3e 2e 0a 20 20 20 20 7d  brev)</b>..    }
5730: 65 6c 73 65 20 69 66 28 20 61 6e 6f 6e 46 6c 61  else if( anonFla
5740: 67 20 29 7b 0a 20 20 20 20 20 20 40 20 3c 70 3e  g ){.      @ <p>
5750: 4c 6f 67 69 6e 20 61 73 20 3c 62 3e 61 6e 6f 6e  Login as <b>anon
5760: 79 6d 6f 75 73 3c 2f 62 3e 20 6f 72 20 61 6e 79  ymous</b> or any
5770: 20 6e 61 6d 65 64 20 75 73 65 72 0a 20 20 20 20   named user.    
5780: 20 20 40 20 74 6f 20 61 63 63 65 73 73 20 70 61    @ to access pa
5790: 67 65 20 3c 62 3e 25 68 28 7a 41 62 62 72 65 76  ge <b>%h(zAbbrev
57a0: 29 3c 2f 62 3e 2e 0a 20 20 20 20 7d 65 6c 73 65  )</b>..    }else
57b0: 7b 0a 20 20 20 20 20 20 40 20 3c 70 3e 4c 6f 67  {.      @ <p>Log
57c0: 69 6e 20 61 73 20 61 20 6e 61 6d 65 64 20 75 73  in as a named us
57d0: 65 72 20 74 6f 20 61 63 63 65 73 73 20 70 61 67  er to access pag
57e0: 65 20 3c 62 3e 25 68 28 7a 41 62 62 72 65 76 29  e <b>%h(zAbbrev)
57f0: 3c 2f 62 3e 2e 0a 20 20 20 20 7d 0a 20 20 7d 0a  </b>..    }.  }.
5800: 20 20 69 66 28 20 67 2e 73 73 6c 4e 6f 74 41 76    if( g.sslNotAv
5810: 61 69 6c 61 62 6c 65 3d 3d 30 0a 20 20 20 26 26  ailable==0.   &&
5820: 20 73 74 72 6e 63 6d 70 28 67 2e 7a 42 61 73 65   strncmp(g.zBase
5830: 55 52 4c 2c 22 68 74 74 70 73 3a 22 2c 36 29 21  URL,"https:",6)!
5840: 3d 30 0a 20 20 20 26 26 20 64 62 5f 67 65 74 5f  =0.   && db_get_
5850: 62 6f 6f 6c 65 61 6e 28 22 68 74 74 70 73 2d 6c  boolean("https-l
5860: 6f 67 69 6e 22 2c 30 29 0a 20 20 29 7b 0a 20 20  ogin",0).  ){.  
5870: 20 20 66 6f 72 6d 5f 62 65 67 69 6e 28 30 2c 20    form_begin(0, 
5880: 22 68 74 74 70 73 3a 25 73 2f 6c 6f 67 69 6e 22  "https:%s/login"
5890: 2c 20 67 2e 7a 42 61 73 65 55 52 4c 2b 35 29 3b  , g.zBaseURL+5);
58a0: 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 66 6f  .  }else{.    fo
58b0: 72 6d 5f 62 65 67 69 6e 28 30 2c 20 22 25 52 2f  rm_begin(0, "%R/
58c0: 6c 6f 67 69 6e 22 29 3b 0a 20 20 7d 0a 20 20 69  login");.  }.  i
58d0: 66 28 20 7a 47 6f 74 6f 20 29 7b 0a 20 20 20 20  f( zGoto ){.    
58e0: 40 20 3c 69 6e 70 75 74 20 74 79 70 65 3d 22 68  @ <input type="h
58f0: 69 64 64 65 6e 22 20 6e 61 6d 65 3d 22 67 22 20  idden" name="g" 
5900: 76 61 6c 75 65 3d 22 25 68 28 7a 47 6f 74 6f 29  value="%h(zGoto)
5910: 22 20 2f 3e 0a 20 20 7d 65 6c 73 65 20 69 66 28  " />.  }else if(
5920: 20 7a 52 65 66 65 72 65 72 20 26 26 20 73 74 72   zReferer && str
5930: 6e 63 6d 70 28 67 2e 7a 42 61 73 65 55 52 4c 2c  ncmp(g.zBaseURL,
5940: 20 7a 52 65 66 65 72 65 72 2c 20 73 74 72 6c 65   zReferer, strle
5950: 6e 28 67 2e 7a 42 61 73 65 55 52 4c 29 29 3d 3d  n(g.zBaseURL))==
5960: 30 20 29 7b 0a 20 20 20 20 40 20 3c 69 6e 70 75  0 ){.    @ <inpu
5970: 74 20 74 79 70 65 3d 22 68 69 64 64 65 6e 22 20  t type="hidden" 
5980: 6e 61 6d 65 3d 22 67 22 20 76 61 6c 75 65 3d 22  name="g" value="
5990: 25 68 28 7a 52 65 66 65 72 65 72 29 22 20 2f 3e  %h(zReferer)" />
59a0: 0a 20 20 7d 0a 20 20 69 66 28 20 61 6e 6f 6e 46  .  }.  if( anonF
59b0: 6c 61 67 20 29 7b 0a 20 20 20 20 40 20 3c 69 6e  lag ){.    @ <in
59c0: 70 75 74 20 74 79 70 65 3d 22 68 69 64 64 65 6e  put type="hidden
59d0: 22 20 6e 61 6d 65 3d 22 61 6e 6f 6e 22 20 76 61  " name="anon" va
59e0: 6c 75 65 3d 22 31 22 20 2f 3e 0a 20 20 7d 0a 20  lue="1" />.  }. 
59f0: 20 69 66 28 20 67 2e 7a 4c 6f 67 69 6e 20 29 7b   if( g.zLogin ){
5a00: 0a 20 20 20 20 40 20 3c 70 3e 43 75 72 72 65 6e  .    @ <p>Curren
5a10: 74 6c 79 20 6c 6f 67 67 65 64 20 69 6e 20 61 73  tly logged in as
5a20: 20 3c 62 3e 25 68 28 67 2e 7a 4c 6f 67 69 6e 29   <b>%h(g.zLogin)
5a30: 3c 2f 62 3e 2e 0a 20 20 20 20 40 20 3c 69 6e 70  </b>..    @ <inp
5a40: 75 74 20 74 79 70 65 3d 22 73 75 62 6d 69 74 22  ut type="submit"
5a50: 20 6e 61 6d 65 3d 22 6f 75 74 22 20 76 61 6c 75   name="out" valu
5a60: 65 3d 22 4c 6f 67 6f 75 74 22 3e 3c 2f 70 3e 0a  e="Logout"></p>.
5a70: 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 40 20 3c    }else{.    @ <
5a80: 74 61 62 6c 65 20 63 6c 61 73 73 3d 22 6c 6f 67  table class="log
5a90: 69 6e 5f 6f 75 74 22 3e 0a 20 20 20 20 40 20 3c  in_out">.    @ <
5aa0: 74 72 3e 0a 20 20 20 20 40 20 20 20 3c 74 64 20  tr>.    @   <td 
5ab0: 63 6c 61 73 73 3d 22 66 6f 72 6d 5f 6c 61 62 65  class="form_labe
5ac0: 6c 22 3e 55 73 65 72 20 49 44 3a 3c 2f 74 64 3e  l">User ID:</td>
5ad0: 0a 20 20 20 20 69 66 28 20 61 6e 6f 6e 46 6c 61  .    if( anonFla
5ae0: 67 20 29 7b 0a 20 20 20 20 20 20 40 20 3c 74 64  g ){.      @ <td
5af0: 3e 3c 69 6e 70 75 74 20 74 79 70 65 3d 22 74 65  ><input type="te
5b00: 78 74 22 20 69 64 3d 22 75 22 20 6e 61 6d 65 3d  xt" id="u" name=
5b10: 22 75 22 20 76 61 6c 75 65 3d 22 61 6e 6f 6e 79  "u" value="anony
5b20: 6d 6f 75 73 22 20 73 69 7a 65 3d 22 33 30 22 3e  mous" size="30">
5b30: 3c 2f 74 64 3e 0a 20 20 20 20 7d 65 6c 73 65 7b  </td>.    }else{
5b40: 0a 20 20 20 20 20 20 40 20 3c 74 64 3e 3c 69 6e  .      @ <td><in
5b50: 70 75 74 20 74 79 70 65 3d 22 74 65 78 74 22 20  put type="text" 
5b60: 69 64 3d 22 75 22 20 6e 61 6d 65 3d 22 75 22 20  id="u" name="u" 
5b70: 76 61 6c 75 65 3d 22 22 20 73 69 7a 65 3d 22 33  value="" size="3
5b80: 30 22 20 2f 3e 3c 2f 74 64 3e 0a 20 20 20 20 7d  0" /></td>.    }
5b90: 0a 20 20 20 20 69 66 28 20 50 28 22 48 54 54 50  .    if( P("HTTP
5ba0: 53 22 29 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20  S")==0 ){.      
5bb0: 40 20 3c 74 64 20 77 69 64 74 68 3d 22 31 35 22  @ <td width="15"
5bc0: 3e 3c 74 64 20 72 6f 77 73 70 61 6e 3d 22 32 22  ><td rowspan="2"
5bd0: 3e 0a 20 20 20 20 20 20 40 20 3c 70 20 63 6c 61  >.      @ <p cla
5be0: 73 73 3d 27 73 65 63 75 72 69 74 79 57 61 72 6e  ss='securityWarn
5bf0: 69 6e 67 27 3e 0a 20 20 20 20 20 20 40 20 57 61  ing'>.      @ Wa
5c00: 72 6e 69 6e 67 3a 20 59 6f 75 72 20 70 61 73 73  rning: Your pass
5c10: 77 6f 72 64 20 77 69 6c 6c 20 62 65 20 73 65 6e  word will be sen
5c20: 74 20 69 6e 20 74 68 65 20 63 6c 65 61 72 20 6f  t in the clear o
5c30: 76 65 72 20 61 6e 0a 20 20 20 20 20 20 40 20 75  ver an.      @ u
5c40: 6e 65 6e 63 72 79 70 74 65 64 20 63 6f 6e 6e 65  nencrypted conne
5c50: 63 74 69 6f 6e 2e 0a 20 20 20 20 20 20 69 66 28  ction..      if(
5c60: 20 67 2e 73 73 6c 4e 6f 74 41 76 61 69 6c 61 62   g.sslNotAvailab
5c70: 6c 65 20 29 7b 0a 20 20 20 20 20 20 20 20 40 20  le ){.        @ 
5c80: 4e 6f 20 65 6e 63 72 79 70 74 65 64 20 63 6f 6e  No encrypted con
5c90: 6e 65 63 74 69 6f 6e 20 69 73 20 61 76 61 69 6c  nection is avail
5ca0: 61 62 6c 65 20 6f 6e 20 74 68 69 73 20 73 65 72  able on this ser
5cb0: 76 65 72 2e 0a 20 20 20 20 20 20 7d 65 6c 73 65  ver..      }else
5cc0: 7b 0a 20 20 20 20 20 20 20 20 40 20 43 6f 6e 73  {.        @ Cons
5cd0: 69 64 65 72 20 6c 6f 67 67 69 6e 67 20 69 6e 20  ider logging in 
5ce0: 61 74 0a 20 20 20 20 20 20 20 20 40 20 3c 61 20  at.        @ <a 
5cf0: 68 72 65 66 3d 27 25 73 28 67 2e 7a 48 74 74 70  href='%s(g.zHttp
5d00: 73 55 52 4c 29 27 3e 25 68 28 67 2e 7a 48 74 74  sURL)'>%h(g.zHtt
5d10: 70 73 55 52 4c 29 3c 2f 61 3e 20 69 6e 73 74 65  psURL)</a> inste
5d20: 61 64 2e 0a 20 20 20 20 20 20 7d 0a 20 20 20 20  ad..      }.    
5d30: 20 20 40 20 3c 2f 70 3e 0a 20 20 20 20 7d 0a 20    @ </p>.    }. 
5d40: 20 20 20 40 20 3c 2f 74 72 3e 0a 20 20 20 20 40     @ </tr>.    @
5d50: 20 3c 74 72 3e 0a 20 20 20 20 40 20 20 3c 74 64   <tr>.    @  <td
5d60: 20 63 6c 61 73 73 3d 22 66 6f 72 6d 5f 6c 61 62   class="form_lab
5d70: 65 6c 22 3e 50 61 73 73 77 6f 72 64 3a 3c 2f 74  el">Password:</t
5d80: 64 3e 0a 20 20 20 20 40 20 20 3c 74 64 3e 3c 69  d>.    @  <td><i
5d90: 6e 70 75 74 20 74 79 70 65 3d 22 70 61 73 73 77  nput type="passw
5da0: 6f 72 64 22 20 69 64 3d 22 70 22 20 6e 61 6d 65  ord" id="p" name
5db0: 3d 22 70 22 20 76 61 6c 75 65 3d 22 22 20 73 69  ="p" value="" si
5dc0: 7a 65 3d 22 33 30 22 20 2f 3e 3c 2f 74 64 3e 0a  ze="30" /></td>.
5dd0: 20 20 20 20 40 20 3c 2f 74 72 3e 0a 20 20 20 20      @ </tr>.    
5de0: 69 66 28 20 67 2e 7a 4c 6f 67 69 6e 3d 3d 30 20  if( g.zLogin==0 
5df0: 26 26 20 28 61 6e 6f 6e 46 6c 61 67 20 7c 7c 20  && (anonFlag || 
5e00: 7a 47 6f 74 6f 3d 3d 30 29 20 29 7b 0a 20 20 20  zGoto==0) ){.   
5e10: 20 20 20 7a 41 6e 6f 6e 50 77 20 3d 20 64 62 5f     zAnonPw = db_
5e20: 74 65 78 74 28 30 2c 20 22 53 45 4c 45 43 54 20  text(0, "SELECT 
5e30: 70 77 20 46 52 4f 4d 20 75 73 65 72 22 0a 20 20  pw FROM user".  
5e40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5e50: 20 20 20 20 20 20 20 20 20 22 20 57 48 45 52 45           " WHERE
5e60: 20 6c 6f 67 69 6e 3d 27 61 6e 6f 6e 79 6d 6f 75   login='anonymou
5e70: 73 27 22 0a 20 20 20 20 20 20 20 20 20 20 20 20  s'".            
5e80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 22                 "
5e90: 20 20 20 41 4e 44 20 63 61 70 21 3d 27 27 22 29     AND cap!=''")
5ea0: 3b 0a 20 20 20 20 7d 0a 20 20 20 20 40 20 3c 74  ;.    }.    @ <t
5eb0: 72 3e 0a 20 20 20 20 40 20 20 20 3c 74 64 3e 3c  r>.    @   <td><
5ec0: 2f 74 64 3e 0a 20 20 20 20 40 20 20 20 3c 74 64  /td>.    @   <td
5ed0: 3e 3c 69 6e 70 75 74 20 74 79 70 65 3d 22 73 75  ><input type="su
5ee0: 62 6d 69 74 22 20 6e 61 6d 65 3d 22 69 6e 22 20  bmit" name="in" 
5ef0: 76 61 6c 75 65 3d 22 4c 6f 67 69 6e 22 3e 3c 2f  value="Login"></
5f00: 74 64 3e 0a 20 20 20 20 40 20 20 20 3c 74 64 20  td>.    @   <td 
5f10: 63 6f 6c 73 70 61 6e 3d 22 32 22 3e 26 6c 61 72  colspan="2">&lar
5f20: 72 3b 20 50 72 65 73 73 69 6e 67 20 74 68 69 73  r; Pressing this
5f30: 20 62 75 74 74 6f 6e 20 67 72 61 6e 74 73 5c 0a   button grants\.
5f40: 20 20 20 20 40 20 20 20 70 65 72 6d 69 73 73 69      @   permissi
5f50: 6f 6e 20 74 6f 20 73 74 6f 72 65 20 61 20 63 6f  on to store a co
5f60: 6f 6b 69 65 0a 20 20 20 20 40 20 3c 2f 74 72 3e  okie.    @ </tr>
5f70: 0a 20 20 20 20 69 66 28 20 21 6e 6f 41 6e 6f 6e  .    if( !noAnon
5f80: 20 26 26 20 6c 6f 67 69 6e 5f 73 65 6c 66 5f 72   && login_self_r
5f90: 65 67 69 73 74 65 72 5f 61 76 61 69 6c 61 62 6c  egister_availabl
5fa0: 65 28 30 29 20 29 7b 0a 20 20 20 20 20 20 40 20  e(0) ){.      @ 
5fb0: 3c 74 72 3e 0a 20 20 20 20 20 20 40 20 20 20 3c  <tr>.      @   <
5fc0: 74 64 3e 3c 2f 74 64 3e 0a 20 20 20 20 20 20 40  td></td>.      @
5fd0: 20 20 20 3c 74 64 3e 3c 69 6e 70 75 74 20 74 79     <td><input ty
5fe0: 70 65 3d 22 73 75 62 6d 69 74 22 20 6e 61 6d 65  pe="submit" name
5ff0: 3d 22 73 65 6c 66 22 20 76 61 6c 75 65 3d 22 43  ="self" value="C
6000: 72 65 61 74 65 20 41 20 4e 65 77 20 41 63 63 6f  reate A New Acco
6010: 75 6e 74 22 3e 0a 20 20 20 20 20 20 40 20 20 20  unt">.      @   
6020: 3c 74 64 20 63 6f 6c 73 70 61 6e 3d 22 32 22 3e  <td colspan="2">
6030: 20 5c 0a 20 20 20 20 20 20 40 20 20 20 26 6c 61   \.      @   &la
6040: 72 72 3b 20 44 6f 6e 27 74 20 68 61 76 65 20 61  rr; Don't have a
6050: 20 6c 6f 67 69 6e 3f 20 20 43 6c 69 63 6b 20 74   login?  Click t
6060: 68 69 73 20 62 75 74 74 6f 6e 20 74 6f 20 63 72  his button to cr
6070: 65 61 74 65 20 6f 6e 65 2e 0a 20 20 20 20 20 20  eate one..      
6080: 40 20 3c 2f 74 72 3e 0a 20 20 20 20 7d 0a 20 20  @ </tr>.    }.  
6090: 20 20 40 20 3c 2f 74 61 62 6c 65 3e 0a 20 20 20    @ </table>.   
60a0: 20 69 66 28 20 7a 41 6e 6f 6e 50 77 20 26 26 20   if( zAnonPw && 
60b0: 21 6e 6f 41 6e 6f 6e 20 29 7b 0a 20 20 20 20 20  !noAnon ){.     
60c0: 20 75 6e 73 69 67 6e 65 64 20 69 6e 74 20 75 53   unsigned int uS
60d0: 65 65 64 20 3d 20 63 61 70 74 63 68 61 5f 73 65  eed = captcha_se
60e0: 65 64 28 29 3b 0a 20 20 20 20 20 20 63 6f 6e 73  ed();.      cons
60f0: 74 20 63 68 61 72 20 2a 7a 44 65 63 6f 64 65 64  t char *zDecoded
6100: 20 3d 20 63 61 70 74 63 68 61 5f 64 65 63 6f 64   = captcha_decod
6110: 65 28 75 53 65 65 64 29 3b 0a 20 20 20 20 20 20  e(uSeed);.      
6120: 69 6e 74 20 62 41 75 74 6f 43 61 70 74 63 68 61  int bAutoCaptcha
6130: 20 3d 20 64 62 5f 67 65 74 5f 62 6f 6f 6c 65 61   = db_get_boolea
6140: 6e 28 22 61 75 74 6f 2d 63 61 70 74 63 68 61 22  n("auto-captcha"
6150: 2c 20 30 29 3b 0a 20 20 20 20 20 20 63 68 61 72  , 0);.      char
6160: 20 2a 7a 43 61 70 74 63 68 61 20 3d 20 63 61 70   *zCaptcha = cap
6170: 74 63 68 61 5f 72 65 6e 64 65 72 28 7a 44 65 63  tcha_render(zDec
6180: 6f 64 65 64 29 3b 0a 20 20 0a 20 20 20 20 20 20  oded);.  .      
6190: 40 20 3c 70 3e 3c 69 6e 70 75 74 20 74 79 70 65  @ <p><input type
61a0: 3d 22 68 69 64 64 65 6e 22 20 6e 61 6d 65 3d 22  ="hidden" name="
61b0: 63 73 22 20 76 61 6c 75 65 3d 22 25 75 28 75 53  cs" value="%u(uS
61c0: 65 65 64 29 22 20 2f 3e 0a 20 20 20 20 20 20 40  eed)" />.      @
61d0: 20 56 69 73 69 74 6f 72 73 20 6d 61 79 20 65 6e   Visitors may en
61e0: 74 65 72 20 3c 62 3e 61 6e 6f 6e 79 6d 6f 75 73  ter <b>anonymous
61f0: 3c 2f 62 3e 20 61 73 20 74 68 65 20 75 73 65 72  </b> as the user
6200: 2d 49 44 20 77 69 74 68 0a 20 20 20 20 20 20 40  -ID with.      @
6210: 20 74 68 65 20 38 2d 63 68 61 72 61 63 74 65 72   the 8-character
6220: 20 68 65 78 61 64 65 63 69 6d 61 6c 20 70 61 73   hexadecimal pas
6230: 73 77 6f 72 64 20 73 68 6f 77 6e 20 62 65 6c 6f  sword shown belo
6240: 77 3a 3c 2f 70 3e 0a 20 20 20 20 20 20 40 20 3c  w:</p>.      @ <
6250: 64 69 76 20 63 6c 61 73 73 3d 22 63 61 70 74 63  div class="captc
6260: 68 61 22 3e 3c 74 61 62 6c 65 20 63 6c 61 73 73  ha"><table class
6270: 3d 22 63 61 70 74 63 68 61 22 3e 3c 74 72 3e 3c  ="captcha"><tr><
6280: 74 64 3e 3c 70 72 65 3e 0a 20 20 20 20 20 20 40  td><pre>.      @
6290: 20 25 68 28 7a 43 61 70 74 63 68 61 29 0a 20 20   %h(zCaptcha).  
62a0: 20 20 20 20 40 20 3c 2f 70 72 65 3e 3c 2f 74 64      @ </pre></td
62b0: 3e 3c 2f 74 72 3e 3c 2f 74 61 62 6c 65 3e 0a 20  ></tr></table>. 
62c0: 20 20 20 20 20 69 66 28 20 62 41 75 74 6f 43 61       if( bAutoCa
62d0: 70 74 63 68 61 20 29 20 7b 0a 20 20 20 20 20 20  ptcha ) {.      
62e0: 20 20 20 40 20 3c 69 6e 70 75 74 20 74 79 70 65     @ <input type
62f0: 3d 22 62 75 74 74 6f 6e 22 20 76 61 6c 75 65 3d  ="button" value=
6300: 22 46 69 6c 6c 20 6f 75 74 20 63 61 70 74 63 68  "Fill out captch
6310: 61 22 20 69 64 3d 27 61 75 74 6f 66 69 6c 6c 42  a" id='autofillB
6320: 75 74 74 6f 6e 27 20 5c 0a 20 20 20 20 20 20 20  utton' \.       
6330: 20 20 40 20 64 61 74 61 2d 61 66 3d 27 25 73 28    @ data-af='%s(
6340: 7a 44 65 63 6f 64 65 64 29 27 20 2f 3e 0a 20 20  zDecoded)' />.  
6350: 20 20 20 20 20 20 20 73 74 79 6c 65 5f 6c 6f 61         style_loa
6360: 64 5f 6f 6e 65 5f 6a 73 5f 66 69 6c 65 28 22 6c  d_one_js_file("l
6370: 6f 67 69 6e 2e 6a 73 22 29 3b 0a 20 20 20 20 20  ogin.js");.     
6380: 20 7d 0a 20 20 20 20 20 20 40 20 3c 2f 64 69 76   }.      @ </div
6390: 3e 0a 20 20 20 20 20 20 66 72 65 65 28 7a 43 61  >.      free(zCa
63a0: 70 74 63 68 61 29 3b 0a 20 20 20 20 7d 0a 20 20  ptcha);.    }.  
63b0: 20 20 40 20 3c 2f 66 6f 72 6d 3e 0a 20 20 7d 0a    @ </form>.  }.
63c0: 20 20 69 66 28 20 6c 6f 67 69 6e 5f 69 73 5f 69    if( login_is_i
63d0: 6e 64 69 76 69 64 75 61 6c 28 29 20 26 26 20 67  ndividual() && g
63e0: 2e 70 65 72 6d 2e 50 61 73 73 77 6f 72 64 20 29  .perm.Password )
63f0: 7b 0a 20 20 20 20 69 66 28 20 65 6d 61 69 6c 5f  {.    if( email_
6400: 65 6e 61 62 6c 65 64 28 29 20 29 7b 0a 20 20 20  enabled() ){.   
6410: 20 20 20 40 20 3c 68 72 3e 0a 20 20 20 20 20 20     @ <hr>.      
6420: 40 20 3c 70 3e 43 6f 6e 66 69 67 75 72 65 20 3c  @ <p>Configure <
6430: 61 20 68 72 65 66 3d 22 25 52 2f 61 6c 65 72 74  a href="%R/alert
6440: 73 22 3e 45 6d 61 69 6c 20 41 6c 65 72 74 73 3c  s">Email Alerts<
6450: 2f 61 3e 0a 20 20 20 20 20 20 40 20 66 6f 72 20  /a>.      @ for 
6460: 75 73 65 72 20 3c 62 3e 25 68 28 67 2e 7a 4c 6f  user <b>%h(g.zLo
6470: 67 69 6e 29 3c 2f 62 3e 3c 2f 70 3e 0a 20 20 20  gin)</b></p>.   
6480: 20 7d 0a 20 20 20 20 40 20 3c 68 72 20 2f 3e 0a   }.    @ <hr />.
6490: 20 20 20 20 40 20 3c 70 3e 43 68 61 6e 67 65 20      @ <p>Change 
64a0: 50 61 73 73 77 6f 72 64 20 66 6f 72 20 75 73 65  Password for use
64b0: 72 20 3c 62 3e 25 68 28 67 2e 7a 4c 6f 67 69 6e  r <b>%h(g.zLogin
64c0: 29 3c 2f 62 3e 3a 3c 2f 70 3e 0a 20 20 20 20 66  )</b>:</p>.    f
64d0: 6f 72 6d 5f 62 65 67 69 6e 28 30 2c 20 22 25 52  orm_begin(0, "%R
64e0: 2f 6c 6f 67 69 6e 22 29 3b 0a 20 20 20 20 40 20  /login");.    @ 
64f0: 3c 74 61 62 6c 65 3e 0a 20 20 20 20 40 20 3c 74  <table>.    @ <t
6500: 72 3e 3c 74 64 20 63 6c 61 73 73 3d 22 66 6f 72  r><td class="for
6510: 6d 5f 6c 61 62 65 6c 22 3e 4f 6c 64 20 50 61 73  m_label">Old Pas
6520: 73 77 6f 72 64 3a 3c 2f 74 64 3e 0a 20 20 20 20  sword:</td>.    
6530: 40 20 3c 74 64 3e 3c 69 6e 70 75 74 20 74 79 70  @ <td><input typ
6540: 65 3d 22 70 61 73 73 77 6f 72 64 22 20 6e 61 6d  e="password" nam
6550: 65 3d 22 70 22 20 73 69 7a 65 3d 22 33 30 22 20  e="p" size="30" 
6560: 2f 3e 3c 2f 74 64 3e 3c 2f 74 72 3e 0a 20 20 20  /></td></tr>.   
6570: 20 40 20 3c 74 72 3e 3c 74 64 20 63 6c 61 73 73   @ <tr><td class
6580: 3d 22 66 6f 72 6d 5f 6c 61 62 65 6c 22 3e 4e 65  ="form_label">Ne
6590: 77 20 50 61 73 73 77 6f 72 64 3a 3c 2f 74 64 3e  w Password:</td>
65a0: 0a 20 20 20 20 40 20 3c 74 64 3e 3c 69 6e 70 75  .    @ <td><inpu
65b0: 74 20 74 79 70 65 3d 22 70 61 73 73 77 6f 72 64  t type="password
65c0: 22 20 6e 61 6d 65 3d 22 6e 31 22 20 73 69 7a 65  " name="n1" size
65d0: 3d 22 33 30 22 20 2f 3e 3c 2f 74 64 3e 3c 2f 74  ="30" /></td></t
65e0: 72 3e 0a 20 20 20 20 40 20 3c 74 72 3e 3c 74 64  r>.    @ <tr><td
65f0: 20 63 6c 61 73 73 3d 22 66 6f 72 6d 5f 6c 61 62   class="form_lab
6600: 65 6c 22 3e 52 65 70 65 61 74 20 4e 65 77 20 50  el">Repeat New P
6610: 61 73 73 77 6f 72 64 3a 3c 2f 74 64 3e 0a 20 20  assword:</td>.  
6620: 20 20 40 20 3c 74 64 3e 3c 69 6e 70 75 74 20 74    @ <td><input t
6630: 79 70 65 3d 22 70 61 73 73 77 6f 72 64 22 20 6e  ype="password" n
6640: 61 6d 65 3d 22 6e 32 22 20 73 69 7a 65 3d 22 33  ame="n2" size="3
6650: 30 22 20 2f 3e 3c 2f 74 64 3e 3c 2f 74 72 3e 0a  0" /></td></tr>.
6660: 20 20 20 20 40 20 3c 74 72 3e 3c 74 64 3e 3c 2f      @ <tr><td></
6670: 74 64 3e 0a 20 20 20 20 40 20 3c 74 64 3e 3c 69  td>.    @ <td><i
6680: 6e 70 75 74 20 74 79 70 65 3d 22 73 75 62 6d 69  nput type="submi
6690: 74 22 20 76 61 6c 75 65 3d 22 43 68 61 6e 67 65  t" value="Change
66a0: 20 50 61 73 73 77 6f 72 64 22 20 2f 3e 3c 2f 74   Password" /></t
66b0: 64 3e 3c 2f 74 72 3e 0a 20 20 20 20 40 20 3c 2f  d></tr>.    @ </
66c0: 74 61 62 6c 65 3e 0a 20 20 20 20 40 20 3c 2f 66  table>.    @ </f
66d0: 6f 72 6d 3e 0a 20 20 7d 0a 20 20 73 74 79 6c 65  orm>.  }.  style
66e0: 5f 66 6f 6f 74 65 72 28 29 3b 0a 7d 0a 0a 2f 2a  _footer();.}../*
66f0: 0a 2a 2a 20 41 74 74 65 6d 70 74 20 74 6f 20 66  .** Attempt to f
6700: 69 6e 64 20 6c 6f 67 69 6e 20 63 72 65 64 65 6e  ind login creden
6710: 74 69 61 6c 73 20 66 6f 72 20 75 73 65 72 20 7a  tials for user z
6720: 4c 6f 67 69 6e 20 6f 6e 20 61 20 70 65 65 72 20  Login on a peer 
6730: 72 65 70 6f 73 69 74 6f 72 79 0a 2a 2a 20 77 69  repository.** wi
6740: 74 68 20 70 72 6f 6a 65 63 74 20 63 6f 64 65 20  th project code 
6750: 7a 43 6f 64 65 2e 20 20 54 72 61 6e 73 66 65 72  zCode.  Transfer
6760: 20 74 68 6f 73 65 20 63 72 65 64 65 6e 74 69 61   those credentia
6770: 6c 73 20 74 6f 20 74 68 65 20 6c 6f 63 61 6c 0a  ls to the local.
6780: 2a 2a 20 72 65 70 6f 73 69 74 6f 72 79 2e 0a 2a  ** repository..*
6790: 2a 0a 2a 2a 20 52 65 74 75 72 6e 20 74 72 75 65  *.** Return true
67a0: 20 69 66 20 61 20 74 72 61 6e 73 66 65 72 20 77   if a transfer w
67b0: 61 73 20 6d 61 64 65 20 61 6e 64 20 66 61 6c 73  as made and fals
67c0: 65 20 69 66 20 6e 6f 74 2e 0a 2a 2f 0a 73 74 61  e if not..*/.sta
67d0: 74 69 63 20 69 6e 74 20 6c 6f 67 69 6e 5f 74 72  tic int login_tr
67e0: 61 6e 73 66 65 72 5f 63 72 65 64 65 6e 74 69 61  ansfer_credentia
67f0: 6c 73 28 0a 20 20 63 6f 6e 73 74 20 63 68 61 72  ls(.  const char
6800: 20 2a 7a 4c 6f 67 69 6e 2c 20 20 20 20 20 20 20   *zLogin,       
6810: 20 20 20 2f 2a 20 4c 6f 67 69 6e 20 77 65 20 61     /* Login we a
6820: 72 65 20 6c 6f 6f 6b 69 6e 67 20 66 6f 72 20 2a  re looking for *
6830: 2f 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a  /.  const char *
6840: 7a 43 6f 64 65 2c 20 20 20 20 20 20 20 20 20 20  zCode,          
6850: 20 2f 2a 20 50 72 6f 6a 65 63 74 20 63 6f 64 65   /* Project code
6860: 20 6f 66 20 70 65 65 72 20 72 65 70 6f 73 69 74   of peer reposit
6870: 6f 72 79 20 2a 2f 0a 20 20 63 6f 6e 73 74 20 63  ory */.  const c
6880: 68 61 72 20 2a 7a 48 61 73 68 2c 20 20 20 20 20  har *zHash,     
6890: 20 20 20 20 20 20 2f 2a 20 48 41 53 48 20 66 72        /* HASH fr
68a0: 6f 6d 20 6c 6f 67 69 6e 20 63 6f 6f 6b 69 65 20  om login cookie 
68b0: 48 41 53 48 2f 43 4f 44 45 2f 4c 4f 47 49 4e 20  HASH/CODE/LOGIN 
68c0: 2a 2f 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20  */.  const char 
68d0: 2a 7a 52 65 6d 6f 74 65 41 64 64 72 20 20 20 20  *zRemoteAddr    
68e0: 20 20 2f 2a 20 52 65 71 75 65 73 74 20 63 6f 6d    /* Request com
68f0: 65 73 20 66 72 6f 6d 20 68 65 72 65 20 2a 2f 0a  es from here */.
6900: 29 7b 0a 20 20 73 71 6c 69 74 65 33 20 2a 70 4f  ){.  sqlite3 *pO
6910: 74 68 65 72 20 3d 20 30 3b 20 20 20 20 20 20 20  ther = 0;       
6920: 20 20 2f 2a 20 54 68 65 20 6f 74 68 65 72 20 72    /* The other r
6930: 65 70 6f 73 69 74 6f 72 79 20 2a 2f 0a 20 20 73  epository */.  s
6940: 71 6c 69 74 65 33 5f 73 74 6d 74 20 2a 70 53 74  qlite3_stmt *pSt
6950: 6d 74 3b 20 20 20 20 20 20 20 20 20 2f 2a 20 51  mt;         /* Q
6960: 75 65 72 79 20 61 67 61 69 6e 73 74 20 74 68 65  uery against the
6970: 20 6f 74 68 65 72 20 72 65 70 6f 73 69 74 6f 72   other repositor
6980: 79 20 2a 2f 0a 20 20 63 68 61 72 20 2a 7a 53 51  y */.  char *zSQ
6990: 4c 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  L;              
69a0: 20 20 20 20 2f 2a 20 53 51 4c 20 6f 66 20 74 68      /* SQL of th
69b0: 65 20 71 75 65 72 79 20 61 67 61 69 6e 73 74 20  e query against 
69c0: 6f 74 68 65 72 20 72 65 70 6f 20 2a 2f 0a 20 20  other repo */.  
69d0: 63 68 61 72 20 2a 7a 4f 74 68 65 72 52 65 70 6f  char *zOtherRepo
69e0: 3b 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20  ;            /* 
69f0: 46 69 6c 65 6e 61 6d 65 20 6f 66 20 74 68 65 20  Filename of the 
6a00: 6f 74 68 65 72 20 72 65 70 6f 73 69 74 6f 72 79  other repository
6a10: 20 2a 2f 0a 20 20 69 6e 74 20 72 63 3b 20 20 20   */.  int rc;   
6a20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
6a30: 20 20 20 2f 2a 20 52 65 73 75 6c 74 20 63 6f 64     /* Result cod
6a40: 65 20 66 72 6f 6d 20 53 51 4c 69 74 65 20 6c 69  e from SQLite li
6a50: 62 72 61 72 79 20 66 75 6e 63 74 69 6f 6e 73 20  brary functions 
6a60: 2a 2f 0a 20 20 69 6e 74 20 6e 58 66 65 72 20 3d  */.  int nXfer =
6a70: 20 30 3b 20 20 20 20 20 20 20 20 20 20 20 20 20   0;             
6a80: 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f 66 20 63    /* Number of c
6a90: 72 65 64 65 6e 74 69 61 6c 73 20 74 72 61 6e 73  redentials trans
6aa0: 66 65 72 72 65 64 20 2a 2f 0a 0a 20 20 7a 4f 74  ferred */..  zOt
6ab0: 68 65 72 52 65 70 6f 20 3d 20 64 62 5f 74 65 78  herRepo = db_tex
6ac0: 74 28 30 2c 0a 20 20 20 20 20 20 20 22 53 45 4c  t(0,.       "SEL
6ad0: 45 43 54 20 76 61 6c 75 65 20 46 52 4f 4d 20 63  ECT value FROM c
6ae0: 6f 6e 66 69 67 20 57 48 45 52 45 20 6e 61 6d 65  onfig WHERE name
6af0: 3d 27 70 65 65 72 2d 72 65 70 6f 2d 25 71 27 22  ='peer-repo-%q'"
6b00: 2c 0a 20 20 20 20 20 20 20 7a 43 6f 64 65 0a 20  ,.       zCode. 
6b10: 20 29 3b 0a 20 20 69 66 28 20 7a 4f 74 68 65 72   );.  if( zOther
6b20: 52 65 70 6f 3d 3d 30 20 29 20 72 65 74 75 72 6e  Repo==0 ) return
6b30: 20 30 3b 20 20 2f 2a 20 4e 6f 20 73 75 63 68 20   0;  /* No such 
6b40: 70 65 65 72 20 72 65 70 6f 73 69 74 6f 72 79 20  peer repository 
6b50: 2a 2f 0a 0a 20 20 72 63 20 3d 20 73 71 6c 69 74  */..  rc = sqlit
6b60: 65 33 5f 6f 70 65 6e 5f 76 32 28 0a 20 20 20 20  e3_open_v2(.    
6b70: 20 20 20 7a 4f 74 68 65 72 52 65 70 6f 2c 20 26     zOtherRepo, &
6b80: 70 4f 74 68 65 72 2c 0a 20 20 20 20 20 20 20 53  pOther,.       S
6b90: 51 4c 49 54 45 5f 4f 50 45 4e 5f 52 45 41 44 57  QLITE_OPEN_READW
6ba0: 52 49 54 45 20 7c 20 53 51 4c 49 54 45 5f 4f 50  RITE | SQLITE_OP
6bb0: 45 4e 5f 43 52 45 41 54 45 2c 0a 20 20 20 20 20  EN_CREATE,.     
6bc0: 20 20 67 2e 7a 56 66 73 4e 61 6d 65 0a 20 20 29    g.zVfsName.  )
6bd0: 3b 0a 20 20 69 66 28 20 72 63 3d 3d 53 51 4c 49  ;.  if( rc==SQLI
6be0: 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 73 71 6c  TE_OK ){.    sql
6bf0: 69 74 65 33 5f 63 72 65 61 74 65 5f 66 75 6e 63  ite3_create_func
6c00: 74 69 6f 6e 28 70 4f 74 68 65 72 2c 22 6e 6f 77  tion(pOther,"now
6c10: 22 2c 30 2c 53 51 4c 49 54 45 5f 55 54 46 38 2c  ",0,SQLITE_UTF8,
6c20: 30 2c 64 62 5f 6e 6f 77 5f 66 75 6e 63 74 69 6f  0,db_now_functio
6c30: 6e 2c 30 2c 30 29 3b 0a 20 20 20 20 73 71 6c 69  n,0,0);.    sqli
6c40: 74 65 33 5f 63 72 65 61 74 65 5f 66 75 6e 63 74  te3_create_funct
6c50: 69 6f 6e 28 70 4f 74 68 65 72 2c 20 22 63 6f 6e  ion(pOther, "con
6c60: 73 74 61 6e 74 5f 74 69 6d 65 5f 63 6d 70 22 2c  stant_time_cmp",
6c70: 20 32 2c 20 53 51 4c 49 54 45 5f 55 54 46 38 2c   2, SQLITE_UTF8,
6c80: 20 30 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20   0,.            
6c90: 20 20 20 20 20 20 63 6f 6e 73 74 61 6e 74 5f 74        constant_t
6ca0: 69 6d 65 5f 63 6d 70 5f 66 75 6e 63 74 69 6f 6e  ime_cmp_function
6cb0: 2c 20 30 2c 20 30 29 3b 0a 20 20 20 20 73 71 6c  , 0, 0);.    sql
6cc0: 69 74 65 33 5f 62 75 73 79 5f 74 69 6d 65 6f 75  ite3_busy_timeou
6cd0: 74 28 70 4f 74 68 65 72 2c 20 35 30 30 30 29 3b  t(pOther, 5000);
6ce0: 0a 20 20 20 20 7a 53 51 4c 20 3d 20 6d 70 72 69  .    zSQL = mpri
6cf0: 6e 74 66 28 0a 20 20 20 20 20 20 22 53 45 4c 45  ntf(.      "SELE
6d00: 43 54 20 63 65 78 70 69 72 65 20 46 52 4f 4d 20  CT cexpire FROM 
6d10: 75 73 65 72 22 0a 20 20 20 20 20 20 22 20 57 48  user".      " WH
6d20: 45 52 45 20 6c 6f 67 69 6e 3d 25 51 22 0a 20 20  ERE login=%Q".  
6d30: 20 20 20 20 22 20 20 20 41 4e 44 20 69 70 61 64      "   AND ipad
6d40: 64 72 3d 25 51 22 0a 20 20 20 20 20 20 22 20 20  dr=%Q".      "  
6d50: 20 41 4e 44 20 6c 65 6e 67 74 68 28 63 61 70 29   AND length(cap)
6d60: 3e 30 22 0a 20 20 20 20 20 20 22 20 20 20 41 4e  >0".      "   AN
6d70: 44 20 6c 65 6e 67 74 68 28 70 77 29 3e 30 22 0a  D length(pw)>0".
6d80: 20 20 20 20 20 20 22 20 20 20 41 4e 44 20 63 65        "   AND ce
6d90: 78 70 69 72 65 3e 6a 75 6c 69 61 6e 64 61 79 28  xpire>julianday(
6da0: 27 6e 6f 77 27 29 22 0a 20 20 20 20 20 20 22 20  'now')".      " 
6db0: 20 20 41 4e 44 20 63 6f 6e 73 74 61 6e 74 5f 74    AND constant_t
6dc0: 69 6d 65 5f 63 6d 70 28 63 6f 6f 6b 69 65 2c 25  ime_cmp(cookie,%
6dd0: 51 29 3d 30 22 2c 0a 20 20 20 20 20 20 7a 4c 6f  Q)=0",.      zLo
6de0: 67 69 6e 2c 20 7a 52 65 6d 6f 74 65 41 64 64 72  gin, zRemoteAddr
6df0: 2c 20 7a 48 61 73 68 0a 20 20 20 20 29 3b 0a 20  , zHash.    );. 
6e00: 20 20 20 70 53 74 6d 74 20 3d 20 30 3b 0a 20 20     pStmt = 0;.  
6e10: 20 20 72 63 20 3d 20 73 71 6c 69 74 65 33 5f 70    rc = sqlite3_p
6e20: 72 65 70 61 72 65 5f 76 32 28 70 4f 74 68 65 72  repare_v2(pOther
6e30: 2c 20 7a 53 51 4c 2c 20 2d 31 2c 20 26 70 53 74  , zSQL, -1, &pSt
6e40: 6d 74 2c 20 30 29 3b 0a 20 20 20 20 69 66 28 20  mt, 0);.    if( 
6e50: 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 26 26  rc==SQLITE_OK &&
6e60: 20 73 71 6c 69 74 65 33 5f 73 74 65 70 28 70 53   sqlite3_step(pS
6e70: 74 6d 74 29 3d 3d 53 51 4c 49 54 45 5f 52 4f 57  tmt)==SQLITE_ROW
6e80: 20 29 7b 0a 20 20 20 20 20 20 64 62 5f 6d 75 6c   ){.      db_mul
6e90: 74 69 5f 65 78 65 63 28 0a 20 20 20 20 20 20 20  ti_exec(.       
6ea0: 20 22 55 50 44 41 54 45 20 75 73 65 72 20 53 45   "UPDATE user SE
6eb0: 54 20 63 6f 6f 6b 69 65 3d 25 51 2c 20 69 70 61  T cookie=%Q, ipa
6ec0: 64 64 72 3d 25 51 2c 20 63 65 78 70 69 72 65 3d  ddr=%Q, cexpire=
6ed0: 25 2e 31 37 67 22 0a 20 20 20 20 20 20 20 20 22  %.17g".        "
6ee0: 20 57 48 45 52 45 20 6c 6f 67 69 6e 3d 25 51 22   WHERE login=%Q"
6ef0: 2c 0a 20 20 20 20 20 20 20 20 7a 48 61 73 68 2c  ,.        zHash,
6f00: 20 7a 52 65 6d 6f 74 65 41 64 64 72 2c 0a 20 20   zRemoteAddr,.  
6f10: 20 20 20 20 20 20 73 71 6c 69 74 65 33 5f 63 6f        sqlite3_co
6f20: 6c 75 6d 6e 5f 64 6f 75 62 6c 65 28 70 53 74 6d  lumn_double(pStm
6f30: 74 2c 20 30 29 2c 20 7a 4c 6f 67 69 6e 0a 20 20  t, 0), zLogin.  
6f40: 20 20 20 20 29 3b 0a 20 20 20 20 20 20 6e 58 66      );.      nXf
6f50: 65 72 2b 2b 3b 0a 20 20 20 20 7d 0a 20 20 20 20  er++;.    }.    
6f60: 73 71 6c 69 74 65 33 5f 66 69 6e 61 6c 69 7a 65  sqlite3_finalize
6f70: 28 70 53 74 6d 74 29 3b 0a 20 20 7d 0a 20 20 73  (pStmt);.  }.  s
6f80: 71 6c 69 74 65 33 5f 63 6c 6f 73 65 28 70 4f 74  qlite3_close(pOt
6f90: 68 65 72 29 3b 0a 20 20 66 6f 73 73 69 6c 5f 66  her);.  fossil_f
6fa0: 72 65 65 28 7a 4f 74 68 65 72 52 65 70 6f 29 3b  ree(zOtherRepo);
6fb0: 0a 20 20 72 65 74 75 72 6e 20 6e 58 66 65 72 3b  .  return nXfer;
6fc0: 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 52 65 74 75 72 6e  .}../*.** Return
6fd0: 20 54 52 55 45 20 69 66 20 7a 4c 6f 67 69 6e 20   TRUE if zLogin 
6fe0: 69 73 20 6f 6e 65 20 6f 66 20 74 68 65 20 73 70  is one of the sp
6ff0: 65 63 69 61 6c 20 75 73 65 72 6e 61 6d 65 73 0a  ecial usernames.
7000: 2a 2f 0a 69 6e 74 20 6c 6f 67 69 6e 5f 69 73 5f  */.int login_is_
7010: 73 70 65 63 69 61 6c 28 63 6f 6e 73 74 20 63 68  special(const ch
7020: 61 72 20 2a 7a 4c 6f 67 69 6e 29 7b 0a 20 20 69  ar *zLogin){.  i
7030: 66 28 20 66 6f 73 73 69 6c 5f 73 74 72 63 6d 70  f( fossil_strcmp
7040: 28 7a 4c 6f 67 69 6e 2c 20 22 61 6e 6f 6e 79 6d  (zLogin, "anonym
7050: 6f 75 73 22 29 3d 3d 30 20 29 20 72 65 74 75 72  ous")==0 ) retur
7060: 6e 20 31 3b 0a 20 20 69 66 28 20 66 6f 73 73 69  n 1;.  if( fossi
7070: 6c 5f 73 74 72 63 6d 70 28 7a 4c 6f 67 69 6e 2c  l_strcmp(zLogin,
7080: 20 22 6e 6f 62 6f 64 79 22 29 3d 3d 30 20 29 20   "nobody")==0 ) 
7090: 72 65 74 75 72 6e 20 31 3b 0a 20 20 69 66 28 20  return 1;.  if( 
70a0: 66 6f 73 73 69 6c 5f 73 74 72 63 6d 70 28 7a 4c  fossil_strcmp(zL
70b0: 6f 67 69 6e 2c 20 22 64 65 76 65 6c 6f 70 65 72  ogin, "developer
70c0: 22 29 3d 3d 30 20 29 20 72 65 74 75 72 6e 20 31  ")==0 ) return 1
70d0: 3b 0a 20 20 69 66 28 20 66 6f 73 73 69 6c 5f 73  ;.  if( fossil_s
70e0: 74 72 63 6d 70 28 7a 4c 6f 67 69 6e 2c 20 22 72  trcmp(zLogin, "r
70f0: 65 61 64 65 72 22 29 3d 3d 30 20 29 20 72 65 74  eader")==0 ) ret
7100: 75 72 6e 20 31 3b 0a 20 20 72 65 74 75 72 6e 20  urn 1;.  return 
7110: 30 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 4c 6f 6f 6b  0;.}../*.** Look
7120: 75 70 20 74 68 65 20 75 69 64 20 66 6f 72 20 61  up the uid for a
7130: 20 6e 6f 6e 2d 62 75 69 6c 74 2d 69 6e 20 75 73   non-built-in us
7140: 65 72 20 77 69 74 68 20 7a 4c 6f 67 69 6e 20 61  er with zLogin a
7150: 6e 64 20 7a 43 6f 6f 6b 69 65 20 61 6e 64 0a 2a  nd zCookie and.*
7160: 2a 20 7a 52 65 6d 6f 74 65 41 64 64 72 2e 20 20  * zRemoteAddr.  
7170: 52 65 74 75 72 6e 20 30 20 69 66 20 6e 6f 74 20  Return 0 if not 
7180: 66 6f 75 6e 64 2e 0a 2a 2a 0a 2a 2a 20 4e 6f 74  found..**.** Not
7190: 65 20 74 68 61 74 20 74 68 69 73 20 6f 6e 6c 79  e that this only
71a0: 20 73 65 61 72 63 68 65 73 20 66 6f 72 20 6c 6f   searches for lo
71b0: 67 67 65 64 2d 69 6e 20 65 6e 74 72 69 65 73 20  gged-in entries 
71c0: 77 69 74 68 20 6d 61 74 63 68 69 6e 67 0a 2a 2a  with matching.**
71d0: 20 7a 43 6f 6f 6b 69 65 20 28 64 62 3a 20 75 73   zCookie (db: us
71e0: 65 72 2e 63 6f 6f 6b 69 65 29 20 61 6e 64 20 7a  er.cookie) and z
71f0: 52 65 6d 6f 74 65 41 64 64 72 20 28 64 62 3a 20  RemoteAddr (db: 
7200: 75 73 65 72 2e 69 70 61 64 64 72 29 0a 2a 2a 20  user.ipaddr).** 
7210: 65 6e 74 72 69 65 73 2e 0a 2a 2f 0a 73 74 61 74  entries..*/.stat
7220: 69 63 20 69 6e 74 20 6c 6f 67 69 6e 5f 66 69 6e  ic int login_fin
7230: 64 5f 75 73 65 72 28 0a 20 20 63 6f 6e 73 74 20  d_user(.  const 
7240: 63 68 61 72 20 2a 7a 4c 6f 67 69 6e 2c 20 20 20  char *zLogin,   
7250: 20 20 20 20 20 20 20 20 20 2f 2a 20 55 73 65 72           /* User
7260: 20 6e 61 6d 65 20 2a 2f 0a 20 20 63 6f 6e 73 74   name */.  const
7270: 20 63 68 61 72 20 2a 7a 43 6f 6f 6b 69 65 2c 20   char *zCookie, 
7280: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4c 6f 67            /* Log
7290: 69 6e 20 63 6f 6f 6b 69 65 20 76 61 6c 75 65 20  in cookie value 
72a0: 2a 2f 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20  */.  const char 
72b0: 2a 7a 52 65 6d 6f 74 65 41 64 64 72 20 20 20 20  *zRemoteAddr    
72c0: 20 20 20 20 2f 2a 20 41 62 62 72 65 76 69 61 74      /* Abbreviat
72d0: 65 64 20 49 50 20 61 64 64 72 65 73 73 20 66 6f  ed IP address fo
72e0: 72 20 76 61 6c 69 64 20 6c 6f 67 69 6e 20 2a 2f  r valid login */
72f0: 0a 29 7b 0a 20 20 69 6e 74 20 75 69 64 3b 0a 20  .){.  int uid;. 
7300: 20 69 66 28 20 6c 6f 67 69 6e 5f 69 73 5f 73 70   if( login_is_sp
7310: 65 63 69 61 6c 28 7a 4c 6f 67 69 6e 29 20 29 20  ecial(zLogin) ) 
7320: 72 65 74 75 72 6e 20 30 3b 0a 20 20 75 69 64 20  return 0;.  uid 
7330: 3d 20 64 62 5f 69 6e 74 28 30 2c 0a 20 20 20 20  = db_int(0,.    
7340: 22 53 45 4c 45 43 54 20 75 69 64 20 46 52 4f 4d  "SELECT uid FROM
7350: 20 75 73 65 72 22 0a 20 20 20 20 22 20 57 48 45   user".    " WHE
7360: 52 45 20 6c 6f 67 69 6e 3d 25 51 22 0a 20 20 20  RE login=%Q".   
7370: 20 22 20 20 20 41 4e 44 20 69 70 61 64 64 72 3d   "   AND ipaddr=
7380: 25 51 22 0a 20 20 20 20 22 20 20 20 41 4e 44 20  %Q".    "   AND 
7390: 63 65 78 70 69 72 65 3e 6a 75 6c 69 61 6e 64 61  cexpire>julianda
73a0: 79 28 27 6e 6f 77 27 29 22 0a 20 20 20 20 22 20  y('now')".    " 
73b0: 20 20 41 4e 44 20 6c 65 6e 67 74 68 28 63 61 70    AND length(cap
73c0: 29 3e 30 22 0a 20 20 20 20 22 20 20 20 41 4e 44  )>0".    "   AND
73d0: 20 6c 65 6e 67 74 68 28 70 77 29 3e 30 22 0a 20   length(pw)>0". 
73e0: 20 20 20 22 20 20 20 41 4e 44 20 63 6f 6e 73 74     "   AND const
73f0: 61 6e 74 5f 74 69 6d 65 5f 63 6d 70 28 63 6f 6f  ant_time_cmp(coo
7400: 6b 69 65 2c 25 51 29 3d 30 22 2c 0a 20 20 20 20  kie,%Q)=0",.    
7410: 7a 4c 6f 67 69 6e 2c 20 7a 52 65 6d 6f 74 65 41  zLogin, zRemoteA
7420: 64 64 72 2c 20 7a 43 6f 6f 6b 69 65 0a 20 20 29  ddr, zCookie.  )
7430: 3b 0a 20 20 72 65 74 75 72 6e 20 75 69 64 3b 0a  ;.  return uid;.
7440: 7d 0a 0a 2f 2a 0a 2a 2a 20 52 65 74 75 72 6e 20  }../*.** Return 
7450: 74 72 75 65 20 69 66 20 69 74 20 69 73 20 61 70  true if it is ap
7460: 70 72 6f 70 72 69 61 74 65 20 74 6f 20 72 65 64  propriate to red
7470: 69 72 65 63 74 20 6c 6f 67 69 6e 20 72 65 71 75  irect login requ
7480: 65 73 74 73 20 74 6f 20 48 54 54 50 53 2e 0a 2a  ests to HTTPS..*
7490: 2a 0a 2a 2a 20 52 65 64 69 72 65 63 74 20 74 6f  *.** Redirect to
74a0: 20 68 74 74 70 73 20 69 73 20 61 70 70 72 6f 70   https is approp
74b0: 72 69 61 74 65 20 69 66 20 61 6c 6c 20 6f 66 20  riate if all of 
74c0: 74 68 65 20 61 62 6f 76 65 20 61 72 65 20 74 72  the above are tr
74d0: 75 65 3a 0a 2a 2a 20 20 20 20 28 31 29 20 54 68  ue:.**    (1) Th
74e0: 65 20 72 65 64 69 72 65 63 74 2d 74 6f 2d 68 74  e redirect-to-ht
74f0: 74 70 73 20 66 6c 61 67 20 69 73 20 73 65 74 0a  tps flag is set.
7500: 2a 2a 20 20 20 20 28 32 29 20 54 68 65 20 63 75  **    (2) The cu
7510: 72 72 65 6e 74 20 63 6f 6e 6e 65 63 74 69 6f 6e  rrent connection
7520: 20 69 73 20 68 74 74 70 2c 20 6e 6f 74 20 68 74   is http, not ht
7530: 74 70 73 20 6f 72 20 73 73 68 0a 2a 2a 20 20 20  tps or ssh.**   
7540: 20 28 33 29 20 54 68 65 20 73 73 6c 4e 6f 74 41   (3) The sslNotA
7550: 76 61 69 6c 61 62 6c 65 20 66 6c 61 67 20 69 73  vailable flag is
7560: 20 63 6c 65 61 72 0a 2a 2f 0a 69 6e 74 20 6c 6f   clear.*/.int lo
7570: 67 69 6e 5f 77 61 6e 74 73 5f 68 74 74 70 73 5f  gin_wants_https_
7580: 72 65 64 69 72 65 63 74 28 76 6f 69 64 29 7b 0a  redirect(void){.
7590: 20 20 69 66 28 20 67 2e 73 73 6c 4e 6f 74 41 76    if( g.sslNotAv
75a0: 61 69 6c 61 62 6c 65 20 29 20 72 65 74 75 72 6e  ailable ) return
75b0: 20 30 3b 0a 20 20 69 66 28 20 64 62 5f 67 65 74   0;.  if( db_get
75c0: 5f 62 6f 6f 6c 65 61 6e 28 22 72 65 64 69 72 65  _boolean("redire
75d0: 63 74 2d 74 6f 2d 68 74 74 70 73 22 2c 30 29 3d  ct-to-https",0)=
75e0: 3d 30 20 29 20 72 65 74 75 72 6e 20 30 3b 0a 20  =0 ) return 0;. 
75f0: 20 69 66 28 20 50 28 22 48 54 54 50 53 22 29 21   if( P("HTTPS")!
7600: 3d 30 20 29 20 72 65 74 75 72 6e 20 30 3b 0a 20  =0 ) return 0;. 
7610: 20 72 65 74 75 72 6e 20 31 3b 0a 7d 0a 0a 0a 2f   return 1;.}.../
7620: 2a 0a 2a 2a 20 41 74 74 65 6d 70 74 20 74 6f 20  *.** Attempt to 
7630: 75 73 65 20 42 61 73 69 63 20 41 75 74 68 65 6e  use Basic Authen
7640: 74 69 63 61 74 69 6f 6e 20 74 6f 20 65 73 74 61  tication to esta
7650: 62 6c 69 73 68 20 74 68 65 20 75 73 65 72 2e 20  blish the user. 
7660: 20 52 65 74 75 72 6e 20 74 68 65 0a 2a 2a 20 28   Return the.** (
7670: 6e 6f 6e 2d 7a 65 72 6f 29 20 75 69 64 20 69 66  non-zero) uid if
7680: 20 73 75 63 63 65 73 73 66 75 6c 2e 20 20 52 65   successful.  Re
7690: 74 75 72 6e 20 30 20 69 66 20 69 74 20 64 6f 65  turn 0 if it doe
76a0: 73 20 6e 6f 74 20 77 6f 72 6b 2e 0a 2a 2f 0a 73  s not work..*/.s
76b0: 74 61 74 69 63 20 69 6e 74 20 6c 6f 67 69 63 5f  tatic int logic_
76c0: 62 61 73 69 63 5f 61 75 74 68 65 6e 74 69 63 61  basic_authentica
76d0: 74 69 6f 6e 28 63 6f 6e 73 74 20 63 68 61 72 20  tion(const char 
76e0: 2a 7a 49 70 41 64 64 72 29 7b 0a 20 20 63 6f 6e  *zIpAddr){.  con
76f0: 73 74 20 63 68 61 72 20 2a 7a 41 75 74 68 20 3d  st char *zAuth =
7700: 20 50 44 28 22 48 54 54 50 5f 41 55 54 48 4f 52   PD("HTTP_AUTHOR
7710: 49 5a 41 54 49 4f 4e 22 2c 20 30 29 3b 0a 20 20  IZATION", 0);.  
7720: 69 6e 74 20 69 3b 0a 20 20 69 6e 74 20 75 69 64  int i;.  int uid
7730: 20 3d 20 30 3b 0a 20 20 69 6e 74 20 6e 44 65 63   = 0;.  int nDec
7740: 6f 64 65 20 3d 20 30 3b 0a 20 20 63 68 61 72 20  ode = 0;.  char 
7750: 2a 7a 44 65 63 6f 64 65 20 3d 20 30 3b 0a 20 20  *zDecode = 0;.  
7760: 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 55 73 65  const char *zUse
7770: 72 6e 61 6d 65 20 3d 20 30 3b 0a 20 20 63 6f 6e  rname = 0;.  con
7780: 73 74 20 63 68 61 72 20 2a 7a 50 61 73 73 77 64  st char *zPasswd
7790: 20 3d 20 30 3b 0a 0a 20 20 69 66 28 20 7a 41 75   = 0;..  if( zAu
77a0: 74 68 3d 3d 30 20 29 20 72 65 74 75 72 6e 20 30  th==0 ) return 0
77b0: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ;               
77c0: 20 20 20 20 20 2f 2a 20 46 61 69 6c 3a 20 4e 6f       /* Fail: No
77d0: 20 41 75 74 68 65 6e 74 69 63 61 74 69 6f 6e 3a   Authentication:
77e0: 20 68 65 61 64 65 72 20 2a 2f 0a 20 20 77 68 69   header */.  whi
77f0: 6c 65 28 20 66 6f 73 73 69 6c 5f 69 73 73 70 61  le( fossil_isspa
7800: 63 65 28 7a 41 75 74 68 5b 30 5d 29 20 29 20 7a  ce(zAuth[0]) ) z
7810: 41 75 74 68 2b 2b 3b 20 20 2f 2a 20 53 6b 69 70  Auth++;  /* Skip
7820: 20 6c 65 61 64 69 6e 67 20 77 68 69 74 65 73 70   leading whitesp
7830: 61 63 65 20 2a 2f 0a 20 20 69 66 28 20 73 74 72  ace */.  if( str
7840: 6e 63 6d 70 28 7a 41 75 74 68 2c 20 22 42 61 73  ncmp(zAuth, "Bas
7850: 69 63 20 22 2c 20 36 29 21 3d 30 20 29 20 72 65  ic ", 6)!=0 ) re
7860: 74 75 72 6e 20 30 3b 20 20 2f 2a 20 46 61 69 6c  turn 0;  /* Fail
7870: 3a 20 4e 6f 74 20 42 61 73 69 63 20 41 75 74 68  : Not Basic Auth
7880: 65 6e 74 69 63 61 74 69 6f 6e 20 2a 2f 0a 0a 20  entication */.. 
7890: 20 2f 2a 20 50 61 72 73 65 20 6f 75 74 20 74 68   /* Parse out th
78a0: 65 20 75 73 65 72 6e 61 6d 65 20 61 6e 64 20 70  e username and p
78b0: 61 73 73 77 6f 72 64 2c 20 73 65 70 61 72 61 74  assword, separat
78c0: 65 64 20 62 79 20 61 20 22 3a 22 20 2a 2f 0a 20  ed by a ":" */. 
78d0: 20 7a 41 75 74 68 20 2b 3d 20 36 3b 0a 20 20 77   zAuth += 6;.  w
78e0: 68 69 6c 65 28 20 66 6f 73 73 69 6c 5f 69 73 73  hile( fossil_iss
78f0: 70 61 63 65 28 7a 41 75 74 68 5b 30 5d 29 20 29  pace(zAuth[0]) )
7900: 20 7a 41 75 74 68 2b 2b 3b 0a 20 20 7a 44 65 63   zAuth++;.  zDec
7910: 6f 64 65 20 3d 20 64 65 63 6f 64 65 36 34 28 7a  ode = decode64(z
7920: 41 75 74 68 2c 20 26 6e 44 65 63 6f 64 65 29 3b  Auth, &nDecode);
7930: 0a 0a 20 20 66 6f 72 28 69 3d 30 3b 20 7a 44 65  ..  for(i=0; zDe
7940: 63 6f 64 65 5b 69 5d 20 26 26 20 7a 44 65 63 6f  code[i] && zDeco
7950: 64 65 5b 69 5d 21 3d 27 3a 27 3b 20 69 2b 2b 29  de[i]!=':'; i++)
7960: 7b 7d 0a 20 20 69 66 28 20 7a 44 65 63 6f 64 65  {}.  if( zDecode
7970: 5b 69 5d 20 29 7b 0a 20 20 20 20 7a 44 65 63 6f  [i] ){.    zDeco
7980: 64 65 5b 69 5d 20 3d 20 30 3b 0a 20 20 20 20 7a  de[i] = 0;.    z
7990: 55 73 65 72 6e 61 6d 65 20 3d 20 7a 44 65 63 6f  Username = zDeco
79a0: 64 65 3b 0a 20 20 20 20 7a 50 61 73 73 77 64 20  de;.    zPasswd 
79b0: 3d 20 26 7a 44 65 63 6f 64 65 5b 69 2b 31 5d 3b  = &zDecode[i+1];
79c0: 0a 0a 20 20 20 20 2f 2a 20 41 74 74 65 6d 70 74  ..    /* Attempt
79d0: 69 6e 67 20 74 6f 20 6c 6f 67 20 69 6e 20 61 73  ing to log in as
79e0: 20 74 68 65 20 75 73 65 72 20 70 72 6f 76 69 64   the user provid
79f0: 65 64 20 62 79 20 48 54 54 50 0a 20 20 20 20 2a  ed by HTTP.    *
7a00: 2a 20 62 61 73 69 63 20 61 75 74 68 0a 20 20 20  * basic auth.   
7a10: 20 2a 2f 0a 20 20 20 20 75 69 64 20 3d 20 6c 6f   */.    uid = lo
7a20: 67 69 6e 5f 73 65 61 72 63 68 5f 75 69 64 28 7a  gin_search_uid(z
7a30: 55 73 65 72 6e 61 6d 65 2c 20 7a 50 61 73 73 77  Username, zPassw
7a40: 64 29 3b 0a 20 20 20 20 69 66 28 20 75 69 64 3e  d);.    if( uid>
7a50: 30 20 29 7b 0a 20 20 20 20 20 20 72 65 63 6f 72  0 ){.      recor
7a60: 64 5f 6c 6f 67 69 6e 5f 61 74 74 65 6d 70 74 28  d_login_attempt(
7a70: 7a 55 73 65 72 6e 61 6d 65 2c 20 7a 49 70 41 64  zUsername, zIpAd
7a80: 64 72 2c 20 31 29 3b 0a 20 20 20 20 7d 65 6c 73  dr, 1);.    }els
7a90: 65 7b 0a 20 20 20 20 20 20 72 65 63 6f 72 64 5f  e{.      record_
7aa0: 6c 6f 67 69 6e 5f 61 74 74 65 6d 70 74 28 7a 55  login_attempt(zU
7ab0: 73 65 72 6e 61 6d 65 2c 20 7a 49 70 41 64 64 72  sername, zIpAddr
7ac0: 2c 20 30 29 3b 0a 0a 20 20 20 20 20 20 2f 2a 20  , 0);..      /* 
7ad0: 54 68 65 20 75 73 65 72 20 61 74 74 65 6d 70 74  The user attempt
7ae0: 65 64 20 74 6f 20 6c 6f 67 69 6e 20 73 70 65 63  ed to login spec
7af0: 69 66 69 63 61 6c 6c 79 20 77 69 74 68 20 48 54  ifically with HT
7b00: 54 50 20 62 61 73 69 63 0a 20 20 20 20 20 20 2a  TP basic.      *
7b10: 2a 20 61 75 74 68 2c 20 62 75 74 20 70 72 6f 76  * auth, but prov
7b20: 69 64 65 64 20 69 6e 76 61 6c 69 64 20 63 72 65  ided invalid cre
7b30: 64 65 6e 74 69 61 6c 73 2e 20 49 6e 66 6f 72 6d  dentials. Inform
7b40: 20 74 68 65 6d 20 6f 66 0a 20 20 20 20 20 20 2a   them of.      *
7b50: 2a 20 74 68 65 20 66 61 69 6c 65 64 20 6c 6f 67  * the failed log
7b60: 69 6e 20 61 74 74 65 6d 70 74 20 76 69 61 20 34  in attempt via 4
7b70: 30 31 2e 0a 20 20 20 20 20 20 2a 2f 0a 20 20 20  01..      */.   
7b80: 20 20 20 63 67 69 5f 73 65 74 5f 73 74 61 74 75     cgi_set_statu
7b90: 73 28 34 30 31 2c 20 22 55 6e 61 75 74 68 6f 72  s(401, "Unauthor
7ba0: 69 7a 65 64 22 29 3b 0a 20 20 20 20 20 20 63 67  ized");.      cg
7bb0: 69 5f 72 65 70 6c 79 28 29 3b 0a 20 20 20 20 20  i_reply();.     
7bc0: 20 66 6f 73 73 69 6c 5f 65 78 69 74 28 30 29 3b   fossil_exit(0);
7bd0: 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20 66 6f 73  .    }.  }.  fos
7be0: 73 69 6c 5f 66 72 65 65 28 7a 44 65 63 6f 64 65  sil_free(zDecode
7bf0: 29 3b 0a 20 20 72 65 74 75 72 6e 20 75 69 64 3b  );.  return uid;
7c00: 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20 72  .}../*.** This r
7c10: 6f 75 74 69 6e 65 20 65 78 61 6d 69 6e 65 73 20  outine examines 
7c20: 74 68 65 20 6c 6f 67 69 6e 20 63 6f 6f 6b 69 65  the login cookie
7c30: 20 74 6f 20 73 65 65 20 69 66 20 69 74 20 65 78   to see if it ex
7c40: 69 73 74 73 20 61 6e 64 0a 2a 2a 20 69 73 20 76  ists and.** is v
7c50: 61 6c 69 64 2e 20 20 49 66 20 74 68 65 20 6c 6f  alid.  If the lo
7c60: 67 69 6e 20 63 6f 6f 6b 69 65 20 63 68 65 63 6b  gin cookie check
7c70: 73 20 6f 75 74 2c 20 69 74 20 74 68 65 6e 20 73  s out, it then s
7c80: 65 74 73 20 67 6c 6f 62 61 6c 0a 2a 2a 20 76 61  ets global.** va
7c90: 72 69 61 62 6c 65 73 20 61 70 70 72 6f 70 72 69  riables appropri
7ca0: 61 74 65 6c 79 2e 0a 2a 2a 0a 2a 2a 20 20 20 20  ately..**.**    
7cb0: 67 2e 75 73 65 72 55 69 64 20 20 20 20 20 20 44  g.userUid      D
7cc0: 61 74 61 62 61 73 65 20 55 53 45 52 2e 55 49 44  atabase USER.UID
7cd0: 20 76 61 6c 75 65 2e 20 20 4d 69 67 68 74 20 62   value.  Might b
7ce0: 65 20 2d 31 20 66 6f 72 20 22 6e 6f 62 6f 64 79  e -1 for "nobody
7cf0: 22 0a 2a 2a 20 20 20 20 67 2e 7a 4c 6f 67 69 6e  ".**    g.zLogin
7d00: 20 20 20 20 20 20 20 44 61 74 61 62 61 73 65 20         Database 
7d10: 55 53 45 52 2e 4c 4f 47 49 4e 20 76 61 6c 75 65  USER.LOGIN value
7d20: 2e 20 20 4e 55 4c 4c 20 66 6f 72 20 75 73 65 72  .  NULL for user
7d30: 20 22 6e 6f 62 6f 64 79 22 0a 2a 2a 20 20 20 20   "nobody".**    
7d40: 67 2e 70 65 72 6d 20 20 20 20 20 20 20 20 20 50  g.perm         P
7d50: 65 72 6d 69 73 73 69 6f 6e 73 20 67 72 61 6e 74  ermissions grant
7d60: 65 64 20 74 6f 20 74 68 69 73 20 75 73 65 72 0a  ed to this user.
7d70: 2a 2a 20 20 20 20 67 2e 61 6e 6f 6e 20 20 20 20  **    g.anon    
7d80: 20 20 20 20 20 50 65 72 6d 69 73 73 69 6f 6e 73       Permissions
7d90: 20 74 68 61 74 20 77 6f 75 6c 64 20 62 65 20 61   that would be a
7da0: 76 61 69 6c 61 62 6c 65 20 74 6f 20 61 6e 6f 6e  vailable to anon
7db0: 79 6d 6f 75 73 0a 2a 2a 20 20 20 20 67 2e 69 73  ymous.**    g.is
7dc0: 48 75 6d 61 6e 20 20 20 20 20 20 54 72 75 65 20  Human      True 
7dd0: 69 66 20 74 68 65 20 75 73 65 72 20 69 73 20 68  if the user is h
7de0: 75 6d 61 6e 2c 20 6e 6f 74 20 61 20 73 70 69 64  uman, not a spid
7df0: 65 72 20 6f 72 20 72 6f 62 6f 74 0a 2a 2a 0a 2a  er or robot.**.*
7e00: 2f 0a 76 6f 69 64 20 6c 6f 67 69 6e 5f 63 68 65  /.void login_che
7e10: 63 6b 5f 63 72 65 64 65 6e 74 69 61 6c 73 28 76  ck_credentials(v
7e20: 6f 69 64 29 7b 0a 20 20 69 6e 74 20 75 69 64 20  oid){.  int uid 
7e30: 3d 20 30 3b 20 20 20 20 20 20 20 20 20 20 20 20  = 0;            
7e40: 20 20 20 20 20 20 2f 2a 20 55 73 65 72 20 69 64        /* User id
7e50: 20 2a 2f 0a 20 20 63 6f 6e 73 74 20 63 68 61 72   */.  const char
7e60: 20 2a 7a 43 6f 6f 6b 69 65 3b 20 20 20 20 20 20   *zCookie;      
7e70: 20 20 20 20 2f 2a 20 54 65 78 74 20 6f 66 20 74      /* Text of t
7e80: 68 65 20 6c 6f 67 69 6e 20 63 6f 6f 6b 69 65 20  he login cookie 
7e90: 2a 2f 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20  */.  const char 
7ea0: 2a 7a 49 70 41 64 64 72 3b 20 20 20 20 20 20 20  *zIpAddr;       
7eb0: 20 20 20 2f 2a 20 52 61 77 20 49 50 20 61 64 64     /* Raw IP add
7ec0: 72 65 73 73 20 6f 66 20 74 68 65 20 72 65 71 75  ress of the requ
7ed0: 65 73 74 6f 72 20 2a 2f 0a 20 20 63 68 61 72 20  estor */.  char 
7ee0: 2a 7a 52 65 6d 6f 74 65 41 64 64 72 3b 20 20 20  *zRemoteAddr;   
7ef0: 20 20 20 20 20 20 20 20 20 2f 2a 20 41 62 62 72           /* Abbr
7f00: 65 76 69 61 74 65 64 20 49 50 20 61 64 64 72 65  eviated IP addre
7f10: 73 73 20 6f 66 20 74 68 65 20 72 65 71 75 65 73  ss of the reques
7f20: 74 6f 72 20 2a 2f 0a 20 20 63 6f 6e 73 74 20 63  tor */.  const c
7f30: 68 61 72 20 2a 7a 43 61 70 20 3d 20 30 3b 20 20  har *zCap = 0;  
7f40: 20 20 20 20 20 20 20 2f 2a 20 43 61 70 61 62 69         /* Capabi
7f50: 6c 69 74 79 20 73 74 72 69 6e 67 20 2a 2f 0a 20  lity string */. 
7f60: 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 50 75   const char *zPu
7f70: 62 6c 69 63 50 61 67 65 73 20 3d 20 30 3b 20 2f  blicPages = 0; /
7f80: 2a 20 47 4c 4f 42 20 70 61 74 74 65 72 6e 73 20  * GLOB patterns 
7f90: 6f 66 20 70 75 62 6c 69 63 20 70 61 67 65 73 20  of public pages 
7fa0: 2a 2f 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20  */.  const char 
7fb0: 2a 7a 4c 6f 67 69 6e 20 3d 20 30 3b 20 20 20 20  *zLogin = 0;    
7fc0: 20 20 20 2f 2a 20 4c 6f 67 69 6e 20 75 73 65 72     /* Login user
7fd0: 20 66 6f 72 20 63 72 65 64 65 6e 74 69 61 6c 73   for credentials
7fe0: 20 2a 2f 0a 0a 20 20 2f 2a 20 4f 6e 6c 79 20 72   */..  /* Only r
7ff0: 75 6e 20 74 68 69 73 20 63 68 65 63 6b 20 6f 6e  un this check on
8000: 63 65 2e 20 20 2a 2f 0a 20 20 69 66 28 20 67 2e  ce.  */.  if( g.
8010: 75 73 65 72 55 69 64 21 3d 30 20 29 20 72 65 74  userUid!=0 ) ret
8020: 75 72 6e 3b 0a 0a 20 20 73 71 6c 69 74 65 33 5f  urn;..  sqlite3_
8030: 63 72 65 61 74 65 5f 66 75 6e 63 74 69 6f 6e 28  create_function(
8040: 67 2e 64 62 2c 20 22 63 6f 6e 73 74 61 6e 74 5f  g.db, "constant_
8050: 74 69 6d 65 5f 63 6d 70 22 2c 20 32 2c 20 53 51  time_cmp", 2, SQ
8060: 4c 49 54 45 5f 55 54 46 38 2c 20 30 2c 0a 20 20  LITE_UTF8, 0,.  
8070: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8080: 63 6f 6e 73 74 61 6e 74 5f 74 69 6d 65 5f 63 6d  constant_time_cm
8090: 70 5f 66 75 6e 63 74 69 6f 6e 2c 20 30 2c 20 30  p_function, 0, 0
80a0: 29 3b 0a 0a 20 20 2f 2a 20 49 66 20 74 68 65 20  );..  /* If the 
80b0: 48 54 54 50 20 63 6f 6e 6e 65 63 74 69 6f 6e 20  HTTP connection 
80c0: 69 73 20 63 6f 6d 69 6e 67 20 6f 76 65 72 20 31  is coming over 1
80d0: 32 37 2e 30 2e 30 2e 31 20 61 6e 64 20 69 66 0a  27.0.0.1 and if.
80e0: 20 20 2a 2a 20 6c 6f 63 61 6c 20 6c 6f 67 69 6e    ** local login
80f0: 20 69 73 20 64 69 73 61 62 6c 65 64 20 61 6e 64   is disabled and
8100: 20 69 66 20 77 65 20 61 72 65 20 75 73 69 6e 67   if we are using
8110: 20 48 54 54 50 20 61 6e 64 20 6e 6f 74 20 48 54   HTTP and not HT
8120: 54 50 53 2c 0a 20 20 2a 2a 20 74 68 65 6e 20 74  TPS,.  ** then t
8130: 68 65 72 65 20 69 73 20 6e 6f 20 6e 65 65 64 20  here is no need 
8140: 74 6f 20 63 68 65 63 6b 20 75 73 65 72 20 63 72  to check user cr
8150: 65 64 65 6e 74 69 61 6c 73 2e 0a 20 20 2a 2a 0a  edentials..  **.
8160: 20 20 2a 2a 20 54 68 69 73 20 66 65 61 74 75 72    ** This featur
8170: 65 20 61 6c 6c 6f 77 73 20 74 68 65 20 22 66 6f  e allows the "fo
8180: 73 73 69 6c 20 75 69 22 20 63 6f 6d 6d 61 6e 64  ssil ui" command
8190: 20 74 6f 20 67 69 76 65 20 74 68 65 20 75 73 65   to give the use
81a0: 72 0a 20 20 2a 2a 20 66 75 6c 6c 20 61 63 63 65  r.  ** full acce
81b0: 73 73 20 72 69 67 68 74 73 20 77 69 74 68 6f 75  ss rights withou
81c0: 74 20 68 61 76 69 6e 67 20 74 6f 20 6c 6f 67 20  t having to log 
81d0: 69 6e 2e 0a 20 20 2a 2f 0a 20 20 7a 52 65 6d 6f  in..  */.  zRemo
81e0: 74 65 41 64 64 72 20 3d 20 69 70 50 72 65 66 69  teAddr = ipPrefi
81f0: 78 28 7a 49 70 41 64 64 72 20 3d 20 50 44 28 22  x(zIpAddr = PD("
8200: 52 45 4d 4f 54 45 5f 41 44 44 52 22 2c 22 6e 69  REMOTE_ADDR","ni
8210: 6c 22 29 29 3b 0a 20 20 69 66 28 20 28 20 63 67  l"));.  if( ( cg
8220: 69 5f 69 73 5f 6c 6f 6f 70 62 61 63 6b 28 7a 49  i_is_loopback(zI
8230: 70 41 64 64 72 29 0a 20 20 20 20 20 20 20 7c 7c  pAddr).       ||
8240: 20 28 67 2e 66 53 73 68 43 6c 69 65 6e 74 20 26   (g.fSshClient &
8250: 20 43 47 49 5f 53 53 48 5f 43 4c 49 45 4e 54 29   CGI_SSH_CLIENT)
8260: 21 3d 30 20 29 0a 20 20 20 26 26 20 67 2e 75 73  !=0 ).   && g.us
8270: 65 4c 6f 63 61 6c 61 75 74 68 0a 20 20 20 26 26  eLocalauth.   &&
8280: 20 64 62 5f 67 65 74 5f 69 6e 74 28 22 6c 6f 63   db_get_int("loc
8290: 61 6c 61 75 74 68 22 2c 30 29 3d 3d 30 0a 20 20  alauth",0)==0.  
82a0: 20 26 26 20 50 28 22 48 54 54 50 53 22 29 3d 3d   && P("HTTPS")==
82b0: 30 0a 20 20 29 7b 0a 20 20 20 20 69 66 28 20 67  0.  ){.    if( g
82c0: 2e 6c 6f 63 61 6c 4f 70 65 6e 20 29 20 7a 4c 6f  .localOpen ) zLo
82d0: 67 69 6e 20 3d 20 64 62 5f 6c 67 65 74 28 22 64  gin = db_lget("d
82e0: 65 66 61 75 6c 74 2d 75 73 65 72 22 2c 30 29 3b  efault-user",0);
82f0: 0a 20 20 20 20 69 66 28 20 7a 4c 6f 67 69 6e 21  .    if( zLogin!
8300: 3d 30 20 29 7b 0a 20 20 20 20 20 20 75 69 64 20  =0 ){.      uid 
8310: 3d 20 64 62 5f 69 6e 74 28 30 2c 20 22 53 45 4c  = db_int(0, "SEL
8320: 45 43 54 20 75 69 64 20 46 52 4f 4d 20 75 73 65  ECT uid FROM use
8330: 72 20 57 48 45 52 45 20 6c 6f 67 69 6e 3d 25 51  r WHERE login=%Q
8340: 22 2c 20 7a 4c 6f 67 69 6e 29 3b 0a 20 20 20 20  ", zLogin);.    
8350: 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 75 69 64  }else{.      uid
8360: 20 3d 20 64 62 5f 69 6e 74 28 30 2c 20 22 53 45   = db_int(0, "SE
8370: 4c 45 43 54 20 75 69 64 20 46 52 4f 4d 20 75 73  LECT uid FROM us
8380: 65 72 20 57 48 45 52 45 20 63 61 70 20 4c 49 4b  er WHERE cap LIK
8390: 45 20 27 25 25 73 25 25 27 22 29 3b 0a 20 20 20  E '%%s%%'");.   
83a0: 20 7d 0a 20 20 20 20 67 2e 7a 4c 6f 67 69 6e 20   }.    g.zLogin 
83b0: 3d 20 64 62 5f 74 65 78 74 28 22 3f 22 2c 20 22  = db_text("?", "
83c0: 53 45 4c 45 43 54 20 6c 6f 67 69 6e 20 46 52 4f  SELECT login FRO
83d0: 4d 20 75 73 65 72 20 57 48 45 52 45 20 75 69 64  M user WHERE uid
83e0: 3d 25 64 22 2c 20 75 69 64 29 3b 0a 20 20 20 20  =%d", uid);.    
83f0: 7a 43 61 70 20 3d 20 22 73 78 22 3b 0a 20 20 20  zCap = "sx";.   
8400: 20 67 2e 6e 6f 50 73 77 64 20 3d 20 31 3b 0a 20   g.noPswd = 1;. 
8410: 20 20 20 67 2e 69 73 48 75 6d 61 6e 20 3d 20 31     g.isHuman = 1
8420: 3b 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 73 6e  ;.    sqlite3_sn
8430: 70 72 69 6e 74 66 28 73 69 7a 65 6f 66 28 67 2e  printf(sizeof(g.
8440: 7a 43 73 72 66 54 6f 6b 65 6e 29 2c 20 67 2e 7a  zCsrfToken), g.z
8450: 43 73 72 66 54 6f 6b 65 6e 2c 20 22 6c 6f 63 61  CsrfToken, "loca
8460: 6c 68 6f 73 74 22 29 3b 0a 20 20 7d 0a 0a 20 20  lhost");.  }..  
8470: 2f 2a 20 43 68 65 63 6b 20 74 68 65 20 6c 6f 67  /* Check the log
8480: 69 6e 20 63 6f 6f 6b 69 65 20 74 6f 20 73 65 65  in cookie to see
8490: 20 69 66 20 69 74 20 6d 61 74 63 68 65 73 20 61   if it matches a
84a0: 20 6b 6e 6f 77 6e 20 76 61 6c 69 64 20 75 73 65   known valid use
84b0: 72 2e 0a 20 20 2a 2f 0a 20 20 69 66 28 20 75 69  r..  */.  if( ui
84c0: 64 3d 3d 30 20 26 26 20 28 7a 43 6f 6f 6b 69 65  d==0 && (zCookie
84d0: 20 3d 20 50 28 6c 6f 67 69 6e 5f 63 6f 6f 6b 69   = P(login_cooki
84e0: 65 5f 6e 61 6d 65 28 29 29 29 21 3d 30 20 29 7b  e_name()))!=0 ){
84f0: 0a 20 20 20 20 2f 2a 20 50 61 72 73 65 20 74 68  .    /* Parse th
8500: 65 20 63 6f 6f 6b 69 65 20 76 61 6c 75 65 20 75  e cookie value u
8510: 70 20 69 6e 74 6f 20 48 41 53 48 2f 41 52 47 2f  p into HASH/ARG/
8520: 55 53 45 52 20 2a 2f 0a 20 20 20 20 63 68 61 72  USER */.    char
8530: 20 2a 7a 48 61 73 68 20 3d 20 66 6f 73 73 69 6c   *zHash = fossil
8540: 5f 73 74 72 64 75 70 28 7a 43 6f 6f 6b 69 65 29  _strdup(zCookie)
8550: 3b 0a 20 20 20 20 63 68 61 72 20 2a 7a 41 72 67  ;.    char *zArg
8560: 20 3d 20 30 3b 0a 20 20 20 20 63 68 61 72 20 2a   = 0;.    char *
8570: 7a 55 73 65 72 20 3d 20 30 3b 0a 20 20 20 20 69  zUser = 0;.    i
8580: 6e 74 20 69 2c 20 63 3b 0a 20 20 20 20 66 6f 72  nt i, c;.    for
8590: 28 69 3d 30 3b 20 28 63 20 3d 20 7a 48 61 73 68  (i=0; (c = zHash
85a0: 5b 69 5d 29 21 3d 30 3b 20 69 2b 2b 29 7b 0a 20  [i])!=0; i++){. 
85b0: 20 20 20 20 20 69 66 28 20 63 3d 3d 27 2f 27 20       if( c=='/' 
85c0: 29 7b 0a 20 20 20 20 20 20 20 20 7a 48 61 73 68  ){.        zHash
85d0: 5b 69 2b 2b 5d 20 3d 20 30 3b 0a 20 20 20 20 20  [i++] = 0;.     
85e0: 20 20 20 69 66 28 20 7a 41 72 67 3d 3d 30 20 29     if( zArg==0 )
85f0: 7b 0a 20 20 20 20 20 20 20 20 20 20 7a 41 72 67  {.          zArg
8600: 20 3d 20 26 7a 48 61 73 68 5b 69 5d 3b 0a 20 20   = &zHash[i];.  
8610: 20 20 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20        }else{.   
8620: 20 20 20 20 20 20 20 7a 55 73 65 72 20 3d 20 26         zUser = &
8630: 7a 48 61 73 68 5b 69 5d 3b 0a 20 20 20 20 20 20  zHash[i];.      
8640: 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20      break;.     
8650: 20 20 20 7d 0a 20 20 20 20 20 20 7d 0a 20 20 20     }.      }.   
8660: 20 7d 0a 20 20 20 20 69 66 28 20 7a 55 73 65 72   }.    if( zUser
8670: 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 2f 2a 20  ==0 ){.      /* 
8680: 49 6e 76 61 6c 69 64 20 63 6f 6f 6b 69 65 20 2a  Invalid cookie *
8690: 2f 0a 20 20 20 20 7d 65 6c 73 65 20 69 66 28 20  /.    }else if( 
86a0: 66 6f 73 73 69 6c 5f 73 74 72 63 6d 70 28 7a 55  fossil_strcmp(zU
86b0: 73 65 72 2c 20 22 61 6e 6f 6e 79 6d 6f 75 73 22  ser, "anonymous"
86c0: 29 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 2f 2a  )==0 ){.      /*
86d0: 20 43 6f 6f 6b 69 65 73 20 6f 66 20 74 68 65 20   Cookies of the 
86e0: 66 6f 72 6d 20 22 48 41 53 48 2f 54 49 4d 45 2f  form "HASH/TIME/
86f0: 61 6e 6f 6e 79 6d 6f 75 73 22 2e 20 20 54 68 65  anonymous".  The
8700: 20 54 49 4d 45 20 6d 75 73 74 20 6e 6f 74 20 62   TIME must not b
8710: 65 0a 20 20 20 20 20 20 2a 2a 20 74 6f 6f 20 6f  e.      ** too o
8720: 6c 64 20 61 6e 64 20 74 68 65 20 73 68 61 31 20  ld and the sha1 
8730: 68 61 73 68 20 6f 66 20 54 49 4d 45 2f 49 50 41  hash of TIME/IPA
8740: 44 44 52 2f 53 45 43 52 45 54 20 6d 75 73 74 20  DDR/SECRET must 
8750: 6d 61 74 63 68 20 48 41 53 48 2e 0a 20 20 20 20  match HASH..    
8760: 20 20 2a 2a 20 53 45 43 52 45 54 20 69 73 20 74    ** SECRET is t
8770: 68 65 20 22 63 61 70 74 63 68 61 2d 73 65 63 72  he "captcha-secr
8780: 65 74 22 20 76 61 6c 75 65 20 69 6e 20 74 68 65  et" value in the
8790: 20 72 65 70 6f 73 69 74 6f 72 79 2e 0a 20 20 20   repository..   
87a0: 20 20 20 2a 2f 0a 20 20 20 20 20 20 64 6f 75 62     */.      doub
87b0: 6c 65 20 72 54 69 6d 65 20 3d 20 61 74 6f 66 28  le rTime = atof(
87c0: 7a 41 72 67 29 3b 0a 20 20 20 20 20 20 42 6c 6f  zArg);.      Blo
87d0: 62 20 62 3b 0a 20 20 20 20 20 20 62 6c 6f 62 5f  b b;.      blob_
87e0: 7a 65 72 6f 28 26 62 29 3b 0a 20 20 20 20 20 20  zero(&b);.      
87f0: 62 6c 6f 62 5f 61 70 70 65 6e 64 66 28 26 62 2c  blob_appendf(&b,
8800: 20 22 25 73 2f 25 73 2f 25 73 22 2c 0a 20 20 20   "%s/%s/%s",.   
8810: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
8820: 7a 41 72 67 2c 20 7a 52 65 6d 6f 74 65 41 64 64  zArg, zRemoteAdd
8830: 72 2c 20 64 62 5f 67 65 74 28 22 63 61 70 74 63  r, db_get("captc
8840: 68 61 2d 73 65 63 72 65 74 22 2c 22 22 29 29 3b  ha-secret",""));
8850: 0a 20 20 20 20 20 20 73 68 61 31 73 75 6d 5f 62  .      sha1sum_b
8860: 6c 6f 62 28 26 62 2c 20 26 62 29 3b 0a 20 20 20  lob(&b, &b);.   
8870: 20 20 20 69 66 28 20 66 6f 73 73 69 6c 5f 73 74     if( fossil_st
8880: 72 63 6d 70 28 7a 48 61 73 68 2c 20 62 6c 6f 62  rcmp(zHash, blob
8890: 5f 73 74 72 28 26 62 29 29 3d 3d 30 20 29 7b 0a  _str(&b))==0 ){.
88a0: 20 20 20 20 20 20 20 20 75 69 64 20 3d 20 64 62          uid = db
88b0: 5f 69 6e 74 28 30 2c 0a 20 20 20 20 20 20 20 20  _int(0,.        
88c0: 20 20 20 20 22 53 45 4c 45 43 54 20 75 69 64 20      "SELECT uid 
88d0: 46 52 4f 4d 20 75 73 65 72 20 57 48 45 52 45 20  FROM user WHERE 
88e0: 6c 6f 67 69 6e 3d 27 61 6e 6f 6e 79 6d 6f 75 73  login='anonymous
88f0: 27 22 0a 20 20 20 20 20 20 20 20 20 20 20 20 22  '".            "
8900: 20 41 4e 44 20 6c 65 6e 67 74 68 28 63 61 70 29   AND length(cap)
8910: 3e 30 22 0a 20 20 20 20 20 20 20 20 20 20 20 20  >0".            
8920: 22 20 41 4e 44 20 6c 65 6e 67 74 68 28 70 77 29  " AND length(pw)
8930: 3e 30 22 0a 20 20 20 20 20 20 20 20 20 20 20 20  >0".            
8940: 22 20 41 4e 44 20 25 2e 31 37 67 2b 30 2e 32 35  " AND %.17g+0.25
8950: 3e 6a 75 6c 69 61 6e 64 61 79 28 27 6e 6f 77 27  >julianday('now'
8960: 29 22 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20  )",.            
8970: 72 54 69 6d 65 0a 20 20 20 20 20 20 20 20 29 3b  rTime.        );
8980: 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 62  .      }.      b
8990: 6c 6f 62 5f 72 65 73 65 74 28 26 62 29 3b 0a 20  lob_reset(&b);. 
89a0: 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20     }else{.      
89b0: 2f 2a 20 43 6f 6f 6b 69 65 73 20 6f 66 20 74 68  /* Cookies of th
89c0: 65 20 66 6f 72 6d 20 22 48 41 53 48 2f 43 4f 44  e form "HASH/COD
89d0: 45 2f 55 53 45 52 22 2e 20 20 53 65 61 72 63 68  E/USER".  Search
89e0: 20 66 69 72 73 74 20 69 6e 20 74 68 65 0a 20 20   first in the.  
89f0: 20 20 20 20 2a 2a 20 6c 6f 63 61 6c 20 75 73 65      ** local use
8a00: 72 20 74 61 62 6c 65 2c 20 74 68 65 6e 20 74 68  r table, then th
8a10: 65 20 75 73 65 72 20 74 61 62 6c 65 20 66 6f 72  e user table for
8a20: 20 70 72 6f 6a 65 63 74 20 43 4f 44 45 20 69 66   project CODE if
8a30: 20 77 65 0a 20 20 20 20 20 20 2a 2a 20 61 72 65   we.      ** are
8a40: 20 70 61 72 74 20 6f 66 20 61 20 6c 6f 67 69 6e   part of a login
8a50: 2d 67 72 6f 75 70 2e 0a 20 20 20 20 20 20 2a 2f  -group..      */
8a60: 0a 20 20 20 20 20 20 75 69 64 20 3d 20 6c 6f 67  .      uid = log
8a70: 69 6e 5f 66 69 6e 64 5f 75 73 65 72 28 7a 55 73  in_find_user(zUs
8a80: 65 72 2c 20 7a 48 61 73 68 2c 20 7a 52 65 6d 6f  er, zHash, zRemo
8a90: 74 65 41 64 64 72 29 3b 0a 20 20 20 20 20 20 69  teAddr);.      i
8aa0: 66 28 20 75 69 64 3d 3d 30 20 26 26 20 6c 6f 67  f( uid==0 && log
8ab0: 69 6e 5f 74 72 61 6e 73 66 65 72 5f 63 72 65 64  in_transfer_cred
8ac0: 65 6e 74 69 61 6c 73 28 7a 55 73 65 72 2c 7a 41  entials(zUser,zA
8ad0: 72 67 2c 7a 48 61 73 68 2c 7a 52 65 6d 6f 74 65  rg,zHash,zRemote
8ae0: 41 64 64 72 29 20 29 7b 0a 20 20 20 20 20 20 20  Addr) ){.       
8af0: 20 75 69 64 20 3d 20 6c 6f 67 69 6e 5f 66 69 6e   uid = login_fin
8b00: 64 5f 75 73 65 72 28 7a 55 73 65 72 2c 20 7a 48  d_user(zUser, zH
8b10: 61 73 68 2c 20 7a 52 65 6d 6f 74 65 41 64 64 72  ash, zRemoteAddr
8b20: 29 3b 0a 20 20 20 20 20 20 20 20 69 66 28 20 75  );.        if( u
8b30: 69 64 20 29 20 72 65 63 6f 72 64 5f 6c 6f 67 69  id ) record_logi
8b40: 6e 5f 61 74 74 65 6d 70 74 28 7a 55 73 65 72 2c  n_attempt(zUser,
8b50: 20 7a 49 70 41 64 64 72 2c 20 31 29 3b 0a 20 20   zIpAddr, 1);.  
8b60: 20 20 20 20 7d 0a 20 20 20 20 7d 0a 20 20 20 20      }.    }.    
8b70: 73 71 6c 69 74 65 33 5f 73 6e 70 72 69 6e 74 66  sqlite3_snprintf
8b80: 28 73 69 7a 65 6f 66 28 67 2e 7a 43 73 72 66 54  (sizeof(g.zCsrfT
8b90: 6f 6b 65 6e 29 2c 20 67 2e 7a 43 73 72 66 54 6f  oken), g.zCsrfTo
8ba0: 6b 65 6e 2c 20 22 25 2e 31 30 73 22 2c 20 7a 48  ken, "%.10s", zH
8bb0: 61 73 68 29 3b 0a 20 20 7d 0a 0a 20 20 2f 2a 20  ash);.  }..  /* 
8bc0: 49 66 20 6e 6f 20 75 73 65 72 20 66 6f 75 6e 64  If no user found
8bd0: 20 61 6e 64 20 74 68 65 20 52 45 4d 4f 54 45 5f   and the REMOTE_
8be0: 55 53 45 52 20 65 6e 76 69 72 6f 6e 6d 65 6e 74  USER environment
8bf0: 20 76 61 72 69 61 62 6c 65 20 69 73 20 73 65 74   variable is set
8c00: 2c 0a 20 20 2a 2a 20 74 68 65 6e 20 61 63 63 65  ,.  ** then acce
8c10: 70 74 20 74 68 65 20 76 61 6c 75 65 20 6f 66 20  pt the value of 
8c20: 52 45 4d 4f 54 45 5f 55 53 45 52 20 61 73 20 74  REMOTE_USER as t
8c30: 68 65 20 75 73 65 72 2e 0a 20 20 2a 2f 0a 20 20  he user..  */.  
8c40: 69 66 28 20 75 69 64 3d 3d 30 20 29 7b 0a 20 20  if( uid==0 ){.  
8c50: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 52    const char *zR
8c60: 65 6d 6f 74 65 55 73 65 72 20 3d 20 50 28 22 52  emoteUser = P("R
8c70: 45 4d 4f 54 45 5f 55 53 45 52 22 29 3b 0a 20 20  EMOTE_USER");.  
8c80: 20 20 69 66 28 20 7a 52 65 6d 6f 74 65 55 73 65    if( zRemoteUse
8c90: 72 20 26 26 20 64 62 5f 67 65 74 5f 62 6f 6f 6c  r && db_get_bool
8ca0: 65 61 6e 28 22 72 65 6d 6f 74 65 5f 75 73 65 72  ean("remote_user
8cb0: 5f 6f 6b 22 2c 30 29 20 29 7b 0a 20 20 20 20 20  _ok",0) ){.     
8cc0: 20 75 69 64 20 3d 20 64 62 5f 69 6e 74 28 30 2c   uid = db_int(0,
8cd0: 20 22 53 45 4c 45 43 54 20 75 69 64 20 46 52 4f   "SELECT uid FRO
8ce0: 4d 20 75 73 65 72 20 57 48 45 52 45 20 6c 6f 67  M user WHERE log
8cf0: 69 6e 3d 25 51 22 0a 20 20 20 20 20 20 20 20 20  in=%Q".         
8d00: 20 20 20 20 20 20 20 20 20 20 20 20 20 22 20 41               " A
8d10: 4e 44 20 6c 65 6e 67 74 68 28 63 61 70 29 3e 30  ND length(cap)>0
8d20: 20 41 4e 44 20 6c 65 6e 67 74 68 28 70 77 29 3e   AND length(pw)>
8d30: 30 22 2c 20 7a 52 65 6d 6f 74 65 55 73 65 72 29  0", zRemoteUser)
8d40: 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 0a 20 20 2f  ;.    }.  }..  /
8d50: 2a 20 49 66 20 74 68 65 20 72 65 71 75 65 73 74  * If the request
8d60: 20 64 69 64 6e 27 74 20 70 72 6f 76 69 64 65 20   didn't provide 
8d70: 61 20 6c 6f 67 69 6e 20 63 6f 6f 6b 69 65 20 6f  a login cookie o
8d80: 72 20 74 68 65 20 6c 6f 67 69 6e 20 63 6f 6f 6b  r the login cook
8d90: 69 65 20 64 69 64 6e 27 74 0a 20 20 2a 2a 20 6d  ie didn't.  ** m
8da0: 61 74 63 68 20 61 20 6b 6e 6f 77 6e 20 76 61 6c  atch a known val
8db0: 69 64 20 75 73 65 72 2c 20 63 68 65 63 6b 20 74  id user, check t
8dc0: 68 65 20 48 54 54 50 20 22 41 75 74 68 6f 72 69  he HTTP "Authori
8dd0: 7a 61 74 69 6f 6e 22 20 68 65 61 64 65 72 20 61  zation" header a
8de0: 6e 64 0a 20 20 2a 2a 20 73 65 65 20 69 66 20 74  nd.  ** see if t
8df0: 68 6f 73 65 20 63 72 65 64 65 6e 74 69 61 6c 73  hose credentials
8e00: 20 61 72 65 20 76 61 6c 69 64 20 66 6f 72 20 61   are valid for a
8e10: 20 6b 6e 6f 77 6e 20 75 73 65 72 2e 0a 20 20 2a   known user..  *
8e20: 2f 0a 20 20 69 66 28 20 75 69 64 3d 3d 30 20 26  /.  if( uid==0 &
8e30: 26 20 64 62 5f 67 65 74 5f 62 6f 6f 6c 65 61 6e  & db_get_boolean
8e40: 28 22 68 74 74 70 5f 61 75 74 68 65 6e 74 69 63  ("http_authentic
8e50: 61 74 69 6f 6e 5f 6f 6b 22 2c 30 29 20 29 7b 0a  ation_ok",0) ){.
8e60: 20 20 20 20 75 69 64 20 3d 20 6c 6f 67 69 63 5f      uid = logic_
8e70: 62 61 73 69 63 5f 61 75 74 68 65 6e 74 69 63 61  basic_authentica
8e80: 74 69 6f 6e 28 7a 49 70 41 64 64 72 29 3b 0a 20  tion(zIpAddr);. 
8e90: 20 7d 0a 0a 20 20 2f 2a 20 49 66 20 6e 6f 20 75   }..  /* If no u
8ea0: 73 65 72 20 66 6f 75 6e 64 20 79 65 74 2c 20 74  ser found yet, t
8eb0: 72 79 20 74 6f 20 6c 6f 67 20 69 6e 20 61 73 20  ry to log in as 
8ec0: 22 6e 6f 62 6f 64 79 22 20 2a 2f 0a 20 20 69 66  "nobody" */.  if
8ed0: 28 20 75 69 64 3d 3d 30 20 29 7b 0a 20 20 20 20  ( uid==0 ){.    
8ee0: 75 69 64 20 3d 20 64 62 5f 69 6e 74 28 30 2c 20  uid = db_int(0, 
8ef0: 22 53 45 4c 45 43 54 20 75 69 64 20 46 52 4f 4d  "SELECT uid FROM
8f00: 20 75 73 65 72 20 57 48 45 52 45 20 6c 6f 67 69   user WHERE logi
8f10: 6e 3d 27 6e 6f 62 6f 64 79 27 22 29 3b 0a 20 20  n='nobody'");.  
8f20: 20 20 69 66 28 20 75 69 64 3d 3d 30 20 29 7b 0a    if( uid==0 ){.
8f30: 20 20 20 20 20 20 2f 2a 20 49 66 20 74 68 65 72        /* If ther
8f40: 65 20 69 73 20 6e 6f 20 75 73 65 72 20 22 6e 6f  e is no user "no
8f50: 62 6f 64 79 22 2c 20 74 68 65 6e 20 6d 61 6b 65  body", then make
8f60: 20 6f 6e 65 20 75 70 20 2d 20 77 69 74 68 20 6e   one up - with n
8f70: 6f 20 70 72 69 76 69 6c 65 67 65 73 20 2a 2f 0a  o privileges */.
8f80: 20 20 20 20 20 20 75 69 64 20 3d 20 2d 31 3b 0a        uid = -1;.
8f90: 20 20 20 20 20 20 7a 43 61 70 20 3d 20 22 22 3b        zCap = "";
8fa0: 0a 20 20 20 20 7d 0a 20 20 20 20 73 71 6c 69 74  .    }.    sqlit
8fb0: 65 33 5f 73 6e 70 72 69 6e 74 66 28 73 69 7a 65  e3_snprintf(size
8fc0: 6f 66 28 67 2e 7a 43 73 72 66 54 6f 6b 65 6e 29  of(g.zCsrfToken)
8fd0: 2c 20 67 2e 7a 43 73 72 66 54 6f 6b 65 6e 2c 20  , g.zCsrfToken, 
8fe0: 22 6e 6f 6e 65 22 29 3b 0a 20 20 7d 0a 0a 20 20  "none");.  }..  
8ff0: 2f 2a 20 41 74 20 74 68 69 73 20 70 6f 69 6e 74  /* At this point
9000: 2c 20 77 65 20 6b 6e 6f 77 20 74 68 61 74 20 75  , we know that u
9010: 69 64 21 3d 30 2e 20 20 46 69 6e 64 20 74 68 65  id!=0.  Find the
9020: 20 70 72 69 76 69 6c 65 67 65 73 20 61 73 73 6f   privileges asso
9030: 63 69 61 74 65 64 0a 20 20 2a 2a 20 77 69 74 68  ciated.  ** with
9040: 20 75 73 65 72 20 75 69 64 2e 0a 20 20 2a 2f 0a   user uid..  */.
9050: 20 20 61 73 73 65 72 74 28 20 75 69 64 21 3d 30    assert( uid!=0
9060: 20 29 3b 0a 20 20 69 66 28 20 7a 43 61 70 3d 3d   );.  if( zCap==
9070: 30 20 29 7b 0a 20 20 20 20 53 74 6d 74 20 73 3b  0 ){.    Stmt s;
9080: 0a 20 20 20 20 64 62 5f 70 72 65 70 61 72 65 28  .    db_prepare(
9090: 26 73 2c 20 22 53 45 4c 45 43 54 20 6c 6f 67 69  &s, "SELECT logi
90a0: 6e 2c 20 63 61 70 20 46 52 4f 4d 20 75 73 65 72  n, cap FROM user
90b0: 20 57 48 45 52 45 20 75 69 64 3d 25 64 22 2c 20   WHERE uid=%d", 
90c0: 75 69 64 29 3b 0a 20 20 20 20 69 66 28 20 64 62  uid);.    if( db
90d0: 5f 73 74 65 70 28 26 73 29 3d 3d 53 51 4c 49 54  _step(&s)==SQLIT
90e0: 45 5f 52 4f 57 20 29 7b 0a 20 20 20 20 20 20 67  E_ROW ){.      g
90f0: 2e 7a 4c 6f 67 69 6e 20 3d 20 64 62 5f 63 6f 6c  .zLogin = db_col
9100: 75 6d 6e 5f 6d 61 6c 6c 6f 63 28 26 73 2c 20 30  umn_malloc(&s, 0
9110: 29 3b 0a 20 20 20 20 20 20 7a 43 61 70 20 3d 20  );.      zCap = 
9120: 64 62 5f 63 6f 6c 75 6d 6e 5f 6d 61 6c 6c 6f 63  db_column_malloc
9130: 28 26 73 2c 20 31 29 3b 0a 20 20 20 20 7d 0a 20  (&s, 1);.    }. 
9140: 20 20 20 64 62 5f 66 69 6e 61 6c 69 7a 65 28 26     db_finalize(&
9150: 73 29 3b 0a 20 20 20 20 69 66 28 20 7a 43 61 70  s);.    if( zCap
9160: 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 7a 43 61  ==0 ){.      zCa
9170: 70 20 3d 20 22 22 3b 0a 20 20 20 20 7d 0a 20 20  p = "";.    }.  
9180: 7d 0a 20 20 69 66 28 20 67 2e 66 48 74 74 70 54  }.  if( g.fHttpT
9190: 72 61 63 65 20 26 26 20 67 2e 7a 4c 6f 67 69 6e  race && g.zLogin
91a0: 20 29 7b 0a 20 20 20 20 66 70 72 69 6e 74 66 28   ){.    fprintf(
91b0: 73 74 64 65 72 72 2c 20 22 23 20 6c 6f 67 69 6e  stderr, "# login
91c0: 3a 20 5b 25 73 5d 20 77 69 74 68 20 63 61 70 61  : [%s] with capa
91d0: 62 69 6c 69 74 69 65 73 20 5b 25 73 5d 5c 6e 22  bilities [%s]\n"
91e0: 2c 20 67 2e 7a 4c 6f 67 69 6e 2c 20 7a 43 61 70  , g.zLogin, zCap
91f0: 29 3b 0a 20 20 7d 0a 0a 20 20 2f 2a 20 53 65 74  );.  }..  /* Set
9200: 20 74 68 65 20 67 6c 6f 62 61 6c 20 76 61 72 69   the global vari
9210: 61 62 6c 65 73 20 72 65 63 6f 72 64 69 6e 67 20  ables recording 
9220: 74 68 65 20 75 73 65 72 69 64 20 61 6e 64 20 6c  the userid and l
9230: 6f 67 69 6e 2e 20 20 54 68 65 0a 20 20 2a 2a 20  ogin.  The.  ** 
9240: 22 6e 6f 62 6f 64 79 22 20 75 73 65 72 20 69 73  "nobody" user is
9250: 20 61 20 73 70 65 63 69 61 6c 20 63 61 73 65 20   a special case 
9260: 69 6e 20 74 68 61 74 20 67 2e 7a 4c 6f 67 69 6e  in that g.zLogin
9270: 3d 3d 30 2e 0a 20 20 2a 2f 0a 20 20 67 2e 75 73  ==0..  */.  g.us
9280: 65 72 55 69 64 20 3d 20 75 69 64 3b 0a 20 20 69  erUid = uid;.  i
9290: 66 28 20 66 6f 73 73 69 6c 5f 73 74 72 63 6d 70  f( fossil_strcmp
92a0: 28 67 2e 7a 4c 6f 67 69 6e 2c 22 6e 6f 62 6f 64  (g.zLogin,"nobod
92b0: 79 22 29 3d 3d 30 20 29 7b 0a 20 20 20 20 67 2e  y")==0 ){.    g.
92c0: 7a 4c 6f 67 69 6e 20 3d 20 30 3b 0a 20 20 7d 0a  zLogin = 0;.  }.
92d0: 20 20 69 66 28 20 50 42 28 22 69 73 72 6f 62 6f    if( PB("isrobo
92e0: 74 22 29 20 29 7b 0a 20 20 20 20 67 2e 69 73 48  t") ){.    g.isH
92f0: 75 6d 61 6e 20 3d 20 30 3b 0a 20 20 7d 65 6c 73  uman = 0;.  }els
9300: 65 20 69 66 28 20 67 2e 7a 4c 6f 67 69 6e 3d 3d  e if( g.zLogin==
9310: 30 20 29 7b 0a 20 20 20 20 67 2e 69 73 48 75 6d  0 ){.    g.isHum
9320: 61 6e 20 3d 20 69 73 48 75 6d 61 6e 28 50 28 22  an = isHuman(P("
9330: 48 54 54 50 5f 55 53 45 52 5f 41 47 45 4e 54 22  HTTP_USER_AGENT"
9340: 29 29 3b 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20  ));.  }else{.   
9350: 20 67 2e 69 73 48 75 6d 61 6e 20 3d 20 31 3b 0a   g.isHuman = 1;.
9360: 20 20 7d 0a 0a 20 20 2f 2a 20 53 65 74 20 74 68    }..  /* Set th
9370: 65 20 63 61 70 61 62 69 6c 69 74 69 65 73 20 2a  e capabilities *
9380: 2f 0a 20 20 6c 6f 67 69 6e 5f 72 65 70 6c 61 63  /.  login_replac
9390: 65 5f 63 61 70 61 62 69 6c 69 74 69 65 73 28 7a  e_capabilities(z
93a0: 43 61 70 2c 20 30 29 3b 0a 0a 20 20 2f 2a 20 54  Cap, 0);..  /* T
93b0: 68 65 20 61 75 74 6f 2d 68 79 70 65 72 6c 69 6e  he auto-hyperlin
93c0: 6b 20 73 65 74 74 69 6e 67 20 61 6c 6c 6f 77 73  k setting allows
93d0: 20 68 79 70 65 72 6c 69 6e 6b 73 20 74 6f 20 62   hyperlinks to b
93e0: 65 20 64 69 73 70 6c 61 79 65 64 20 66 6f 72 20  e displayed for 
93f0: 75 73 65 72 73 0a 20 20 2a 2a 20 77 68 6f 20 64  users.  ** who d
9400: 6f 20 6e 6f 74 20 68 61 76 65 20 74 68 65 20 22  o not have the "
9410: 68 22 20 70 65 72 6d 69 73 73 69 6f 6e 20 61 73  h" permission as
9420: 20 6c 6f 6e 67 20 61 73 20 74 68 65 69 72 20 55   long as their U
9430: 73 65 72 41 67 65 6e 74 20 73 74 72 69 6e 67 0a  serAgent string.
9440: 20 20 2a 2a 20 6d 61 6b 65 73 20 69 74 20 61 70    ** makes it ap
9450: 70 65 61 72 20 74 68 61 74 20 74 68 65 79 20 61  pear that they a
9460: 72 65 20 68 75 6d 61 6e 2e 20 20 43 68 65 63 6b  re human.  Check
9470: 20 74 6f 20 73 65 65 20 69 66 20 61 75 74 6f 2d   to see if auto-
9480: 68 79 70 65 72 6c 69 6e 6b 20 69 73 0a 20 20 2a  hyperlink is.  *
9490: 2a 20 65 6e 61 62 6c 65 64 20 66 6f 72 20 74 68  * enabled for th
94a0: 69 73 20 72 65 70 6f 73 69 74 6f 72 79 20 61 6e  is repository an
94b0: 64 20 6d 61 6b 65 20 61 70 70 72 6f 70 72 69 61  d make appropria
94c0: 74 65 20 61 64 6a 75 73 74 6d 65 6e 74 73 20 74  te adjustments t
94d0: 6f 20 74 68 65 0a 20 20 2a 2a 20 70 65 72 6d 69  o the.  ** permi
94e0: 73 73 69 6f 6e 20 66 6c 61 67 73 20 69 66 20 69  ssion flags if i
94f0: 74 20 69 73 2e 20 20 54 68 69 73 20 73 68 6f 75  t is.  This shou
9500: 6c 64 20 62 65 20 64 6f 6e 65 20 62 65 66 6f 72  ld be done befor
9510: 65 20 74 68 65 20 70 65 72 6d 69 73 73 69 6f 6e  e the permission
9520: 73 0a 20 20 2a 2a 20 61 72 65 20 28 70 6f 74 65  s.  ** are (pote
9530: 6e 74 69 61 6c 6c 79 29 20 63 6f 70 69 65 64 20  ntially) copied 
9540: 74 6f 20 74 68 65 20 61 6e 6f 6e 79 6d 6f 75 73  to the anonymous
9550: 20 70 65 72 6d 69 73 73 69 6f 6e 20 73 65 74 3b   permission set;
9560: 20 6f 74 68 65 72 77 69 73 65 2c 0a 20 20 2a 2a   otherwise,.  **
9570: 20 74 68 6f 73 65 20 77 69 6c 6c 20 62 65 20 6f   those will be o
9580: 75 74 2d 6f 66 2d 73 79 6e 63 2e 0a 20 20 2a 2f  ut-of-sync..  */
9590: 0a 20 20 69 66 28 20 7a 43 61 70 5b 30 5d 0a 20  .  if( zCap[0]. 
95a0: 20 20 26 26 20 21 67 2e 70 65 72 6d 2e 48 79 70    && !g.perm.Hyp
95b0: 65 72 6c 69 6e 6b 0a 20 20 20 26 26 20 67 2e 69  erlink.   && g.i
95c0: 73 48 75 6d 61 6e 0a 20 20 20 26 26 20 64 62 5f  sHuman.   && db_
95d0: 67 65 74 5f 62 6f 6f 6c 65 61 6e 28 22 61 75 74  get_boolean("aut
95e0: 6f 2d 68 79 70 65 72 6c 69 6e 6b 22 2c 31 29 0a  o-hyperlink",1).
95f0: 20 20 29 7b 0a 20 20 20 20 67 2e 70 65 72 6d 2e    ){.    g.perm.
9600: 48 79 70 65 72 6c 69 6e 6b 20 3d 20 31 3b 0a 20  Hyperlink = 1;. 
9610: 20 20 20 67 2e 6a 61 76 61 73 63 72 69 70 74 48     g.javascriptH
9620: 79 70 65 72 6c 69 6e 6b 20 3d 20 31 3b 0a 20 20  yperlink = 1;.  
9630: 7d 0a 0a 20 20 2f 2a 0a 20 20 2a 2a 20 41 74 20  }..  /*.  ** At 
9640: 74 68 69 73 20 70 6f 69 6e 74 2c 20 74 68 65 20  this point, the 
9650: 63 61 70 61 62 69 6c 69 74 69 65 73 20 66 6f 72  capabilities for
9660: 20 74 68 65 20 6c 6f 67 67 65 64 20 69 6e 20 75   the logged in u
9670: 73 65 72 20 61 72 65 20 6e 6f 74 20 67 6f 69 6e  ser are not goin
9680: 67 0a 20 20 2a 2a 20 74 6f 20 62 65 20 6d 6f 64  g.  ** to be mod
9690: 69 66 69 65 64 20 61 6e 79 6d 6f 72 65 3b 20 74  ified anymore; t
96a0: 68 65 72 65 66 6f 72 65 2c 20 77 65 20 63 61 6e  herefore, we can
96b0: 20 63 6f 70 79 20 74 68 65 6d 20 6f 76 65 72 20   copy them over 
96c0: 74 6f 20 74 68 65 20 6f 6e 65 73 0a 20 20 2a 2a  to the ones.  **
96d0: 20 66 6f 72 20 74 68 65 20 61 6e 6f 6e 79 6d 6f   for the anonymo
96e0: 75 73 20 75 73 65 72 2e 0a 20 20 2a 2a 0a 20 20  us user..  **.  
96f0: 2a 2a 20 57 41 52 4e 49 4e 47 3a 20 49 6e 20 74  ** WARNING: In t
9700: 68 65 20 66 75 74 75 72 65 2c 20 70 6c 65 61 73  he future, pleas
9710: 65 20 64 6f 20 6e 6f 74 20 61 64 64 20 63 6f 64  e do not add cod
9720: 65 20 61 66 74 65 72 20 74 68 69 73 20 70 6f 69  e after this poi
9730: 6e 74 20 74 68 61 74 0a 20 20 2a 2a 20 20 20 20  nt that.  **    
9740: 20 20 20 20 20 20 6d 6f 64 69 66 69 65 73 20 74        modifies t
9750: 68 65 20 63 61 70 61 62 69 6c 69 74 69 65 73 20  he capabilities 
9760: 66 6f 72 20 74 68 65 20 6c 6f 67 67 65 64 20 69  for the logged i
9770: 6e 20 75 73 65 72 2e 0a 20 20 2a 2f 0a 20 20 6c  n user..  */.  l
9780: 6f 67 69 6e 5f 73 65 74 5f 61 6e 6f 6e 5f 6e 6f  ogin_set_anon_no
9790: 62 6f 64 79 5f 63 61 70 61 62 69 6c 69 74 69 65  body_capabilitie
97a0: 73 28 29 3b 0a 0a 20 20 2f 2a 20 49 66 20 74 68  s();..  /* If th
97b0: 65 20 70 75 62 6c 69 63 2d 70 61 67 65 73 20 67  e public-pages g
97c0: 6c 6f 62 20 70 61 74 74 65 72 6e 20 69 73 20 64  lob pattern is d
97d0: 65 66 69 6e 65 64 20 61 6e 64 20 52 45 51 55 45  efined and REQUE
97e0: 53 54 5f 55 52 49 20 6d 61 74 63 68 65 73 0a 20  ST_URI matches. 
97f0: 20 2a 2a 20 6f 6e 65 20 6f 66 20 74 68 65 20 67   ** one of the g
9800: 6c 6f 62 73 20 69 6e 20 70 75 62 6c 69 63 2d 70  lobs in public-p
9810: 61 67 65 73 2c 20 74 68 65 6e 20 61 6c 73 6f 20  ages, then also 
9820: 61 64 64 20 69 6e 20 61 6c 6c 20 64 65 66 61 75  add in all defau
9830: 6c 74 2d 70 65 72 6d 73 0a 20 20 2a 2a 20 70 65  lt-perms.  ** pe
9840: 72 6d 69 73 73 69 6f 6e 73 2e 0a 20 20 2a 2f 0a  rmissions..  */.
9850: 20 20 7a 50 75 62 6c 69 63 50 61 67 65 73 20 3d    zPublicPages =
9860: 20 64 62 5f 67 65 74 28 22 70 75 62 6c 69 63 2d   db_get("public-
9870: 70 61 67 65 73 22 2c 30 29 3b 0a 20 20 69 66 28  pages",0);.  if(
9880: 20 7a 50 75 62 6c 69 63 50 61 67 65 73 21 3d 30   zPublicPages!=0
9890: 20 29 7b 0a 20 20 20 20 47 6c 6f 62 20 2a 70 47   ){.    Glob *pG
98a0: 6c 6f 62 20 3d 20 67 6c 6f 62 5f 63 72 65 61 74  lob = glob_creat
98b0: 65 28 7a 50 75 62 6c 69 63 50 61 67 65 73 29 3b  e(zPublicPages);
98c0: 0a 20 20 20 20 69 66 28 20 67 6c 6f 62 5f 6d 61  .    if( glob_ma
98d0: 74 63 68 28 70 47 6c 6f 62 2c 20 50 44 28 22 52  tch(pGlob, PD("R
98e0: 45 51 55 45 53 54 5f 55 52 49 22 2c 22 6e 6f 2d  EQUEST_URI","no-
98f0: 6d 61 74 63 68 22 29 29 20 29 7b 0a 20 20 20 20  match")) ){.    
9900: 20 20 6c 6f 67 69 6e 5f 73 65 74 5f 63 61 70 61    login_set_capa
9910: 62 69 6c 69 74 69 65 73 28 64 62 5f 67 65 74 28  bilities(db_get(
9920: 22 64 65 66 61 75 6c 74 2d 70 65 72 6d 73 22 2c  "default-perms",
9930: 22 75 22 29 2c 20 30 29 3b 0a 20 20 20 20 7d 0a  "u"), 0);.    }.
9940: 20 20 20 20 67 6c 6f 62 5f 66 72 65 65 28 70 47      glob_free(pG
9950: 6c 6f 62 29 3b 0a 20 20 7d 0a 7d 0a 0a 2f 2a 0a  lob);.  }.}../*.
9960: 2a 2a 20 4d 65 6d 6f 72 79 20 6f 66 20 73 65 74  ** Memory of set
9970: 74 69 6e 67 73 0a 2a 2f 0a 73 74 61 74 69 63 20  tings.*/.static 
9980: 69 6e 74 20 6c 6f 67 69 6e 5f 61 6e 6f 6e 5f 6f  int login_anon_o
9990: 6e 63 65 20 3d 20 31 3b 0a 0a 2f 2a 0a 2a 2a 20  nce = 1;../*.** 
99a0: 41 64 64 20 74 6f 20 67 2e 70 65 72 6d 20 74 68  Add to g.perm th
99b0: 65 20 64 65 66 61 75 6c 74 20 70 72 69 76 69 6c  e default privil
99c0: 65 67 65 73 20 6f 66 20 75 73 65 72 73 20 22 6e  eges of users "n
99d0: 6f 62 6f 64 79 22 20 61 6e 64 2f 6f 72 20 22 61  obody" and/or "a
99e0: 6e 6f 6e 79 6d 6f 75 73 22 0a 2a 2a 20 61 73 20  nonymous".** as 
99f0: 61 70 70 72 6f 70 72 69 61 74 65 20 66 6f 72 20  appropriate for 
9a00: 74 68 65 20 75 73 65 72 20 67 2e 7a 4c 6f 67 69  the user g.zLogi
9a10: 6e 2e 0a 2a 2a 0a 2a 2a 20 54 68 69 73 20 72 6f  n..**.** This ro
9a20: 75 74 69 6e 65 20 61 6c 73 6f 20 73 65 74 73 20  utine also sets 
9a30: 75 70 20 67 2e 61 6e 6f 6e 20 74 6f 20 62 65 20  up g.anon to be 
9a40: 65 69 74 68 65 72 20 61 20 63 6f 70 79 20 6f 66  either a copy of
9a50: 20 67 2e 70 65 72 6d 20 66 6f 72 0a 2a 2a 20 61   g.perm for.** a
9a60: 6c 6c 20 6c 6f 67 67 65 64 20 69 6e 20 75 73 65  ll logged in use
9a70: 73 2c 20 6f 72 20 74 68 65 20 70 72 69 76 69 6c  s, or the privil
9a80: 65 67 65 73 20 74 68 61 74 20 77 6f 75 6c 64 20  eges that would 
9a90: 62 65 20 61 76 61 69 6c 61 62 6c 65 20 74 6f 20  be available to 
9aa0: 22 61 6e 6f 6e 79 6d 6f 75 73 22 0a 2a 2a 20 69  "anonymous".** i
9ab0: 66 20 67 2e 7a 4c 6f 67 69 6e 3d 3d 30 20 28 6d  f g.zLogin==0 (m
9ac0: 65 61 6e 69 6e 67 20 74 68 61 74 20 74 68 65 20  eaning that the 
9ad0: 75 73 65 72 20 69 73 20 22 6e 6f 62 6f 64 79 22  user is "nobody"
9ae0: 29 2e 0a 2a 2f 0a 76 6f 69 64 20 6c 6f 67 69 6e  )..*/.void login
9af0: 5f 73 65 74 5f 61 6e 6f 6e 5f 6e 6f 62 6f 64 79  _set_anon_nobody
9b00: 5f 63 61 70 61 62 69 6c 69 74 69 65 73 28 76 6f  _capabilities(vo
9b10: 69 64 29 7b 0a 20 20 69 66 28 20 6c 6f 67 69 6e  id){.  if( login
9b20: 5f 61 6e 6f 6e 5f 6f 6e 63 65 20 29 7b 0a 20 20  _anon_once ){.  
9b30: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 43    const char *zC
9b40: 61 70 3b 0a 20 20 20 20 2f 2a 20 41 6c 6c 20 75  ap;.    /* All u
9b50: 73 65 72 73 20 67 65 74 20 70 72 69 76 69 6c 65  sers get privile
9b60: 67 65 73 20 66 72 6f 6d 20 22 6e 6f 62 6f 64 79  ges from "nobody
9b70: 22 20 2a 2f 0a 20 20 20 20 7a 43 61 70 20 3d 20  " */.    zCap = 
9b80: 64 62 5f 74 65 78 74 28 22 22 2c 20 22 53 45 4c  db_text("", "SEL
9b90: 45 43 54 20 63 61 70 20 46 52 4f 4d 20 75 73 65  ECT cap FROM use
9ba0: 72 20 57 48 45 52 45 20 6c 6f 67 69 6e 20 3d 20  r WHERE login = 
9bb0: 27 6e 6f 62 6f 64 79 27 22 29 3b 0a 20 20 20 20  'nobody'");.    
9bc0: 6c 6f 67 69 6e 5f 73 65 74 5f 63 61 70 61 62 69  login_set_capabi
9bd0: 6c 69 74 69 65 73 28 7a 43 61 70 2c 20 30 29 3b  lities(zCap, 0);
9be0: 0a 20 20 20 20 7a 43 61 70 20 3d 20 64 62 5f 74  .    zCap = db_t
9bf0: 65 78 74 28 22 22 2c 20 22 53 45 4c 45 43 54 20  ext("", "SELECT 
9c00: 63 61 70 20 46 52 4f 4d 20 75 73 65 72 20 57 48  cap FROM user WH
9c10: 45 52 45 20 6c 6f 67 69 6e 20 3d 20 27 61 6e 6f  ERE login = 'ano
9c20: 6e 79 6d 6f 75 73 27 22 29 3b 0a 20 20 20 20 69  nymous'");.    i
9c30: 66 28 20 67 2e 7a 4c 6f 67 69 6e 20 26 26 20 66  f( g.zLogin && f
9c40: 6f 73 73 69 6c 5f 73 74 72 63 6d 70 28 67 2e 7a  ossil_strcmp(g.z
9c50: 4c 6f 67 69 6e 2c 20 22 6e 6f 62 6f 64 79 22 29  Login, "nobody")
9c60: 21 3d 30 20 29 7b 0a 20 20 20 20 20 20 2f 2a 20  !=0 ){.      /* 
9c70: 41 6c 6c 20 6c 6f 67 67 65 64 2d 69 6e 20 75 73  All logged-in us
9c80: 65 72 73 20 69 6e 68 65 72 69 74 20 70 72 69 76  ers inherit priv
9c90: 69 6c 65 67 65 73 20 66 72 6f 6d 20 22 61 6e 6f  ileges from "ano
9ca0: 6e 79 6d 6f 75 73 22 20 2a 2f 0a 20 20 20 20 20  nymous" */.     
9cb0: 20 6c 6f 67 69 6e 5f 73 65 74 5f 63 61 70 61 62   login_set_capab
9cc0: 69 6c 69 74 69 65 73 28 7a 43 61 70 2c 20 30 29  ilities(zCap, 0)
9cd0: 3b 0a 20 20 20 20 20 20 67 2e 61 6e 6f 6e 20 3d  ;.      g.anon =
9ce0: 20 67 2e 70 65 72 6d 3b 0a 20 20 20 20 7d 65 6c   g.perm;.    }el
9cf0: 73 65 7b 0a 20 20 20 20 20 20 2f 2a 20 52 65 63  se{.      /* Rec
9d00: 6f 72 64 20 74 68 65 20 70 72 69 76 69 6c 65 67  ord the privileg
9d10: 65 73 20 6f 66 20 61 6e 6f 6e 79 6d 6f 75 73 20  es of anonymous 
9d20: 69 6e 20 67 2e 61 6e 6f 6e 20 2a 2f 0a 20 20 20  in g.anon */.   
9d30: 20 20 20 67 2e 61 6e 6f 6e 20 3d 20 67 2e 70 65     g.anon = g.pe
9d40: 72 6d 3b 0a 20 20 20 20 20 20 6c 6f 67 69 6e 5f  rm;.      login_
9d50: 73 65 74 5f 63 61 70 61 62 69 6c 69 74 69 65 73  set_capabilities
9d60: 28 7a 43 61 70 2c 20 4c 4f 47 49 4e 5f 41 4e 4f  (zCap, LOGIN_ANO
9d70: 4e 29 3b 0a 20 20 20 20 7d 0a 20 20 20 20 6c 6f  N);.    }.    lo
9d80: 67 69 6e 5f 61 6e 6f 6e 5f 6f 6e 63 65 20 3d 20  gin_anon_once = 
9d90: 30 3b 0a 20 20 7d 0a 7d 0a 0a 2f 2a 0a 2a 2a 20  0;.  }.}../*.** 
9da0: 46 6c 61 67 73 20 70 61 73 73 65 64 20 69 6e 74  Flags passed int
9db0: 6f 20 74 68 65 20 32 6e 64 20 61 72 67 75 6d 65  o the 2nd argume
9dc0: 6e 74 20 6f 66 20 6c 6f 67 69 6e 5f 73 65 74 2f  nt of login_set/
9dd0: 72 65 70 6c 61 63 65 5f 63 61 70 61 62 69 6c 69  replace_capabili
9de0: 74 69 65 73 28 29 2e 0a 2a 2f 0a 23 69 66 20 49  ties()..*/.#if I
9df0: 4e 54 45 52 46 41 43 45 0a 23 64 65 66 69 6e 65  NTERFACE.#define
9e00: 20 4c 4f 47 49 4e 5f 49 47 4e 4f 52 45 5f 55 56   LOGIN_IGNORE_UV
9e10: 20 20 30 78 30 31 20 20 20 20 20 20 20 20 20 2f    0x01         /
9e20: 2a 20 49 67 6e 6f 72 65 20 22 75 22 20 61 6e 64  * Ignore "u" and
9e30: 20 22 76 22 20 2a 2f 0a 23 64 65 66 69 6e 65 20   "v" */.#define 
9e40: 4c 4f 47 49 4e 5f 41 4e 4f 4e 20 20 20 20 20 20  LOGIN_ANON      
9e50: 20 30 78 30 32 20 20 20 20 20 20 20 20 20 2f 2a   0x02         /*
9e60: 20 55 73 65 20 67 2e 61 6e 6f 6e 20 69 6e 73 74   Use g.anon inst
9e70: 65 61 64 20 6f 66 20 67 2e 70 65 72 6d 20 2a 2f  ead of g.perm */
9e80: 0a 23 65 6e 64 69 66 0a 0a 2f 2a 0a 2a 2a 20 41  .#endif../*.** A
9e90: 64 64 73 20 61 6c 6c 20 63 61 70 61 62 69 6c 69  dds all capabili
9ea0: 74 79 20 66 6c 61 67 73 20 69 6e 20 7a 43 61 70  ty flags in zCap
9eb0: 20 74 6f 20 67 2e 70 65 72 6d 20 6f 72 20 67 2e   to g.perm or g.
9ec0: 61 6e 6f 6e 2e 0a 2a 2f 0a 76 6f 69 64 20 6c 6f  anon..*/.void lo
9ed0: 67 69 6e 5f 73 65 74 5f 63 61 70 61 62 69 6c 69  gin_set_capabili
9ee0: 74 69 65 73 28 63 6f 6e 73 74 20 63 68 61 72 20  ties(const char 
9ef0: 2a 7a 43 61 70 2c 20 75 6e 73 69 67 6e 65 64 20  *zCap, unsigned 
9f00: 66 6c 61 67 73 29 7b 0a 20 20 69 6e 74 20 69 3b  flags){.  int i;
9f10: 0a 20 20 46 6f 73 73 69 6c 55 73 65 72 50 65 72  .  FossilUserPer
9f20: 6d 73 20 2a 70 20 3d 20 28 66 6c 61 67 73 20 26  ms *p = (flags &
9f30: 20 4c 4f 47 49 4e 5f 41 4e 4f 4e 29 20 3f 20 26   LOGIN_ANON) ? &
9f40: 67 2e 61 6e 6f 6e 20 3a 20 26 67 2e 70 65 72 6d  g.anon : &g.perm
9f50: 3b 0a 20 20 69 66 28 4e 55 4c 4c 3d 3d 7a 43 61  ;.  if(NULL==zCa
9f60: 70 29 7b 0a 20 20 20 20 72 65 74 75 72 6e 3b 0a  p){.    return;.
9f70: 20 20 7d 0a 20 20 66 6f 72 28 69 3d 30 3b 20 7a    }.  for(i=0; z
9f80: 43 61 70 5b 69 5d 3b 20 69 2b 2b 29 7b 0a 20 20  Cap[i]; i++){.  
9f90: 20 20 73 77 69 74 63 68 28 20 7a 43 61 70 5b 69    switch( zCap[i
9fa0: 5d 20 29 7b 0a 20 20 20 20 20 20 63 61 73 65 20  ] ){.      case 
9fb0: 27 73 27 3a 20 20 20 70 2d 3e 53 65 74 75 70 20  's':   p->Setup 
9fc0: 3d 20 31 3b 20 2f 2a 20 46 61 6c 6c 20 74 68 72  = 1; /* Fall thr
9fd0: 75 20 69 6e 74 6f 20 41 64 6d 69 6e 20 2a 2f 0a  u into Admin */.
9fe0: 20 20 20 20 20 20 63 61 73 65 20 27 61 27 3a 20        case 'a': 
9ff0: 20 20 70 2d 3e 41 64 6d 69 6e 20 3d 20 70 2d 3e    p->Admin = p->
a000: 52 64 54 6b 74 20 3d 20 70 2d 3e 57 72 54 6b 74  RdTkt = p->WrTkt
a010: 20 3d 20 70 2d 3e 5a 69 70 20 3d 0a 20 20 20 20   = p->Zip =.    
a020: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a030: 20 20 20 20 20 20 20 20 20 70 2d 3e 52 64 57 69           p->RdWi
a040: 6b 69 20 3d 20 70 2d 3e 57 72 57 69 6b 69 20 3d  ki = p->WrWiki =
a050: 20 70 2d 3e 4e 65 77 57 69 6b 69 20 3d 0a 20 20   p->NewWiki =.  
a060: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a070: 20 20 20 20 20 20 20 20 20 20 20 70 2d 3e 41 70             p->Ap
a080: 6e 64 57 69 6b 69 20 3d 20 70 2d 3e 48 79 70 65  ndWiki = p->Hype
a090: 72 6c 69 6e 6b 20 3d 20 70 2d 3e 43 6c 6f 6e 65  rlink = p->Clone
a0a0: 20 3d 0a 20 20 20 20 20 20 20 20 20 20 20 20 20   =.             
a0b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a0c0: 70 2d 3e 4e 65 77 54 6b 74 20 3d 20 70 2d 3e 50  p->NewTkt = p->P
a0d0: 61 73 73 77 6f 72 64 20 3d 20 70 2d 3e 52 64 41  assword = p->RdA
a0e0: 64 64 72 20 3d 0a 20 20 20 20 20 20 20 20 20 20  ddr =.          
a0f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a100: 20 20 20 70 2d 3e 54 6b 74 46 6d 74 20 3d 20 70     p->TktFmt = p
a110: 2d 3e 41 74 74 61 63 68 20 3d 20 70 2d 3e 41 70  ->Attach = p->Ap
a120: 6e 64 54 6b 74 20 3d 0a 20 20 20 20 20 20 20 20  ndTkt =.        
a130: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a140: 20 20 20 20 20 70 2d 3e 4d 6f 64 57 69 6b 69 20       p->ModWiki 
a150: 3d 20 70 2d 3e 4d 6f 64 54 6b 74 20 3d 20 70 2d  = p->ModTkt = p-
a160: 3e 44 65 6c 65 74 65 20 3d 0a 20 20 20 20 20 20  >Delete =.      
a170: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a180: 20 20 20 20 20 20 20 70 2d 3e 52 64 46 6f 72 75         p->RdForu
a190: 6d 20 3d 20 70 2d 3e 57 72 46 6f 72 75 6d 20 3d  m = p->WrForum =
a1a0: 20 70 2d 3e 4d 6f 64 46 6f 72 75 6d 20 3d 0a 20   p->ModForum =. 
a1b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a1c0: 20 20 20 20 20 20 20 20 20 20 20 20 70 2d 3e 57              p->W
a1d0: 72 54 46 6f 72 75 6d 20 3d 20 70 2d 3e 41 64 6d  rTForum = p->Adm
a1e0: 69 6e 46 6f 72 75 6d 20 3d 0a 20 20 20 20 20 20  inForum =.      
a1f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a200: 20 20 20 20 20 20 20 70 2d 3e 45 6d 61 69 6c 41         p->EmailA
a210: 6c 65 72 74 20 3d 20 70 2d 3e 41 6e 6e 6f 75 6e  lert = p->Announ
a220: 63 65 20 3d 0a 20 20 20 20 20 20 20 20 20 20 20  ce =.           
a230: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a240: 20 20 70 2d 3e 57 72 55 6e 76 65 72 20 3d 20 70    p->WrUnver = p
a250: 2d 3e 50 72 69 76 61 74 65 20 3d 20 31 3b 0a 20  ->Private = 1;. 
a260: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a270: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 46              /* F
a280: 61 6c 6c 20 74 68 72 75 20 69 6e 74 6f 20 52 65  all thru into Re
a290: 61 64 2f 57 72 69 74 65 20 2a 2f 0a 20 20 20 20  ad/Write */.    
a2a0: 20 20 63 61 73 65 20 27 69 27 3a 20 20 20 70 2d    case 'i':   p-
a2b0: 3e 52 65 61 64 20 3d 20 70 2d 3e 57 72 69 74 65  >Read = p->Write
a2c0: 20 3d 20 31 3b 20 20 20 20 20 20 20 20 20 20 20   = 1;           
a2d0: 20 20 20 20 20 20 20 20 20 20 20 62 72 65 61 6b             break
a2e0: 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27 6f 27  ;.      case 'o'
a2f0: 3a 20 20 20 70 2d 3e 52 65 61 64 20 3d 20 31 3b  :   p->Read = 1;
a300: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a310: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a320: 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 63 61   break;.      ca
a330: 73 65 20 27 7a 27 3a 20 20 20 70 2d 3e 5a 69 70  se 'z':   p->Zip
a340: 20 3d 20 31 3b 20 20 20 20 20 20 20 20 20 20 20   = 1;           
a350: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a360: 20 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 0a 20         break;.. 
a370: 20 20 20 20 20 63 61 73 65 20 27 64 27 3a 20 20       case 'd':  
a380: 20 70 2d 3e 44 65 6c 65 74 65 20 3d 20 31 3b 20   p->Delete = 1; 
a390: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a3a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 62 72                br
a3b0: 65 61 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20  eak;.      case 
a3c0: 27 68 27 3a 20 20 20 70 2d 3e 48 79 70 65 72 6c  'h':   p->Hyperl
a3d0: 69 6e 6b 20 3d 20 31 3b 20 20 20 20 20 20 20 20  ink = 1;        
a3e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a3f0: 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20      break;.     
a400: 20 63 61 73 65 20 27 67 27 3a 20 20 20 70 2d 3e   case 'g':   p->
a410: 43 6c 6f 6e 65 20 3d 20 31 3b 20 20 20 20 20 20  Clone = 1;      
a420: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a430: 20 20 20 20 20 20 20 20 20 20 62 72 65 61 6b 3b            break;
a440: 0a 20 20 20 20 20 20 63 61 73 65 20 27 70 27 3a  .      case 'p':
a450: 20 20 20 70 2d 3e 50 61 73 73 77 6f 72 64 20 3d     p->Password =
a460: 20 31 3b 20 20 20 20 20 20 20 20 20 20 20 20 20   1;             
a470: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a480: 62 72 65 61 6b 3b 0a 0a 20 20 20 20 20 20 63 61  break;..      ca
a490: 73 65 20 27 6a 27 3a 20 20 20 70 2d 3e 52 64 57  se 'j':   p->RdW
a4a0: 69 6b 69 20 3d 20 31 3b 20 20 20 20 20 20 20 20  iki = 1;        
a4b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a4c0: 20 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20 20         break;.  
a4d0: 20 20 20 20 63 61 73 65 20 27 6b 27 3a 20 20 20      case 'k':   
a4e0: 70 2d 3e 57 72 57 69 6b 69 20 3d 20 70 2d 3e 52  p->WrWiki = p->R
a4f0: 64 57 69 6b 69 20 3d 20 70 2d 3e 41 70 6e 64 57  dWiki = p->ApndW
a500: 69 6b 69 20 3d 31 3b 20 20 20 20 20 20 62 72 65  iki =1;      bre
a510: 61 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27  ak;.      case '
a520: 6d 27 3a 20 20 20 70 2d 3e 41 70 6e 64 57 69 6b  m':   p->ApndWik
a530: 69 20 3d 20 31 3b 20 20 20 20 20 20 20 20 20 20  i = 1;          
a540: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a550: 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20     break;.      
a560: 63 61 73 65 20 27 66 27 3a 20 20 20 70 2d 3e 4e  case 'f':   p->N
a570: 65 77 57 69 6b 69 20 3d 20 31 3b 20 20 20 20 20  ewWiki = 1;     
a580: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a590: 20 20 20 20 20 20 20 20 20 62 72 65 61 6b 3b 0a           break;.
a5a0: 20 20 20 20 20 20 63 61 73 65 20 27 6c 27 3a 20        case 'l': 
a5b0: 20 20 70 2d 3e 4d 6f 64 57 69 6b 69 20 3d 20 31    p->ModWiki = 1
a5c0: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ;               
a5d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 62                 b
a5e0: 72 65 61 6b 3b 0a 0a 20 20 20 20 20 20 63 61 73  reak;..      cas
a5f0: 65 20 27 65 27 3a 20 20 20 70 2d 3e 52 64 41 64  e 'e':   p->RdAd
a600: 64 72 20 3d 20 31 3b 20 20 20 20 20 20 20 20 20  dr = 1;         
a610: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a620: 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20        break;.   
a630: 20 20 20 63 61 73 65 20 27 72 27 3a 20 20 20 70     case 'r':   p
a640: 2d 3e 52 64 54 6b 74 20 3d 20 31 3b 20 20 20 20  ->RdTkt = 1;    
a650: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a660: 20 20 20 20 20 20 20 20 20 20 20 20 62 72 65 61              brea
a670: 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27 6e  k;.      case 'n
a680: 27 3a 20 20 20 70 2d 3e 4e 65 77 54 6b 74 20 3d  ':   p->NewTkt =
a690: 20 31 3b 20 20 20 20 20 20 20 20 20 20 20 20 20   1;             
a6a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a6b0: 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 63    break;.      c
a6c0: 61 73 65 20 27 77 27 3a 20 20 20 70 2d 3e 57 72  ase 'w':   p->Wr
a6d0: 54 6b 74 20 3d 20 70 2d 3e 52 64 54 6b 74 20 3d  Tkt = p->RdTkt =
a6e0: 20 70 2d 3e 4e 65 77 54 6b 74 20 3d 0a 20 20 20   p->NewTkt =.   
a6f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 70                 p
a700: 2d 3e 41 70 6e 64 54 6b 74 20 3d 20 31 3b 20 20  ->ApndTkt = 1;  
a710: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a720: 20 20 20 20 20 20 20 20 20 20 20 20 62 72 65 61              brea
a730: 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27 63  k;.      case 'c
a740: 27 3a 20 20 20 70 2d 3e 41 70 6e 64 54 6b 74 20  ':   p->ApndTkt 
a750: 3d 20 31 3b 20 20 20 20 20 20 20 20 20 20 20 20  = 1;            
a760: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a770: 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 63    break;.      c
a780: 61 73 65 20 27 71 27 3a 20 20 20 70 2d 3e 4d 6f  ase 'q':   p->Mo
a790: 64 54 6b 74 20 3d 20 31 3b 20 20 20 20 20 20 20  dTkt = 1;       
a7a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a7b0: 20 20 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20          break;. 
a7c0: 20 20 20 20 20 63 61 73 65 20 27 74 27 3a 20 20       case 't':  
a7d0: 20 70 2d 3e 54 6b 74 46 6d 74 20 3d 20 31 3b 20   p->TktFmt = 1; 
a7e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a7f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 62 72                br
a800: 65 61 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20  eak;.      case 
a810: 27 62 27 3a 20 20 20 70 2d 3e 41 74 74 61 63 68  'b':   p->Attach
a820: 20 3d 20 31 3b 20 20 20 20 20 20 20 20 20 20 20   = 1;           
a830: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a840: 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20      break;.     
a850: 20 63 61 73 65 20 27 78 27 3a 20 20 20 70 2d 3e   case 'x':   p->
a860: 50 72 69 76 61 74 65 20 3d 20 31 3b 20 20 20 20  Private = 1;    
a870: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a880: 20 20 20 20 20 20 20 20 20 20 62 72 65 61 6b 3b            break;
a890: 0a 20 20 20 20 20 20 63 61 73 65 20 27 79 27 3a  .      case 'y':
a8a0: 20 20 20 70 2d 3e 57 72 55 6e 76 65 72 20 3d 20     p->WrUnver = 
a8b0: 31 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  1;              
a8c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a8d0: 62 72 65 61 6b 3b 0a 0a 20 20 20 20 20 20 63 61  break;..      ca
a8e0: 73 65 20 27 36 27 3a 20 20 20 70 2d 3e 41 64 6d  se '6':   p->Adm
a8f0: 69 6e 46 6f 72 75 6d 20 3d 20 31 3b 0a 20 20 20  inForum = 1;.   
a900: 20 20 20 63 61 73 65 20 27 35 27 3a 20 20 20 70     case '5':   p
a910: 2d 3e 4d 6f 64 46 6f 72 75 6d 20 3d 20 31 3b 0a  ->ModForum = 1;.
a920: 20 20 20 20 20 20 63 61 73 65 20 27 34 27 3a 20        case '4': 
a930: 20 20 70 2d 3e 57 72 54 46 6f 72 75 6d 20 3d 20    p->WrTForum = 
a940: 31 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27 33  1;.      case '3
a950: 27 3a 20 20 20 70 2d 3e 57 72 46 6f 72 75 6d 20  ':   p->WrForum 
a960: 3d 20 31 3b 0a 20 20 20 20 20 20 63 61 73 65 20  = 1;.      case 
a970: 27 32 27 3a 20 20 20 70 2d 3e 52 64 46 6f 72 75  '2':   p->RdForu
a980: 6d 20 3d 20 31 3b 20 20 20 20 20 20 20 20 20 20  m = 1;          
a990: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a9a0: 20 20 20 20 62 72 65 61 6b 3b 0a 0a 20 20 20 20      break;..    
a9b0: 20 20 63 61 73 65 20 27 37 27 3a 20 20 20 70 2d    case '7':   p-
a9c0: 3e 45 6d 61 69 6c 41 6c 65 72 74 20 3d 20 31 3b  >EmailAlert = 1;
a9d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a9e0: 20 20 20 20 20 20 20 20 20 20 20 62 72 65 61 6b             break
a9f0: 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27 41 27  ;.      case 'A'
aa00: 3a 20 20 20 70 2d 3e 41 6e 6e 6f 75 6e 63 65 20  :   p->Announce 
aa10: 3d 20 31 3b 20 20 20 20 20 20 20 20 20 20 20 20  = 1;            
aa20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
aa30: 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 63 61   break;.      ca
aa40: 73 65 20 27 44 27 3a 20 20 20 70 2d 3e 44 65 62  se 'D':   p->Deb
aa50: 75 67 20 3d 20 31 3b 20 20 20 20 20 20 20 20 20  ug = 1;         
aa60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
aa70: 20 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 0a 20         break;.. 
aa80: 20 20 20 20 20 2f 2a 20 54 68 65 20 22 75 22 20       /* The "u" 
aa90: 70 72 69 76 69 6c 65 67 65 73 20 69 73 20 61 20  privileges is a 
aaa0: 6c 69 74 74 6c 65 20 64 69 66 66 65 72 65 6e 74  little different
aab0: 2e 20 20 49 74 20 72 65 63 75 72 73 69 76 65 6c  .  It recursivel
aac0: 79 0a 20 20 20 20 20 20 2a 2a 20 69 6e 68 65 72  y.      ** inher
aad0: 69 74 73 20 61 6c 6c 20 70 72 69 76 69 6c 65 67  its all privileg
aae0: 65 73 20 6f 66 20 74 68 65 20 75 73 65 72 20 6e  es of the user n
aaf0: 61 6d 65 64 20 22 72 65 61 64 65 72 22 20 2a 2f  amed "reader" */
ab00: 0a 20 20 20 20 20 20 63 61 73 65 20 27 75 27 3a  .      case 'u':
ab10: 20 7b 0a 20 20 20 20 20 20 20 20 69 66 28 20 28   {.        if( (
ab20: 66 6c 61 67 73 20 26 20 4c 4f 47 49 4e 5f 49 47  flags & LOGIN_IG
ab30: 4e 4f 52 45 5f 55 56 29 3d 3d 30 20 29 7b 0a 20  NORE_UV)==0 ){. 
ab40: 20 20 20 20 20 20 20 20 20 63 6f 6e 73 74 20 63           const c
ab50: 68 61 72 20 2a 7a 55 73 65 72 3b 0a 20 20 20 20  har *zUser;.    
ab60: 20 20 20 20 20 20 7a 55 73 65 72 20 3d 20 64 62        zUser = db
ab70: 5f 74 65 78 74 28 22 22 2c 20 22 53 45 4c 45 43  _text("", "SELEC
ab80: 54 20 63 61 70 20 46 52 4f 4d 20 75 73 65 72 20  T cap FROM user 
ab90: 57 48 45 52 45 20 6c 6f 67 69 6e 3d 27 72 65 61  WHERE login='rea
aba0: 64 65 72 27 22 29 3b 0a 20 20 20 20 20 20 20 20  der'");.        
abb0: 20 20 6c 6f 67 69 6e 5f 73 65 74 5f 63 61 70 61    login_set_capa
abc0: 62 69 6c 69 74 69 65 73 28 7a 55 73 65 72 2c 20  bilities(zUser, 
abd0: 66 6c 61 67 73 20 7c 20 4c 4f 47 49 4e 5f 49 47  flags | LOGIN_IG
abe0: 4e 4f 52 45 5f 55 56 29 3b 0a 20 20 20 20 20 20  NORE_UV);.      
abf0: 20 20 7d 0a 20 20 20 20 20 20 20 20 62 72 65 61    }.        brea
ac00: 6b 3b 0a 20 20 20 20 20 20 7d 0a 0a 20 20 20 20  k;.      }..    
ac10: 20 20 2f 2a 20 54 68 65 20 22 76 22 20 70 72 69    /* The "v" pri
ac20: 76 69 6c 65 67 65 73 20 69 73 20 61 20 6c 69 74  vileges is a lit
ac30: 74 6c 65 20 64 69 66 66 65 72 65 6e 74 2e 20 20  tle different.  
ac40: 49 74 20 72 65 63 75 72 73 69 76 65 6c 79 0a 20  It recursively. 
ac50: 20 20 20 20 20 2a 2a 20 69 6e 68 65 72 69 74 73       ** inherits
ac60: 20 61 6c 6c 20 70 72 69 76 69 6c 65 67 65 73 20   all privileges 
ac70: 6f 66 20 74 68 65 20 75 73 65 72 20 6e 61 6d 65  of the user name
ac80: 64 20 22 64 65 76 65 6c 6f 70 65 72 22 20 2a 2f  d "developer" */
ac90: 0a 20 20 20 20 20 20 63 61 73 65 20 27 76 27 3a  .      case 'v':
aca0: 20 7b 0a 20 20 20 20 20 20 20 20 69 66 28 20 28   {.        if( (
acb0: 66 6c 61 67 73 20 26 20 4c 4f 47 49 4e 5f 49 47  flags & LOGIN_IG
acc0: 4e 4f 52 45 5f 55 56 29 3d 3d 30 20 29 7b 0a 20  NORE_UV)==0 ){. 
acd0: 20 20 20 20 20 20 20 20 20 63 6f 6e 73 74 20 63           const c
ace0: 68 61 72 20 2a 7a 44 65 76 3b 0a 20 20 20 20 20  har *zDev;.     
acf0: 20 20 20 20 20 7a 44 65 76 20 3d 20 64 62 5f 74       zDev = db_t
ad00: 65 78 74 28 22 22 2c 20 22 53 45 4c 45 43 54 20  ext("", "SELECT 
ad10: 63 61 70 20 46 52 4f 4d 20 75 73 65 72 20 57 48  cap FROM user WH
ad20: 45 52 45 20 6c 6f 67 69 6e 3d 27 64 65 76 65 6c  ERE login='devel
ad30: 6f 70 65 72 27 22 29 3b 0a 20 20 20 20 20 20 20  oper'");.       
ad40: 20 20 20 6c 6f 67 69 6e 5f 73 65 74 5f 63 61 70     login_set_cap
ad50: 61 62 69 6c 69 74 69 65 73 28 7a 44 65 76 2c 20  abilities(zDev, 
ad60: 66 6c 61 67 73 20 7c 20 4c 4f 47 49 4e 5f 49 47  flags | LOGIN_IG
ad70: 4e 4f 52 45 5f 55 56 29 3b 0a 20 20 20 20 20 20  NORE_UV);.      
ad80: 20 20 7d 0a 20 20 20 20 20 20 20 20 62 72 65 61    }.        brea
ad90: 6b 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 7d  k;.      }.    }
ada0: 0a 20 20 7d 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 5a 65  .  }.}../*.** Ze
adb0: 72 6f 65 73 20 6f 75 74 20 67 2e 70 65 72 6d 20  roes out g.perm 
adc0: 61 6e 64 20 63 61 6c 6c 73 20 6c 6f 67 69 6e 5f  and calls login_
add0: 73 65 74 5f 63 61 70 61 62 69 6c 69 74 69 65 73  set_capabilities
ade0: 28 7a 43 61 70 2c 66 6c 61 67 73 29 2e 0a 2a 2f  (zCap,flags)..*/
adf0: 0a 76 6f 69 64 20 6c 6f 67 69 6e 5f 72 65 70 6c  .void login_repl
ae00: 61 63 65 5f 63 61 70 61 62 69 6c 69 74 69 65 73  ace_capabilities
ae10: 28 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 43 61  (const char *zCa
ae20: 70 2c 20 75 6e 73 69 67 6e 65 64 20 66 6c 61 67  p, unsigned flag
ae30: 73 29 7b 0a 20 20 6d 65 6d 73 65 74 28 26 67 2e  s){.  memset(&g.
ae40: 70 65 72 6d 2c 20 30 2c 20 73 69 7a 65 6f 66 28  perm, 0, sizeof(
ae50: 67 2e 70 65 72 6d 29 29 3b 0a 20 20 6c 6f 67 69  g.perm));.  logi
ae60: 6e 5f 73 65 74 5f 63 61 70 61 62 69 6c 69 74 69  n_set_capabiliti
ae70: 65 73 28 7a 43 61 70 2c 20 66 6c 61 67 73 29 3b  es(zCap, flags);
ae80: 0a 20 20 6c 6f 67 69 6e 5f 61 6e 6f 6e 5f 6f 6e  .  login_anon_on
ae90: 63 65 20 3d 20 31 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a  ce = 1;.}../*.**
aea0: 20 49 66 20 74 68 65 20 63 75 72 72 65 6e 74 20   If the current 
aeb0: 6c 6f 67 69 6e 20 6c 61 63 6b 73 20 61 6e 79 20  login lacks any 
aec0: 6f 66 20 74 68 65 20 63 61 70 61 62 69 6c 69 74  of the capabilit
aed0: 69 65 73 20 6c 69 73 74 65 64 20 69 6e 0a 2a 2a  ies listed in.**
aee0: 20 74 68 65 20 69 6e 70 75 74 2c 20 74 68 65 6e   the input, then
aef0: 20 72 65 74 75 72 6e 20 30 2e 20 20 49 66 20 61   return 0.  If a
af00: 6c 6c 20 63 61 70 61 62 69 6c 69 74 69 65 73 20  ll capabilities 
af10: 61 72 65 20 70 72 65 73 65 6e 74 2c 20 74 68 65  are present, the
af20: 6e 0a 2a 2a 20 72 65 74 75 72 6e 20 31 2e 0a 2a  n.** return 1..*
af30: 2f 0a 69 6e 74 20 6c 6f 67 69 6e 5f 68 61 73 5f  /.int login_has_
af40: 63 61 70 61 62 69 6c 69 74 79 28 63 6f 6e 73 74  capability(const
af50: 20 63 68 61 72 20 2a 7a 43 61 70 2c 20 69 6e 74   char *zCap, int
af60: 20 6e 43 61 70 2c 20 75 33 32 20 66 6c 67 73 29   nCap, u32 flgs)
af70: 7b 0a 20 20 69 6e 74 20 69 3b 0a 20 20 69 6e 74  {.  int i;.  int
af80: 20 72 63 20 3d 20 31 3b 0a 20 20 46 6f 73 73 69   rc = 1;.  Fossi
af90: 6c 55 73 65 72 50 65 72 6d 73 20 2a 70 20 3d 20  lUserPerms *p = 
afa0: 28 66 6c 67 73 20 26 20 4c 4f 47 49 4e 5f 41 4e  (flgs & LOGIN_AN
afb0: 4f 4e 29 20 3f 20 26 67 2e 61 6e 6f 6e 20 3a 20  ON) ? &g.anon : 
afc0: 26 67 2e 70 65 72 6d 3b 0a 20 20 69 66 28 20 6e  &g.perm;.  if( n
afd0: 43 61 70 3c 30 20 29 20 6e 43 61 70 20 3d 20 73  Cap<0 ) nCap = s
afe0: 74 72 6c 65 6e 28 7a 43 61 70 29 3b 0a 20 20 66  trlen(zCap);.  f
aff0: 6f 72 28 69 3d 30 3b 20 69 3c 6e 43 61 70 20 26  or(i=0; i<nCap &
b000: 26 20 72 63 20 26 26 20 7a 43 61 70 5b 69 5d 3b  & rc && zCap[i];
b010: 20 69 2b 2b 29 7b 0a 20 20 20 20 73 77 69 74 63   i++){.    switc
b020: 68 28 20 7a 43 61 70 5b 69 5d 20 29 7b 0a 20 20  h( zCap[i] ){.  
b030: 20 20 20 20 63 61 73 65 20 27 61 27 3a 20 20 72      case 'a':  r
b040: 63 20 3d 20 70 2d 3e 41 64 6d 69 6e 3b 20 20 20  c = p->Admin;   
b050: 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 63    break;.      c
b060: 61 73 65 20 27 62 27 3a 20 20 72 63 20 3d 20 70  ase 'b':  rc = p
b070: 2d 3e 41 74 74 61 63 68 3b 20 20 20 20 62 72 65  ->Attach;    bre
b080: 61 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27  ak;.      case '
b090: 63 27 3a 20 20 72 63 20 3d 20 70 2d 3e 41 70 6e  c':  rc = p->Apn
b0a0: 64 54 6b 74 3b 20 20 20 62 72 65 61 6b 3b 0a 20  dTkt;   break;. 
b0b0: 20 20 20 20 20 63 61 73 65 20 27 64 27 3a 20 20       case 'd':  
b0c0: 72 63 20 3d 20 70 2d 3e 44 65 6c 65 74 65 3b 20  rc = p->Delete; 
b0d0: 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20     break;.      
b0e0: 63 61 73 65 20 27 65 27 3a 20 20 72 63 20 3d 20  case 'e':  rc = 
b0f0: 70 2d 3e 52 64 41 64 64 72 3b 20 20 20 20 62 72  p->RdAddr;    br
b100: 65 61 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20  eak;.      case 
b110: 27 66 27 3a 20 20 72 63 20 3d 20 70 2d 3e 4e 65  'f':  rc = p->Ne
b120: 77 57 69 6b 69 3b 20 20 20 62 72 65 61 6b 3b 0a  wWiki;   break;.
b130: 20 20 20 20 20 20 63 61 73 65 20 27 67 27 3a 20        case 'g': 
b140: 20 72 63 20 3d 20 70 2d 3e 43 6c 6f 6e 65 3b 20   rc = p->Clone; 
b150: 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20      break;.     
b160: 20 63 61 73 65 20 27 68 27 3a 20 20 72 63 20 3d   case 'h':  rc =
b170: 20 70 2d 3e 48 79 70 65 72 6c 69 6e 6b 3b 20 62   p->Hyperlink; b
b180: 72 65 61 6b 3b 0a 20 20 20 20 20 20 63 61 73 65  reak;.      case
b190: 20 27 69 27 3a 20 20 72 63 20 3d 20 70 2d 3e 57   'i':  rc = p->W
b1a0: 72 69 74 65 3b 20 20 20 20 20 62 72 65 61 6b 3b  rite;     break;
b1b0: 0a 20 20 20 20 20 20 63 61 73 65 20 27 6a 27 3a  .      case 'j':
b1c0: 20 20 72 63 20 3d 20 70 2d 3e 52 64 57 69 6b 69    rc = p->RdWiki
b1d0: 3b 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20  ;    break;.    
b1e0: 20 20 63 61 73 65 20 27 6b 27 3a 20 20 72 63 20    case 'k':  rc 
b1f0: 3d 20 70 2d 3e 57 72 57 69 6b 69 3b 20 20 20 20  = p->WrWiki;    
b200: 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 63 61 73  break;.      cas
b210: 65 20 27 6c 27 3a 20 20 72 63 20 3d 20 70 2d 3e  e 'l':  rc = p->
b220: 4d 6f 64 57 69 6b 69 3b 20 20 20 62 72 65 61 6b  ModWiki;   break
b230: 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27 6d 27  ;.      case 'm'
b240: 3a 20 20 72 63 20 3d 20 70 2d 3e 41 70 6e 64 57  :  rc = p->ApndW
b250: 69 6b 69 3b 20 20 62 72 65 61 6b 3b 0a 20 20 20  iki;  break;.   
b260: 20 20 20 63 61 73 65 20 27 6e 27 3a 20 20 72 63     case 'n':  rc
b270: 20 3d 20 70 2d 3e 4e 65 77 54 6b 74 3b 20 20 20   = p->NewTkt;   
b280: 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 63 61   break;.      ca
b290: 73 65 20 27 6f 27 3a 20 20 72 63 20 3d 20 70 2d  se 'o':  rc = p-
b2a0: 3e 52 65 61 64 3b 20 20 20 20 20 20 62 72 65 61  >Read;      brea
b2b0: 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27 70  k;.      case 'p
b2c0: 27 3a 20 20 72 63 20 3d 20 70 2d 3e 50 61 73 73  ':  rc = p->Pass
b2d0: 77 6f 72 64 3b 20 20 62 72 65 61 6b 3b 0a 20 20  word;  break;.  
b2e0: 20 20 20 20 63 61 73 65 20 27 71 27 3a 20 20 72      case 'q':  r
b2f0: 63 20 3d 20 70 2d 3e 4d 6f 64 54 6b 74 3b 20 20  c = p->ModTkt;  
b300: 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 63    break;.      c
b310: 61 73 65 20 27 72 27 3a 20 20 72 63 20 3d 20 70  ase 'r':  rc = p
b320: 2d 3e 52 64 54 6b 74 3b 20 20 20 20 20 62 72 65  ->RdTkt;     bre
b330: 61 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27  ak;.      case '
b340: 73 27 3a 20 20 72 63 20 3d 20 70 2d 3e 53 65 74  s':  rc = p->Set
b350: 75 70 3b 20 20 20 20 20 62 72 65 61 6b 3b 0a 20  up;     break;. 
b360: 20 20 20 20 20 63 61 73 65 20 27 74 27 3a 20 20       case 't':  
b370: 72 63 20 3d 20 70 2d 3e 54 6b 74 46 6d 74 3b 20  rc = p->TktFmt; 
b380: 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20     break;.      
b390: 2f 2a 20 63 61 73 65 20 27 75 27 3a 20 52 45 41  /* case 'u': REA
b3a0: 44 45 52 20 20 20 20 2a 2f 0a 20 20 20 20 20 20  DER    */.      
b3b0: 2f 2a 20 63 61 73 65 20 27 76 27 3a 20 44 45 56  /* case 'v': DEV
b3c0: 45 4c 4f 50 45 52 20 2a 2f 0a 20 20 20 20 20 20  ELOPER */.      
b3d0: 63 61 73 65 20 27 77 27 3a 20 20 72 63 20 3d 20  case 'w':  rc = 
b3e0: 70 2d 3e 57 72 54 6b 74 3b 20 20 20 20 20 62 72  p->WrTkt;     br
b3f0: 65 61 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20  eak;.      case 
b400: 27 78 27 3a 20 20 72 63 20 3d 20 70 2d 3e 50 72  'x':  rc = p->Pr
b410: 69 76 61 74 65 3b 20 20 20 62 72 65 61 6b 3b 0a  ivate;   break;.
b420: 20 20 20 20 20 20 63 61 73 65 20 27 79 27 3a 20        case 'y': 
b430: 20 72 63 20 3d 20 70 2d 3e 57 72 55 6e 76 65 72   rc = p->WrUnver
b440: 3b 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20  ;   break;.     
b450: 20 63 61 73 65 20 27 7a 27 3a 20 20 72 63 20 3d   case 'z':  rc =
b460: 20 70 2d 3e 5a 69 70 3b 20 20 20 20 20 20 20 62   p->Zip;       b
b470: 72 65 61 6b 3b 0a 20 20 20 20 20 20 63 61 73 65  reak;.      case
b480: 20 27 32 27 3a 20 20 72 63 20 3d 20 70 2d 3e 52   '2':  rc = p->R
b490: 64 46 6f 72 75 6d 3b 20 20 20 62 72 65 61 6b 3b  dForum;   break;
b4a0: 0a 20 20 20 20 20 20 63 61 73 65 20 27 33 27 3a  .      case '3':
b4b0: 20 20 72 63 20 3d 20 70 2d 3e 57 72 46 6f 72 75    rc = p->WrForu
b4c0: 6d 3b 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20  m;   break;.    
b4d0: 20 20 63 61 73 65 20 27 34 27 3a 20 20 72 63 20    case '4':  rc 
b4e0: 3d 20 70 2d 3e 57 72 54 46 6f 72 75 6d 3b 20 20  = p->WrTForum;  
b4f0: 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 63 61 73  break;.      cas
b500: 65 20 27 35 27 3a 20 20 72 63 20 3d 20 70 2d 3e  e '5':  rc = p->
b510: 4d 6f 64 46 6f 72 75 6d 3b 20 20 62 72 65 61 6b  ModForum;  break
b520: 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27 36 27  ;.      case '6'
b530: 3a 20 20 72 63 20 3d 20 70 2d 3e 41 64 6d 69 6e  :  rc = p->Admin
b540: 46 6f 72 75 6d 3b 62 72 65 61 6b 3b 0a 20 20 20  Forum;break;.   
b550: 20 20 20 63 61 73 65 20 27 37 27 3a 20 20 72 63     case '7':  rc
b560: 20 3d 20 70 2d 3e 45 6d 61 69 6c 41 6c 65 72 74   = p->EmailAlert
b570: 3b 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 63 61  ;break;.      ca
b580: 73 65 20 27 41 27 3a 20 20 72 63 20 3d 20 70 2d  se 'A':  rc = p-
b590: 3e 41 6e 6e 6f 75 6e 63 65 3b 20 20 62 72 65 61  >Announce;  brea
b5a0: 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27 44  k;.      case 'D
b5b0: 27 3a 20 20 72 63 20 3d 20 70 2d 3e 44 65 62 75  ':  rc = p->Debu
b5c0: 67 3b 20 20 20 20 20 62 72 65 61 6b 3b 0a 20 20  g;     break;.  
b5d0: 20 20 20 20 64 65 66 61 75 6c 74 3a 20 20 20 72      default:   r
b5e0: 63 20 3d 20 30 3b 20 20 20 20 20 20 20 20 20 20  c = 0;          
b5f0: 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 7d 0a 20    break;.    }. 
b600: 20 7d 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a   }.  return rc;.
b610: 7d 0a 0a 2f 2a 0a 2a 2a 20 43 68 61 6e 67 65 20  }../*.** Change 
b620: 74 68 65 20 6c 6f 67 69 6e 20 74 6f 20 7a 55 73  the login to zUs
b630: 65 72 2e 0a 2a 2f 0a 76 6f 69 64 20 6c 6f 67 69  er..*/.void logi
b640: 6e 5f 61 73 5f 75 73 65 72 28 63 6f 6e 73 74 20  n_as_user(const 
b650: 63 68 61 72 20 2a 7a 55 73 65 72 29 7b 0a 20 20  char *zUser){.  
b660: 63 68 61 72 20 2a 7a 43 61 70 20 3d 20 22 22 3b  char *zCap = "";
b670: 20 20 20 2f 2a 20 4e 65 77 20 63 61 70 61 62 69     /* New capabi
b680: 6c 69 74 69 65 73 20 2a 2f 0a 0a 20 20 2f 2a 20  lities */..  /* 
b690: 54 75 72 6e 20 6f 66 66 20 61 6c 6c 20 63 61 70  Turn off all cap
b6a0: 61 62 69 6c 69 74 69 65 73 20 66 72 6f 6d 20 70  abilities from p
b6b0: 72 69 6f 72 20 6c 6f 67 69 6e 73 20 2a 2f 0a 20  rior logins */. 
b6c0: 20 6d 65 6d 73 65 74 28 20 26 67 2e 70 65 72 6d   memset( &g.perm
b6d0: 2c 20 30 2c 20 73 69 7a 65 6f 66 28 67 2e 70 65  , 0, sizeof(g.pe
b6e0: 72 6d 29 20 29 3b 0a 0a 20 20 2f 2a 20 53 65 74  rm) );..  /* Set
b6f0: 20 74 68 65 20 67 6c 6f 62 61 6c 20 76 61 72 69   the global vari
b700: 61 62 6c 65 73 20 72 65 63 6f 72 64 69 6e 67 20  ables recording 
b710: 74 68 65 20 75 73 65 72 69 64 20 61 6e 64 20 6c  the userid and l
b720: 6f 67 69 6e 2e 20 20 54 68 65 0a 20 20 2a 2a 20  ogin.  The.  ** 
b730: 22 6e 6f 62 6f 64 79 22 20 75 73 65 72 20 69 73  "nobody" user is
b740: 20 61 20 73 70 65 63 69 61 6c 20 63 61 73 65 20   a special case 
b750: 69 6e 20 74 68 61 74 20 67 2e 7a 4c 6f 67 69 6e  in that g.zLogin
b760: 3d 3d 30 2e 0a 20 20 2a 2f 0a 20 20 67 2e 75 73  ==0..  */.  g.us
b770: 65 72 55 69 64 20 3d 20 64 62 5f 69 6e 74 28 30  erUid = db_int(0
b780: 2c 20 22 53 45 4c 45 43 54 20 75 69 64 20 46 52  , "SELECT uid FR
b790: 4f 4d 20 75 73 65 72 20 57 48 45 52 45 20 6c 6f  OM user WHERE lo
b7a0: 67 69 6e 3d 25 51 22 2c 20 7a 55 73 65 72 29 3b  gin=%Q", zUser);
b7b0: 0a 20 20 69 66 28 20 67 2e 75 73 65 72 55 69 64  .  if( g.userUid
b7c0: 3d 3d 30 20 29 7b 0a 20 20 20 20 7a 55 73 65 72  ==0 ){.    zUser
b7d0: 20 3d 20 30 3b 0a 20 20 20 20 67 2e 75 73 65 72   = 0;.    g.user
b7e0: 55 69 64 20 3d 20 64 62 5f 69 6e 74 28 30 2c 20  Uid = db_int(0, 
b7f0: 22 53 45 4c 45 43 54 20 75 69 64 20 46 52 4f 4d  "SELECT uid FROM
b800: 20 75 73 65 72 20 57 48 45 52 45 20 6c 6f 67 69   user WHERE logi
b810: 6e 3d 27 6e 6f 62 6f 64 79 27 22 29 3b 0a 20 20  n='nobody'");.  
b820: 7d 0a 20 20 69 66 28 20 67 2e 75 73 65 72 55 69  }.  if( g.userUi
b830: 64 20 29 7b 0a 20 20 20 20 7a 43 61 70 20 3d 20  d ){.    zCap = 
b840: 64 62 5f 74 65 78 74 28 22 22 2c 20 22 53 45 4c  db_text("", "SEL
b850: 45 43 54 20 63 61 70 20 46 52 4f 4d 20 75 73 65  ECT cap FROM use
b860: 72 20 57 48 45 52 45 20 75 69 64 3d 25 64 22 2c  r WHERE uid=%d",
b870: 20 67 2e 75 73 65 72 55 69 64 29 3b 0a 20 20 7d   g.userUid);.  }
b880: 0a 20 20 69 66 28 20 66 6f 73 73 69 6c 5f 73 74  .  if( fossil_st
b890: 72 63 6d 70 28 7a 55 73 65 72 2c 22 6e 6f 62 6f  rcmp(zUser,"nobo
b8a0: 64 79 22 29 3d 3d 30 20 29 20 7a 55 73 65 72 20  dy")==0 ) zUser 
b8b0: 3d 20 30 3b 0a 20 20 67 2e 7a 4c 6f 67 69 6e 20  = 0;.  g.zLogin 
b8c0: 3d 20 66 6f 73 73 69 6c 5f 73 74 72 64 75 70 28  = fossil_strdup(
b8d0: 7a 55 73 65 72 29 3b 0a 0a 20 20 2f 2a 20 53 65  zUser);..  /* Se
b8e0: 74 20 74 68 65 20 63 61 70 61 62 69 6c 69 74 69  t the capabiliti
b8f0: 65 73 20 2a 2f 0a 20 20 6c 6f 67 69 6e 5f 73 65  es */.  login_se
b900: 74 5f 63 61 70 61 62 69 6c 69 74 69 65 73 28 7a  t_capabilities(z
b910: 43 61 70 2c 20 30 29 3b 0a 20 20 6c 6f 67 69 6e  Cap, 0);.  login
b920: 5f 61 6e 6f 6e 5f 6f 6e 63 65 20 3d 20 31 3b 0a  _anon_once = 1;.
b930: 20 20 6c 6f 67 69 6e 5f 73 65 74 5f 61 6e 6f 6e    login_set_anon
b940: 5f 6e 6f 62 6f 64 79 5f 63 61 70 61 62 69 6c 69  _nobody_capabili
b950: 74 69 65 73 28 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a  ties();.}../*.**
b960: 20 52 65 74 75 72 6e 20 74 72 75 65 20 69 66 20   Return true if 
b970: 74 68 65 20 75 73 65 72 20 69 73 20 22 6e 6f 62  the user is "nob
b980: 6f 64 79 22 0a 2a 2f 0a 69 6e 74 20 6c 6f 67 69  ody".*/.int logi
b990: 6e 5f 69 73 5f 6e 6f 62 6f 64 79 28 76 6f 69 64  n_is_nobody(void
b9a0: 29 7b 0a 20 20 72 65 74 75 72 6e 20 67 2e 7a 4c  ){.  return g.zL
b9b0: 6f 67 69 6e 3d 3d 30 20 7c 7c 20 67 2e 7a 4c 6f  ogin==0 || g.zLo
b9c0: 67 69 6e 5b 30 5d 3d 3d 30 20 7c 7c 20 66 6f 73  gin[0]==0 || fos
b9d0: 73 69 6c 5f 73 74 72 63 6d 70 28 67 2e 7a 4c 6f  sil_strcmp(g.zLo
b9e0: 67 69 6e 2c 22 6e 6f 62 6f 64 79 22 29 3d 3d 30  gin,"nobody")==0
b9f0: 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 52 65 74 75 72  ;.}../*.** Retur
ba00: 6e 20 74 72 75 65 20 69 66 20 74 68 65 20 75 73  n true if the us
ba10: 65 72 20 69 73 20 61 20 73 70 65 63 69 66 69 63  er is a specific
ba20: 20 69 6e 64 69 76 69 64 75 61 6c 2c 20 6e 6f 74   individual, not
ba30: 20 22 6e 6f 62 6f 64 79 22 20 6f 72 0a 2a 2a 20   "nobody" or.** 
ba40: 22 61 6e 6f 6e 79 6d 6f 75 73 22 2e 0a 2a 2f 0a  "anonymous"..*/.
ba50: 69 6e 74 20 6c 6f 67 69 6e 5f 69 73 5f 69 6e 64  int login_is_ind
ba60: 69 76 69 64 75 61 6c 28 76 6f 69 64 29 7b 0a 20  ividual(void){. 
ba70: 20 72 65 74 75 72 6e 20 67 2e 7a 4c 6f 67 69 6e   return g.zLogin
ba80: 21 3d 30 20 26 26 20 67 2e 7a 4c 6f 67 69 6e 5b  !=0 && g.zLogin[
ba90: 30 5d 21 3d 30 20 26 26 20 66 6f 73 73 69 6c 5f  0]!=0 && fossil_
baa0: 73 74 72 63 6d 70 28 67 2e 7a 4c 6f 67 69 6e 2c  strcmp(g.zLogin,
bab0: 22 6e 6f 62 6f 64 79 22 29 21 3d 30 0a 20 20 20  "nobody")!=0.   
bac0: 20 20 20 20 20 20 20 20 26 26 20 66 6f 73 73 69          && fossi
bad0: 6c 5f 73 74 72 63 6d 70 28 67 2e 7a 4c 6f 67 69  l_strcmp(g.zLogi
bae0: 6e 2c 22 61 6e 6f 6e 79 6d 6f 75 73 22 29 21 3d  n,"anonymous")!=
baf0: 30 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 52 65 74 75  0;.}../*.** Retu
bb00: 72 6e 20 74 68 65 20 6c 6f 67 69 6e 20 6e 61 6d  rn the login nam
bb10: 65 2e 20 20 49 66 20 6e 6f 20 6c 6f 67 69 6e 20  e.  If no login 
bb20: 6e 61 6d 65 20 69 73 20 73 70 65 63 69 66 69 65  name is specifie
bb30: 64 2c 20 72 65 74 75 72 6e 20 22 6e 6f 62 6f 64  d, return "nobod
bb40: 79 22 2e 0a 2a 2f 0a 63 6f 6e 73 74 20 63 68 61  y"..*/.const cha
bb50: 72 20 2a 6c 6f 67 69 6e 5f 6e 61 6d 65 28 76 6f  r *login_name(vo
bb60: 69 64 29 7b 0a 20 20 72 65 74 75 72 6e 20 28 67  id){.  return (g
bb70: 2e 7a 4c 6f 67 69 6e 20 26 26 20 67 2e 7a 4c 6f  .zLogin && g.zLo
bb80: 67 69 6e 5b 30 5d 29 20 3f 20 67 2e 7a 4c 6f 67  gin[0]) ? g.zLog
bb90: 69 6e 20 3a 20 22 6e 6f 62 6f 64 79 22 3b 0a 7d  in : "nobody";.}
bba0: 0a 0a 2f 2a 0a 2a 2a 20 43 61 6c 6c 20 74 68 69  ../*.** Call thi
bbb0: 73 20 72 6f 75 74 69 6e 65 20 77 68 65 6e 20 74  s routine when t
bbc0: 68 65 20 63 72 65 64 65 6e 74 69 61 6c 20 63 68  he credential ch
bbd0: 65 63 6b 20 66 61 69 6c 73 2e 20 20 49 74 20 63  eck fails.  It c
bbe0: 61 75 73 65 73 0a 2a 2a 20 61 20 72 65 64 69 72  auses.** a redir
bbf0: 65 63 74 20 74 6f 20 74 68 65 20 22 6c 6f 67 69  ect to the "logi
bc00: 6e 22 20 70 61 67 65 2e 0a 2a 2f 0a 76 6f 69 64  n" page..*/.void
bc10: 20 6c 6f 67 69 6e 5f 6e 65 65 64 65 64 28 69 6e   login_needed(in
bc20: 74 20 61 6e 6f 6e 4f 6b 29 7b 0a 23 69 66 64 65  t anonOk){.#ifde
bc30: 66 20 46 4f 53 53 49 4c 5f 45 4e 41 42 4c 45 5f  f FOSSIL_ENABLE_
bc40: 4a 53 4f 4e 0a 20 20 69 66 28 67 2e 6a 73 6f 6e  JSON.  if(g.json
bc50: 2e 69 73 4a 73 6f 6e 4d 6f 64 65 29 7b 0a 20 20  .isJsonMode){.  
bc60: 20 20 6a 73 6f 6e 5f 65 72 72 28 20 46 53 4c 5f    json_err( FSL_
bc70: 4a 53 4f 4e 5f 45 5f 44 45 4e 49 45 44 2c 20 4e  JSON_E_DENIED, N
bc80: 55 4c 4c 2c 20 31 20 29 3b 0a 20 20 20 20 66 6f  ULL, 1 );.    fo
bc90: 73 73 69 6c 5f 65 78 69 74 28 30 29 3b 0a 20 20  ssil_exit(0);.  
bca0: 20 20 2f 2a 20 4e 4f 54 52 45 41 43 48 45 44 20    /* NOTREACHED 
bcb0: 2a 2f 0a 20 20 20 20 61 73 73 65 72 74 28 30 29  */.    assert(0)
bcc0: 3b 0a 20 20 7d 65 6c 73 65 0a 23 65 6e 64 69 66  ;.  }else.#endif
bcd0: 20 2f 2a 20 46 4f 53 53 49 4c 5f 45 4e 41 42 4c   /* FOSSIL_ENABL
bce0: 45 5f 4a 53 4f 4e 20 2a 2f 0a 20 20 7b 0a 20 20  E_JSON */.  {.  
bcf0: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 55    const char *zU
bd00: 72 6c 20 3d 20 50 44 28 22 52 45 51 55 45 53 54  rl = PD("REQUEST
bd10: 5f 55 52 49 22 2c 20 22 69 6e 64 65 78 22 29 3b  _URI", "index");
bd20: 0a 20 20 20 20 63 6f 6e 73 74 20 63 68 61 72 20  .    const char 
bd30: 2a 7a 51 53 20 3d 20 50 28 22 51 55 45 52 59 5f  *zQS = P("QUERY_
bd40: 53 54 52 49 4e 47 22 29 3b 0a 20 20 20 20 42 6c  STRING");.    Bl
bd50: 6f 62 20 72 65 64 69 72 3b 0a 20 20 20 20 62 6c  ob redir;.    bl
bd60: 6f 62 5f 69 6e 69 74 28 26 72 65 64 69 72 2c 20  ob_init(&redir, 
bd70: 30 2c 20 30 29 3b 0a 20 20 20 20 69 66 28 20 6c  0, 0);.    if( l
bd80: 6f 67 69 6e 5f 77 61 6e 74 73 5f 68 74 74 70 73  ogin_wants_https
bd90: 5f 72 65 64 69 72 65 63 74 28 29 20 26 26 20 21  _redirect() && !
bda0: 67 2e 73 73 6c 4e 6f 74 41 76 61 69 6c 61 62 6c  g.sslNotAvailabl
bdb0: 65 20 29 7b 0a 20 20 20 20 20 20 62 6c 6f 62 5f  e ){.      blob_
bdc0: 61 70 70 65 6e 64 66 28 26 72 65 64 69 72 2c 20  appendf(&redir, 
bdd0: 22 25 73 2f 6c 6f 67 69 6e 3f 67 3d 25 54 22 2c  "%s/login?g=%T",
bde0: 20 67 2e 7a 48 74 74 70 73 55 52 4c 2c 20 7a 55   g.zHttpsURL, zU
bdf0: 72 6c 29 3b 0a 20 20 20 20 7d 65 6c 73 65 7b 0a  rl);.    }else{.
be00: 20 20 20 20 20 20 62 6c 6f 62 5f 61 70 70 65 6e        blob_appen
be10: 64 66 28 26 72 65 64 69 72 2c 20 22 25 52 2f 6c  df(&redir, "%R/l
be20: 6f 67 69 6e 3f 67 3d 25 54 22 2c 20 7a 55 72 6c  ogin?g=%T", zUrl
be30: 29 3b 0a 20 20 20 20 7d 0a 20 20 20 20 69 66 28  );.    }.    if(
be40: 20 61 6e 6f 6e 4f 6b 20 29 20 62 6c 6f 62 5f 61   anonOk ) blob_a
be50: 70 70 65 6e 64 28 26 72 65 64 69 72 2c 20 22 26  ppend(&redir, "&
be60: 61 6e 6f 6e 22 2c 20 35 29 3b 0a 20 20 20 20 69  anon", 5);.    i
be70: 66 28 20 7a 51 53 20 26 26 20 7a 51 53 5b 30 5d  f( zQS && zQS[0]
be80: 20 29 7b 0a 20 20 20 20 20 20 62 6c 6f 62 5f 61   ){.      blob_a
be90: 70 70 65 6e 64 66 28 26 72 65 64 69 72 2c 20 22  ppendf(&redir, "
bea0: 26 25 73 22 2c 20 7a 51 53 29 3b 0a 20 20 20 20  &%s", zQS);.    
beb0: 7d 0a 20 20 20 20 63 67 69 5f 72 65 64 69 72 65  }.    cgi_redire
bec0: 63 74 28 62 6c 6f 62 5f 73 74 72 28 26 72 65 64  ct(blob_str(&red
bed0: 69 72 29 29 3b 0a 20 20 20 20 2f 2a 20 4e 4f 54  ir));.    /* NOT
bee0: 52 45 41 43 48 45 44 20 2a 2f 0a 20 20 20 20 61  REACHED */.    a
bef0: 73 73 65 72 74 28 30 29 3b 0a 20 20 7d 0a 7d 0a  ssert(0);.  }.}.
bf00: 0a 2f 2a 0a 2a 2a 20 43 61 6c 6c 20 74 68 69 73  ./*.** Call this
bf10: 20 72 6f 75 74 69 6e 65 20 69 66 20 74 68 65 20   routine if the 
bf20: 75 73 65 72 20 6c 61 63 6b 73 20 67 2e 70 65 72  user lacks g.per
bf30: 6d 2e 48 79 70 65 72 6c 69 6e 6b 20 70 65 72 6d  m.Hyperlink perm
bf40: 69 73 73 69 6f 6e 2e 20 20 49 66 0a 2a 2a 20 74  ission.  If.** t
bf50: 68 65 20 61 6e 6f 6e 79 6d 6f 75 73 20 75 73 65  he anonymous use
bf60: 72 20 68 61 73 20 48 79 70 65 72 6c 69 6e 6b 20  r has Hyperlink 
bf70: 70 65 72 6d 69 73 73 69 6f 6e 2c 20 74 68 65 6e  permission, then
bf80: 20 70 61 69 6e 74 20 61 20 6d 65 73 61 67 65 0a   paint a mesage.
bf90: 2a 2a 20 74 6f 20 69 6e 66 6f 72 6d 20 74 68 65  ** to inform the
bfa0: 20 75 73 65 72 20 74 68 61 74 20 6d 75 63 68 20   user that much 
bfb0: 6d 6f 72 65 20 69 6e 66 6f 72 6d 61 74 69 6f 6e  more information
bfc0: 20 69 73 20 61 76 61 69 6c 61 62 6c 65 20 62 79   is available by
bfd0: 0a 2a 2a 20 6c 6f 67 67 69 6e 67 20 69 6e 20 61  .** logging in a
bfe0: 73 20 61 6e 6f 6e 79 6d 6f 75 73 2e 0a 2a 2f 0a  s anonymous..*/.
bff0: 76 6f 69 64 20 6c 6f 67 69 6e 5f 61 6e 6f 6e 79  void login_anony
c000: 6d 6f 75 73 5f 61 76 61 69 6c 61 62 6c 65 28 76  mous_available(v
c010: 6f 69 64 29 7b 0a 20 20 69 66 28 20 21 67 2e 70  oid){.  if( !g.p
c020: 65 72 6d 2e 48 79 70 65 72 6c 69 6e 6b 20 26 26  erm.Hyperlink &&
c030: 20 67 2e 61 6e 6f 6e 2e 48 79 70 65 72 6c 69 6e   g.anon.Hyperlin
c040: 6b 20 29 7b 0a 20 20 20 20 63 6f 6e 73 74 20 63  k ){.    const c
c050: 68 61 72 20 2a 7a 55 72 6c 20 3d 20 50 44 28 22  har *zUrl = PD("
c060: 52 45 51 55 45 53 54 5f 55 52 49 22 2c 20 22 69  REQUEST_URI", "i
c070: 6e 64 65 78 22 29 3b 0a 20 20 20 20 40 20 3c 70  ndex");.    @ <p
c080: 3e 4d 61 6e 79 20 3c 73 70 61 6e 20 63 6c 61 73  >Many <span clas
c090: 73 3d 22 64 69 73 61 62 6c 65 64 22 3e 68 79 70  s="disabled">hyp
c0a0: 65 72 6c 69 6e 6b 73 20 61 72 65 20 64 69 73 61  erlinks are disa
c0b0: 62 6c 65 64 2e 3c 2f 73 70 61 6e 3e 3c 62 72 20  bled.</span><br 
c0c0: 2f 3e 0a 20 20 20 20 40 20 55 73 65 20 3c 61 20  />.    @ Use <a 
c0d0: 68 72 65 66 3d 22 25 52 2f 6c 6f 67 69 6e 3f 61  href="%R/login?a
c0e0: 6e 6f 6e 3d 31 26 61 6d 70 3b 67 3d 25 54 28 7a  non=1&amp;g=%T(z
c0f0: 55 72 6c 29 22 3e 61 6e 6f 6e 79 6d 6f 75 73 20  Url)">anonymous 
c100: 6c 6f 67 69 6e 3c 2f 61 3e 0a 20 20 20 20 40 20  login</a>.    @ 
c110: 74 6f 20 65 6e 61 62 6c 65 20 68 79 70 65 72 6c  to enable hyperl
c120: 69 6e 6b 73 2e 3c 2f 70 3e 0a 20 20 7d 0a 7d 0a  inks.</p>.  }.}.
c130: 0a 2f 2a 0a 2a 2a 20 57 68 69 6c 65 20 72 65 6e  ./*.** While ren
c140: 64 65 72 69 6e 67 20 61 20 66 6f 72 6d 2c 20 63  dering a form, c
c150: 61 6c 6c 20 74 68 69 73 20 72 6f 75 74 69 6e 65  all this routine
c160: 20 74 6f 20 61 64 64 20 74 68 65 20 41 6e 74 69   to add the Anti
c170: 2d 43 53 52 46 20 74 6f 6b 65 6e 0a 2a 2a 20 61  -CSRF token.** a
c180: 73 20 61 20 68 69 64 64 65 6e 20 65 6c 65 6d 65  s a hidden eleme
c190: 6e 74 20 6f 66 20 74 68 65 20 66 6f 72 6d 2e 0a  nt of the form..
c1a0: 2a 2f 0a 76 6f 69 64 20 6c 6f 67 69 6e 5f 69 6e  */.void login_in
c1b0: 73 65 72 74 5f 63 73 72 66 5f 73 65 63 72 65 74  sert_csrf_secret
c1c0: 28 76 6f 69 64 29 7b 0a 20 20 40 20 3c 69 6e 70  (void){.  @ <inp
c1d0: 75 74 20 74 79 70 65 3d 22 68 69 64 64 65 6e 22  ut type="hidden"
c1e0: 20 6e 61 6d 65 3d 22 63 73 72 66 22 20 76 61 6c   name="csrf" val
c1f0: 75 65 3d 22 25 73 28 67 2e 7a 43 73 72 66 54 6f  ue="%s(g.zCsrfTo
c200: 6b 65 6e 29 22 20 2f 3e 0a 7d 0a 0a 2f 2a 0a 2a  ken)" />.}../*.*
c210: 2a 20 42 65 66 6f 72 65 20 75 73 69 6e 67 20 74  * Before using t
c220: 68 65 20 72 65 73 75 6c 74 73 20 6f 66 20 61 20  he results of a 
c230: 66 6f 72 6d 2c 20 66 69 72 73 74 20 63 61 6c 6c  form, first call
c240: 20 74 68 69 73 20 72 6f 75 74 69 6e 65 20 74 6f   this routine to
c250: 20 76 65 72 69 66 79 0a 2a 2a 20 74 68 61 74 20   verify.** that 
c260: 74 68 69 73 20 41 6e 74 69 2d 43 53 52 46 20 74  this Anti-CSRF t
c270: 6f 6b 65 6e 20 69 73 20 70 72 65 73 65 6e 74 20  oken is present 
c280: 61 6e 64 20 69 73 20 76 61 6c 69 64 2e 20 20 49  and is valid.  I
c290: 66 20 74 68 65 20 41 6e 74 69 2d 43 53 52 46 20  f the Anti-CSRF 
c2a0: 74 6f 6b 65 6e 0a 2a 2a 20 69 73 20 6d 69 73 73  token.** is miss
c2b0: 69 6e 67 20 6f 72 20 69 73 20 69 6e 63 6f 72 72  ing or is incorr
c2c0: 65 63 74 2c 20 74 68 61 74 20 69 6e 64 69 63 61  ect, that indica
c2d0: 74 65 73 20 61 20 63 72 6f 73 73 2d 73 69 74 65  tes a cross-site
c2e0: 20 73 63 72 69 70 74 69 6e 67 20 61 74 74 61 63   scripting attac
c2f0: 6b 2e 0a 2a 2a 20 49 66 20 74 68 65 20 65 76 65  k..** If the eve
c300: 6e 74 20 6f 66 20 61 6e 20 61 74 74 61 63 6b 20  nt of an attack 
c310: 69 73 20 64 65 74 65 63 74 65 64 2c 20 61 6e 20  is detected, an 
c320: 65 72 72 6f 72 20 6d 65 73 73 61 67 65 20 69 73  error message is
c330: 20 67 65 6e 65 72 61 74 65 64 20 61 6e 64 0a 2a   generated and.*
c340: 2a 20 61 6c 6c 20 66 75 72 74 68 65 72 20 70 72  * all further pr
c350: 6f 63 65 73 73 69 6e 67 20 69 73 20 61 62 6f 72  ocessing is abor
c360: 74 65 64 2e 0a 2a 2f 0a 76 6f 69 64 20 6c 6f 67  ted..*/.void log
c370: 69 6e 5f 76 65 72 69 66 79 5f 63 73 72 66 5f 73  in_verify_csrf_s
c380: 65 63 72 65 74 28 76 6f 69 64 29 7b 0a 20 20 69  ecret(void){.  i
c390: 66 28 20 67 2e 6f 6b 43 73 72 66 20 29 20 72 65  f( g.okCsrf ) re
c3a0: 74 75 72 6e 3b 0a 20 20 69 66 28 20 66 6f 73 73  turn;.  if( foss
c3b0: 69 6c 5f 73 74 72 63 6d 70 28 50 28 22 63 73 72  il_strcmp(P("csr
c3c0: 66 22 29 2c 20 67 2e 7a 43 73 72 66 54 6f 6b 65  f"), g.zCsrfToke
c3d0: 6e 29 3d 3d 30 20 29 7b 0a 20 20 20 20 67 2e 6f  n)==0 ){.    g.o
c3e0: 6b 43 73 72 66 20 3d 20 31 3b 0a 20 20 20 20 72  kCsrf = 1;.    r
c3f0: 65 74 75 72 6e 3b 0a 20 20 7d 0a 20 20 66 6f 73  eturn;.  }.  fos
c400: 73 69 6c 5f 66 61 74 61 6c 28 22 43 72 6f 73 73  sil_fatal("Cross
c410: 2d 73 69 74 65 20 72 65 71 75 65 73 74 20 66 6f  -site request fo
c420: 72 67 65 72 79 20 61 74 74 65 6d 70 74 22 29 3b  rgery attempt");
c430: 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 57 45 42 50 41 47  .}../*.** WEBPAG
c440: 45 3a 20 72 65 67 69 73 74 65 72 0a 2a 2a 0a 2a  E: register.**.*
c450: 2a 20 50 61 67 65 20 74 6f 20 61 6c 6c 6f 77 20  * Page to allow 
c460: 75 73 65 72 73 20 74 6f 20 73 65 6c 66 2d 72 65  users to self-re
c470: 67 69 73 74 65 72 2e 20 20 54 68 65 20 22 73 65  gister.  The "se
c480: 6c 66 2d 72 65 67 69 73 74 65 72 22 20 73 65 74  lf-register" set
c490: 74 69 6e 67 0a 2a 2a 20 6d 75 73 74 20 62 65 20  ting.** must be 
c4a0: 65 6e 61 62 6c 65 64 20 66 6f 72 20 74 68 69 73  enabled for this
c4b0: 20 70 61 67 65 20 74 6f 20 6f 70 65 72 61 74 65   page to operate
c4c0: 2e 0a 2a 2f 0a 76 6f 69 64 20 72 65 67 69 73 74  ..*/.void regist
c4d0: 65 72 5f 70 61 67 65 28 76 6f 69 64 29 7b 0a 20  er_page(void){. 
c4e0: 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 55 73   const char *zUs
c4f0: 65 72 49 44 2c 20 2a 7a 50 61 73 73 77 64 2c 20  erID, *zPasswd, 
c500: 2a 7a 43 6f 6e 66 69 72 6d 2c 20 2a 7a 45 41 64  *zConfirm, *zEAd
c510: 64 72 3b 0a 20 20 63 6f 6e 73 74 20 63 68 61 72  dr;.  const char
c520: 20 2a 7a 44 4e 61 6d 65 3b 0a 20 20 75 6e 73 69   *zDName;.  unsi
c530: 67 6e 65 64 20 69 6e 74 20 75 53 65 65 64 3b 0a  gned int uSeed;.
c540: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 44    const char *zD
c550: 65 63 6f 64 65 64 3b 0a 20 20 63 68 61 72 20 2a  ecoded;.  char *
c560: 7a 43 61 70 74 63 68 61 3b 0a 20 20 69 6e 74 20  zCaptcha;.  int 
c570: 69 45 72 72 4c 69 6e 65 20 3d 20 2d 31 3b 0a 20  iErrLine = -1;. 
c580: 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 45 72   const char *zEr
c590: 72 20 3d 20 30 3b 0a 20 20 63 68 61 72 20 2a 7a  r = 0;.  char *z
c5a0: 50 65 72 6d 73 3b 20 20 20 20 20 20 20 20 20 20  Perms;          
c5b0: 20 20 20 2f 2a 20 50 65 72 6d 69 73 73 69 6f 6e     /* Permission
c5c0: 73 20 66 6f 72 20 74 68 65 20 64 65 66 61 75 6c  s for the defaul
c5d0: 74 20 75 73 65 72 20 2a 2f 0a 20 20 69 6e 74 20  t user */.  int 
c5e0: 63 61 6e 44 6f 41 6c 65 72 74 73 20 3d 20 30 3b  canDoAlerts = 0;
c5f0: 20 20 20 20 20 20 2f 2a 20 54 72 75 65 20 69 66        /* True if
c600: 20 72 65 63 65 69 76 69 6e 67 20 65 6d 61 69 6c   receiving email
c610: 20 61 6c 65 72 74 73 20 69 73 20 70 6f 73 73 69   alerts is possi
c620: 62 6c 65 20 2a 2f 0a 20 20 69 66 28 20 21 64 62  ble */.  if( !db
c630: 5f 67 65 74 5f 62 6f 6f 6c 65 61 6e 28 22 73 65  _get_boolean("se
c640: 6c 66 2d 72 65 67 69 73 74 65 72 22 2c 20 30 29  lf-register", 0)
c650: 20 29 7b 0a 20 20 20 20 73 74 79 6c 65 5f 68 65   ){.    style_he
c660: 61 64 65 72 28 22 52 65 67 69 73 74 72 61 74 69  ader("Registrati
c670: 6f 6e 20 6e 6f 74 20 70 6f 73 73 69 62 6c 65 22  on not possible"
c680: 29 3b 0a 20 20 20 20 40 20 3c 70 3e 54 68 69 73  );.    @ <p>This
c690: 20 70 72 6f 6a 65 63 74 20 64 6f 65 73 20 6e 6f   project does no
c6a0: 74 20 61 6c 6c 6f 77 20 75 73 65 72 20 73 65 6c  t allow user sel
c6b0: 66 2d 72 65 67 69 73 74 72 61 74 69 6f 6e 2e 20  f-registration. 
c6c0: 50 6c 65 61 73 65 20 63 6f 6e 74 61 63 74 20 74  Please contact t
c6d0: 68 65 0a 20 20 20 20 40 20 70 72 6f 6a 65 63 74  he.    @ project
c6e0: 20 61 64 6d 69 6e 69 73 74 72 61 74 6f 72 20 74   administrator t
c6f0: 6f 20 6f 62 74 61 69 6e 20 61 6e 20 61 63 63 6f  o obtain an acco
c700: 75 6e 74 2e 3c 2f 70 3e 0a 20 20 20 20 73 74 79  unt.</p>.    sty
c710: 6c 65 5f 66 6f 6f 74 65 72 28 29 3b 0a 20 20 20  le_footer();.   
c720: 20 72 65 74 75 72 6e 3b 0a 20 20 7d 0a 20 20 7a   return;.  }.  z
c730: 50 65 72 6d 73 20 3d 20 64 62 5f 67 65 74 28 22  Perms = db_get("
c740: 64 65 66 61 75 6c 74 2d 70 65 72 6d 73 22 2c 22  default-perms","
c750: 75 22 29 3b 0a 0a 20 20 2f 2a 20 50 72 6f 6d 70  u");..  /* Promp
c760: 74 20 74 68 65 20 75 73 65 72 20 66 6f 72 20 65  t the user for e
c770: 6d 61 69 6c 20 61 6c 65 72 74 73 20 69 66 20 74  mail alerts if t
c780: 68 69 73 20 72 65 70 6f 73 69 74 6f 72 79 20 69  his repository i
c790: 73 20 63 6f 6e 66 69 67 75 72 65 64 20 66 6f 72  s configured for
c7a0: 0a 20 20 2a 2a 20 65 6d 61 69 6c 20 61 6c 65 72  .  ** email aler
c7b0: 74 73 20 61 6e 64 20 69 66 20 74 68 65 20 64 65  ts and if the de
c7c0: 66 61 75 6c 74 20 70 65 72 6d 69 73 73 69 6f 6e  fault permission
c7d0: 73 20 69 6e 63 6c 75 64 65 20 22 37 22 20 2a 2f  s include "7" */
c7e0: 0a 20 20 63 61 6e 44 6f 41 6c 65 72 74 73 20 3d  .  canDoAlerts =
c7f0: 20 65 6d 61 69 6c 5f 74 61 62 6c 65 73 5f 65 78   email_tables_ex
c800: 69 73 74 28 29 20 26 26 20 64 62 5f 69 6e 74 28  ist() && db_int(
c810: 30 2c 0a 20 20 20 20 22 53 45 4c 45 43 54 20 66  0,.    "SELECT f
c820: 75 6c 6c 63 61 70 28 25 51 29 20 47 4c 4f 42 20  ullcap(%Q) GLOB 
c830: 27 2a 37 2a 27 22 2c 20 7a 50 65 72 6d 73 0a 20  '*7*'", zPerms. 
c840: 20 29 3b 0a 0a 20 20 7a 55 73 65 72 49 44 20 3d   );..  zUserID =
c850: 20 50 44 54 28 22 75 22 2c 22 22 29 3b 0a 20 20   PDT("u","");.  
c860: 7a 50 61 73 73 77 64 20 3d 20 50 44 54 28 22 70  zPasswd = PDT("p
c870: 22 2c 22 22 29 3b 0a 20 20 7a 43 6f 6e 66 69 72  ","");.  zConfir
c880: 6d 20 3d 20 50 44 54 28 22 63 70 22 2c 22 22 29  m = PDT("cp","")
c890: 3b 0a 20 20 7a 45 41 64 64 72 20 3d 20 50 44 54  ;.  zEAddr = PDT
c8a0: 28 22 65 61 22 2c 22 22 29 3b 0a 20 20 7a 44 4e  ("ea","");.  zDN
c8b0: 61 6d 65 20 3d 20 50 44 54 28 22 64 6e 22 2c 22  ame = PDT("dn","
c8c0: 22 29 3b 0a 0a 20 20 2f 2a 20 54 72 79 20 74 6f  ");..  /* Try to
c8d0: 20 6d 61 6b 65 20 61 6e 79 20 73 65 6e 73 65 20   make any sense 
c8e0: 66 72 6f 6d 20 75 73 65 72 20 69 6e 70 75 74 2e  from user input.
c8f0: 20 2a 2f 0a 20 20 69 66 28 20 50 28 22 6e 65 77   */.  if( P("new
c900: 22 29 3d 3d 30 20 7c 7c 20 21 63 67 69 5f 63 73  ")==0 || !cgi_cs
c910: 72 66 5f 73 61 66 65 28 31 29 20 29 7b 0a 20 20  rf_safe(1) ){.  
c920: 20 20 2f 2a 20 54 68 69 73 20 69 73 20 6e 6f 74    /* This is not
c930: 20 61 20 76 61 6c 69 64 20 66 6f 72 6d 20 73 75   a valid form su
c940: 62 6d 69 73 73 69 6f 6e 2e 20 20 46 61 6c 6c 20  bmission.  Fall 
c950: 74 68 72 6f 75 67 68 20 69 6e 74 6f 0a 20 20 20  through into.   
c960: 20 2a 2a 20 74 68 65 20 66 6f 72 6d 20 64 69 73   ** the form dis
c970: 70 6c 61 79 20 2a 2f 0a 20 20 7d 65 6c 73 65 20  play */.  }else 
c980: 69 66 28 20 21 63 61 70 74 63 68 61 5f 69 73 5f  if( !captcha_is_
c990: 63 6f 72 72 65 63 74 28 31 29 20 29 7b 0a 20 20  correct(1) ){.  
c9a0: 20 20 69 45 72 72 4c 69 6e 65 20 3d 20 36 3b 0a    iErrLine = 6;.
c9b0: 20 20 20 20 7a 45 72 72 20 3d 20 22 49 6e 63 6f      zErr = "Inco
c9c0: 72 72 65 63 74 20 43 41 50 54 43 48 41 22 3b 0a  rrect CAPTCHA";.
c9d0: 20 20 7d 65 6c 73 65 20 69 66 28 20 73 74 72 6c    }else if( strl
c9e0: 65 6e 28 7a 55 73 65 72 49 44 29 3c 33 20 29 7b  en(zUserID)<3 ){
c9f0: 0a 20 20 20 20 69 45 72 72 4c 69 6e 65 20 3d 20  .    iErrLine = 
ca00: 31 3b 0a 20 20 20 20 7a 45 72 72 20 3d 20 22 55  1;.    zErr = "U
ca10: 73 65 72 20 49 44 20 74 6f 6f 20 73 68 6f 72 74  ser ID too short
ca20: 2e 20 4d 75 73 74 20 62 65 20 61 74 20 6c 65 61  . Must be at lea
ca30: 73 74 20 33 20 63 68 61 72 61 63 74 65 72 73 2e  st 3 characters.
ca40: 22 3b 0a 20 20 7d 65 6c 73 65 20 69 66 28 20 73  ";.  }else if( s
ca50: 71 6c 69 74 65 33 5f 73 74 72 67 6c 6f 62 28 22  qlite3_strglob("
ca60: 2a 5b 5e 2d 61 2d 7a 41 2d 5a 30 2d 39 5f 2e 5d  *[^-a-zA-Z0-9_.]
ca70: 2a 22 2c 7a 55 73 65 72 49 44 29 3d 3d 30 20 29  *",zUserID)==0 )
ca80: 7b 0a 20 20 20 20 69 45 72 72 4c 69 6e 65 20 3d  {.    iErrLine =
ca90: 20 31 3b 0a 20 20 20 20 7a 45 72 72 20 3d 20 22   1;.    zErr = "
caa0: 55 73 65 72 20 49 44 20 6d 61 79 20 6e 6f 74 20  User ID may not 
cab0: 63 6f 6e 74 61 69 6e 20 73 70 61 63 65 73 20 6f  contain spaces o
cac0: 72 20 73 70 65 63 69 61 6c 20 63 68 61 72 61 63  r special charac
cad0: 74 65 72 73 2e 22 3b 0a 20 20 7d 65 6c 73 65 20  ters.";.  }else 
cae0: 69 66 28 20 7a 44 4e 61 6d 65 5b 30 5d 3d 3d 30  if( zDName[0]==0
caf0: 20 29 7b 0a 20 20 20 20 69 45 72 72 4c 69 6e 65   ){.    iErrLine
cb00: 20 3d 20 32 3b 0a 20 20 20 20 7a 45 72 72 20 3d   = 2;.    zErr =
cb10: 20 22 52 65 71 75 69 72 65 64 22 3b 0a 20 20 7d   "Required";.  }
cb20: 65 6c 73 65 20 69 66 28 20 7a 45 41 64 64 72 5b  else if( zEAddr[
cb30: 30 5d 3d 3d 30 20 29 7b 0a 20 20 20 20 69 45 72  0]==0 ){.    iEr
cb40: 72 4c 69 6e 65 20 3d 20 33 3b 0a 20 20 20 20 7a  rLine = 3;.    z
cb50: 45 72 72 20 3d 20 22 52 65 71 75 69 72 65 64 22  Err = "Required"
cb60: 3b 0a 20 20 7d 65 6c 73 65 20 69 66 28 20 65 6d  ;.  }else if( em
cb70: 61 69 6c 5f 63 6f 70 79 5f 61 64 64 72 28 7a 45  ail_copy_addr(zE
cb80: 41 64 64 72 2c 30 29 3d 3d 30 20 29 7b 0a 20 20  Addr,0)==0 ){.  
cb90: 20 20 69 45 72 72 4c 69 6e 65 20 3d 20 33 3b 0a    iErrLine = 3;.
cba0: 20 20 20 20 7a 45 72 72 20 3d 20 22 4e 6f 74 20      zErr = "Not 
cbb0: 61 20 76 61 6c 69 64 20 65 6d 61 69 6c 20 61 64  a valid email ad
cbc0: 64 72 65 73 73 22 3b 0a 20 20 7d 65 6c 73 65 20  dress";.  }else 
cbd0: 69 66 28 20 73 74 72 6c 65 6e 28 7a 50 61 73 73  if( strlen(zPass
cbe0: 77 64 29 3c 36 20 29 7b 0a 20 20 20 20 69 45 72  wd)<6 ){.    iEr
cbf0: 72 4c 69 6e 65 20 3d 20 34 3b 0a 20 20 20 20 7a  rLine = 4;.    z
cc00: 45 72 72 20 3d 20 22 50 61 73 73 77 6f 72 64 20  Err = "Password 
cc10: 6d 75 73 74 20 62 65 20 61 74 20 6c 65 61 73 74  must be at least
cc20: 20 36 20 63 68 61 72 61 63 74 65 72 73 20 6c 6f   6 characters lo
cc30: 6e 67 22 3b 0a 20 20 7d 65 6c 73 65 20 69 66 28  ng";.  }else if(
cc40: 20 66 6f 73 73 69 6c 5f 73 74 72 63 6d 70 28 7a   fossil_strcmp(z
cc50: 50 61 73 73 77 64 2c 7a 43 6f 6e 66 69 72 6d 29  Passwd,zConfirm)
cc60: 21 3d 30 20 29 7b 0a 20 20 20 20 69 45 72 72 4c  !=0 ){.    iErrL
cc70: 69 6e 65 20 3d 20 35 3b 0a 20 20 20 20 7a 45 72  ine = 5;.    zEr
cc80: 72 20 3d 20 22 50 61 73 73 77 6f 72 64 73 20 64  r = "Passwords d
cc90: 6f 20 6e 6f 74 20 6d 61 74 63 68 22 3b 0a 20 20  o not match";.  
cca0: 7d 65 6c 73 65 20 69 66 28 20 64 62 5f 65 78 69  }else if( db_exi
ccb0: 73 74 73 28 22 53 45 4c 45 43 54 20 31 20 46 52  sts("SELECT 1 FR
ccc0: 4f 4d 20 75 73 65 72 20 57 48 45 52 45 20 6c 6f  OM user WHERE lo
ccd0: 67 69 6e 3d 25 51 22 2c 20 7a 55 73 65 72 49 44  gin=%Q", zUserID
cce0: 29 20 29 7b 0a 20 20 20 20 69 45 72 72 4c 69 6e  ) ){.    iErrLin
ccf0: 65 20 3d 20 31 3b 0a 20 20 20 20 7a 45 72 72 20  e = 1;.    zErr 
cd00: 3d 20 22 54 68 69 73 20 55 73 65 72 20 49 44 20  = "This User ID 
cd10: 69 73 20 61 6c 72 65 61 64 79 20 74 61 6b 65 6e  is already taken
cd20: 2e 20 43 68 6f 6f 73 65 20 73 6f 6d 65 74 68 69  . Choose somethi
cd30: 6e 67 20 64 69 66 66 65 72 65 6e 74 2e 22 3b 0a  ng different.";.
cd40: 20 20 7d 65 6c 73 65 20 69 66 28 20 64 62 5f 65    }else if( db_e
cd50: 78 69 73 74 73 28 22 53 45 4c 45 43 54 20 31 20  xists("SELECT 1 
cd60: 46 52 4f 4d 20 75 73 65 72 20 57 48 45 52 45 20  FROM user WHERE 
cd70: 69 6e 66 6f 20 4c 49 4b 45 20 27 25 25 25 71 25  info LIKE '%%%q%
cd80: 25 27 22 2c 20 7a 45 41 64 64 72 29 20 29 7b 0a  %'", zEAddr) ){.
cd90: 20 20 20 20 69 45 72 72 4c 69 6e 65 20 3d 20 33      iErrLine = 3
cda0: 3b 0a 20 20 20 20 7a 45 72 72 20 3d 20 22 54 68  ;.    zErr = "Th
cdb0: 69 73 20 61 64 64 72 65 73 73 20 69 73 20 61 6c  is address is al
cdc0: 72 65 61 64 79 20 75 73 65 64 2e 22 3b 0a 20 20  ready used.";.  
cdd0: 7d 65 6c 73 65 7b 0a 20 20 20 20 42 6c 6f 62 20  }else{.    Blob 
cde0: 73 71 6c 3b 0a 20 20 20 20 69 6e 74 20 75 69 64  sql;.    int uid
cdf0: 3b 0a 20 20 20 20 63 68 61 72 20 2a 7a 50 61 73  ;.    char *zPas
ce00: 73 20 3d 20 73 68 61 31 5f 73 68 61 72 65 64 5f  s = sha1_shared_
ce10: 73 65 63 72 65 74 28 7a 50 61 73 73 77 64 2c 20  secret(zPasswd, 
ce20: 7a 55 73 65 72 49 44 2c 20 30 29 3b 0a 20 20 20  zUserID, 0);.   
ce30: 20 62 6c 6f 62 5f 69 6e 69 74 28 26 73 71 6c 2c   blob_init(&sql,
ce40: 20 30 2c 20 30 29 3b 0a 20 20 20 20 62 6c 6f 62   0, 0);.    blob
ce50: 5f 61 70 70 65 6e 64 5f 73 71 6c 28 26 73 71 6c  _append_sql(&sql
ce60: 2c 0a 20 20 20 20 20 20 20 22 49 4e 53 45 52 54  ,.       "INSERT
ce70: 20 49 4e 54 4f 20 75 73 65 72 28 6c 6f 67 69 6e   INTO user(login
ce80: 2c 70 77 2c 63 61 70 2c 69 6e 66 6f 2c 6d 74 69  ,pw,cap,info,mti
ce90: 6d 65 29 5c 6e 22 0a 20 20 20 20 20 20 20 22 56  me)\n".       "V
cea0: 41 4c 55 45 53 28 25 51 2c 25 51 2c 25 51 2c 22  ALUES(%Q,%Q,%Q,"
ceb0: 0a 20 20 20 20 20 20 20 22 27 25 71 20 3c 25 71  .       "'%q <%q
cec0: 3e 5c 6e 73 65 6c 66 2d 72 65 67 69 73 74 65 72  >\nself-register
ced0: 20 66 72 6f 6d 20 69 70 20 25 71 20 6f 6e 20 27   from ip %q on '
cee0: 7c 7c 64 61 74 65 74 69 6d 65 28 27 6e 6f 77 27  ||datetime('now'
cef0: 29 2c 6e 6f 77 28 29 29 22 2c 0a 20 20 20 20 20  ),now())",.     
cf00: 20 20 7a 55 73 65 72 49 44 2c 20 7a 50 61 73 73    zUserID, zPass
cf10: 2c 20 7a 50 65 72 6d 73 2c 20 7a 44 4e 61 6d 65  , zPerms, zDName
cf20: 2c 20 7a 45 41 64 64 72 2c 20 67 2e 7a 49 70 41  , zEAddr, g.zIpA
cf30: 64 64 72 29 3b 0a 20 20 20 20 66 6f 73 73 69 6c  ddr);.    fossil
cf40: 5f 66 72 65 65 28 7a 50 61 73 73 29 3b 0a 20 20  _free(zPass);.  
cf50: 20 20 64 62 5f 6d 75 6c 74 69 5f 65 78 65 63 28    db_multi_exec(
cf60: 22 25 73 22 2c 20 62 6c 6f 62 5f 73 71 6c 5f 74  "%s", blob_sql_t
cf70: 65 78 74 28 26 73 71 6c 29 29 3b 0a 20 20 20 20  ext(&sql));.    
cf80: 75 69 64 20 3d 20 64 62 5f 69 6e 74 28 30 2c 20  uid = db_int(0, 
cf90: 22 53 45 4c 45 43 54 20 75 69 64 20 46 52 4f 4d  "SELECT uid FROM
cfa0: 20 75 73 65 72 20 57 48 45 52 45 20 6c 6f 67 69   user WHERE logi
cfb0: 6e 3d 25 51 22 2c 20 7a 55 73 65 72 49 44 29 3b  n=%Q", zUserID);
cfc0: 0a 20 20 20 20 6c 6f 67 69 6e 5f 73 65 74 5f 75  .    login_set_u
cfd0: 73 65 72 5f 63 6f 6f 6b 69 65 28 7a 55 73 65 72  ser_cookie(zUser
cfe0: 49 44 2c 20 75 69 64 2c 20 4e 55 4c 4c 29 3b 0a  ID, uid, NULL);.
cff0: 20 20 20 20 69 66 28 20 63 61 6e 44 6f 41 6c 65      if( canDoAle
d000: 72 74 73 20 26 26 20 61 74 6f 69 28 50 44 28 22  rts && atoi(PD("
d010: 61 6c 65 72 74 73 22 2c 22 31 22 29 29 21 3d 30  alerts","1"))!=0
d020: 20 29 7b 0a 20 20 20 20 20 20 2f 2a 20 41 6c 73   ){.      /* Als
d030: 6f 20 6d 61 6b 65 20 74 68 65 20 6e 65 77 20 75  o make the new u
d040: 73 65 72 20 61 20 73 75 62 73 63 72 69 62 65 72  ser a subscriber
d050: 2e 20 2a 2f 0a 20 20 20 20 20 20 42 6c 6f 62 20  . */.      Blob 
d060: 68 64 72 2c 20 62 6f 64 79 3b 0a 20 20 20 20 20  hdr, body;.     
d070: 20 45 6d 61 69 6c 53 65 6e 64 65 72 20 2a 70 53   EmailSender *pS
d080: 65 6e 64 65 72 3b 0a 20 20 20 20 20 20 73 71 6c  ender;.      sql
d090: 69 74 65 33 5f 69 6e 74 36 34 20 69 64 3b 20 20  ite3_int64 id;  
d0a0: 20 2f 2a 20 4e 65 77 20 73 75 62 73 63 72 69 62   /* New subscrib
d0b0: 65 72 20 49 64 20 2a 2f 0a 20 20 20 20 20 20 63  er Id */.      c
d0c0: 6f 6e 73 74 20 63 68 61 72 20 2a 7a 43 6f 64 65  onst char *zCode
d0d0: 3b 20 20 2f 2a 20 4e 65 77 20 73 75 62 73 63 72  ;  /* New subscr
d0e0: 69 62 65 72 20 63 6f 64 65 20 28 69 6e 20 68 65  iber code (in he
d0f0: 78 29 20 2a 2f 0a 20 20 20 20 20 20 63 6f 6e 73  x) */.      cons
d100: 74 20 63 68 61 72 20 2a 7a 47 6f 74 6f 20 3d 20  t char *zGoto = 
d110: 50 28 22 67 22 29 3b 0a 20 20 20 20 20 20 69 6e  P("g");.      in
d120: 74 20 6e 73 75 62 20 3d 20 30 3b 0a 20 20 20 20  t nsub = 0;.    
d130: 20 20 63 68 61 72 20 73 73 75 62 5b 32 30 5d 3b    char ssub[20];
d140: 0a 20 20 20 20 20 20 73 73 75 62 5b 6e 73 75 62  .      ssub[nsub
d150: 2b 2b 5d 20 3d 20 27 61 27 3b 0a 20 20 20 20 20  ++] = 'a';.     
d160: 20 69 66 28 20 67 2e 70 65 72 6d 2e 52 65 61 64   if( g.perm.Read
d170: 20 29 20 20 20 20 73 73 75 62 5b 6e 73 75 62 2b   )    ssub[nsub+
d180: 2b 5d 20 3d 20 27 63 27 3b 0a 20 20 20 20 20 20  +] = 'c';.      
d190: 69 66 28 20 67 2e 70 65 72 6d 2e 52 64 46 6f 72  if( g.perm.RdFor
d1a0: 75 6d 20 29 20 73 73 75 62 5b 6e 73 75 62 2b 2b  um ) ssub[nsub++
d1b0: 5d 20 3d 20 27 66 27 3b 0a 20 20 20 20 20 20 69  ] = 'f';.      i
d1c0: 66 28 20 67 2e 70 65 72 6d 2e 52 64 54 6b 74 20  f( g.perm.RdTkt 
d1d0: 29 20 20 20 73 73 75 62 5b 6e 73 75 62 2b 2b 5d  )   ssub[nsub++]
d1e0: 20 3d 20 27 74 27 3b 0a 20 20 20 20 20 20 69 66   = 't';.      if
d1f0: 28 20 67 2e 70 65 72 6d 2e 52 64 57 69 6b 69 20  ( g.perm.RdWiki 
d200: 29 20 20 73 73 75 62 5b 6e 73 75 62 2b 2b 5d 20  )  ssub[nsub++] 
d210: 3d 20 27 77 27 3b 0a 20 20 20 20 20 20 73 73 75  = 'w';.      ssu
d220: 62 5b 6e 73 75 62 5d 20 3d 20 30 3b 0a 20 20 20  b[nsub] = 0;.   
d230: 20 20 20 64 62 5f 6d 75 6c 74 69 5f 65 78 65 63     db_multi_exec
d240: 28 0a 20 20 20 20 20 20 20 20 22 49 4e 53 45 52  (.        "INSER
d250: 54 20 49 4e 54 4f 20 73 75 62 73 63 72 69 62 65  T INTO subscribe
d260: 72 28 73 65 6d 61 69 6c 2c 73 75 6e 61 6d 65 2c  r(semail,suname,
d270: 22 0a 20 20 20 20 20 20 20 20 22 20 20 73 76 65  ".        "  sve
d280: 72 69 66 69 65 64 2c 73 64 6f 6e 6f 74 63 61 6c  rified,sdonotcal
d290: 6c 2c 73 64 69 67 65 73 74 2c 73 73 75 62 2c 73  l,sdigest,ssub,s
d2a0: 63 74 69 6d 65 2c 6d 74 69 6d 65 2c 73 6d 69 70  ctime,mtime,smip
d2b0: 29 22 0a 20 20 20 20 20 20 20 20 22 56 41 4c 55  )".        "VALU
d2c0: 45 53 28 25 51 2c 25 51 2c 25 64 2c 30 2c 25 64  ES(%Q,%Q,%d,0,%d
d2d0: 2c 25 51 2c 6e 6f 77 28 29 2c 6e 6f 77 28 29 2c  ,%Q,now(),now(),
d2e0: 25 51 29 22 2c 0a 20 20 20 20 20 20 20 20 2f 2a  %Q)",.        /*
d2f0: 20 73 65 6d 61 69 6c 20 2a 2f 20 20 20 20 7a 45   semail */    zE
d300: 41 64 64 72 2c 0a 20 20 20 20 20 20 20 20 2f 2a  Addr,.        /*
d310: 20 73 75 6e 61 6d 65 20 2a 2f 20 20 20 20 7a 55   suname */    zU
d320: 73 65 72 49 44 2c 0a 20 20 20 20 20 20 20 20 2f  serID,.        /
d330: 2a 20 73 76 65 72 69 66 69 65 64 20 2a 2f 20 30  * sverified */ 0
d340: 2c 0a 20 20 20 20 20 20 20 20 2f 2a 20 73 64 69  ,.        /* sdi
d350: 67 65 73 74 20 2a 2f 20 20 20 30 2c 0a 20 20 20  gest */   0,.   
d360: 20 20 20 20 20 2f 2a 20 73 73 75 62 20 2a 2f 20       /* ssub */ 
d370: 20 20 20 20 20 73 73 75 62 2c 0a 20 20 20 20 20       ssub,.     
d380: 20 20 20 2f 2a 20 73 6d 69 70 20 2a 2f 20 20 20     /* smip */   
d390: 20 20 20 67 2e 7a 49 70 41 64 64 72 0a 20 20 20     g.zIpAddr.   
d3a0: 20 20 20 29 3b 0a 20 20 20 20 20 20 69 64 20 3d     );.      id =
d3b0: 20 64 62 5f 6c 61 73 74 5f 69 6e 73 65 72 74 5f   db_last_insert_
d3c0: 72 6f 77 69 64 28 29 3b 0a 20 20 20 20 20 20 7a  rowid();.      z
d3d0: 43 6f 64 65 20 3d 20 64 62 5f 74 65 78 74 28 30  Code = db_text(0
d3e0: 2c 0a 20 20 20 20 20 20 20 20 20 20 20 22 53 45  ,.           "SE
d3f0: 4c 45 43 54 20 68 65 78 28 73 75 62 73 63 72 69  LECT hex(subscri
d400: 62 65 72 43 6f 64 65 29 20 46 52 4f 4d 20 73 75  berCode) FROM su
d410: 62 73 63 72 69 62 65 72 20 57 48 45 52 45 20 73  bscriber WHERE s
d420: 75 62 73 63 72 69 62 65 72 49 64 3d 25 6c 6c 64  ubscriberId=%lld
d430: 22 2c 0a 20 20 20 20 20 20 20 20 20 20 20 69 64  ",.           id
d440: 29 3b 0a 20 20 20 20 20 20 2f 2a 20 41 20 76 65  );.      /* A ve
d450: 72 69 66 69 63 61 74 69 6f 6e 20 65 6d 61 69 6c  rification email
d460: 20 2a 2f 0a 20 20 20 20 20 20 70 53 65 6e 64 65   */.      pSende
d470: 72 20 3d 20 65 6d 61 69 6c 5f 73 65 6e 64 65 72  r = email_sender
d480: 5f 6e 65 77 28 30 2c 30 29 3b 0a 20 20 20 20 20  _new(0,0);.     
d490: 20 62 6c 6f 62 5f 69 6e 69 74 28 26 68 64 72 2c   blob_init(&hdr,
d4a0: 30 2c 30 29 3b 0a 20 20 20 20 20 20 62 6c 6f 62  0,0);.      blob
d4b0: 5f 69 6e 69 74 28 26 62 6f 64 79 2c 30 2c 30 29  _init(&body,0,0)
d4c0: 3b 0a 20 20 20 20 20 20 62 6c 6f 62 5f 61 70 70  ;.      blob_app
d4d0: 65 6e 64 66 28 26 68 64 72 2c 20 22 54 6f 3a 20  endf(&hdr, "To: 
d4e0: 3c 25 73 3e 5c 6e 22 2c 20 7a 45 41 64 64 72 29  <%s>\n", zEAddr)
d4f0: 3b 0a 20 20 20 20 20 20 62 6c 6f 62 5f 61 70 70  ;.      blob_app
d500: 65 6e 64 66 28 26 68 64 72 2c 20 22 53 75 62 6a  endf(&hdr, "Subj
d510: 65 63 74 3a 20 53 75 62 73 63 72 69 70 74 69 6f  ect: Subscriptio
d520: 6e 20 76 65 72 69 66 69 63 61 74 69 6f 6e 5c 6e  n verification\n
d530: 22 29 3b 0a 20 20 20 20 20 20 65 6d 61 69 6c 5f  ");.      email_
d540: 61 70 70 65 6e 64 5f 63 6f 6e 66 69 72 6d 61 74  append_confirmat
d550: 69 6f 6e 5f 6d 65 73 73 61 67 65 28 26 62 6f 64  ion_message(&bod
d560: 79 2c 20 7a 43 6f 64 65 29 3b 0a 20 20 20 20 20  y, zCode);.     
d570: 20 65 6d 61 69 6c 5f 73 65 6e 64 28 70 53 65 6e   email_send(pSen
d580: 64 65 72 2c 20 26 68 64 72 2c 20 26 62 6f 64 79  der, &hdr, &body
d590: 2c 20 30 29 3b 0a 20 20 20 20 20 20 73 74 79 6c  , 0);.      styl
d5a0: 65 5f 68 65 61 64 65 72 28 22 45 6d 61 69 6c 20  e_header("Email 
d5b0: 56 65 72 69 66 69 63 61 74 69 6f 6e 22 29 3b 0a  Verification");.
d5c0: 20 20 20 20 20 20 69 66 28 20 70 53 65 6e 64 65        if( pSende
d5d0: 72 2d 3e 7a 45 72 72 20 29 7b 0a 20 20 20 20 20  r->zErr ){.     
d5e0: 20 20 20 40 20 3c 68 31 3e 49 6e 74 65 72 6e 61     @ <h1>Interna
d5f0: 6c 20 45 72 72 6f 72 3c 2f 68 31 3e 0a 20 20 20  l Error</h1>.   
d600: 20 20 20 20 20 40 20 3c 70 3e 54 68 65 20 66 6f       @ <p>The fo
d610: 6c 6c 6f 77 69 6e 67 20 69 6e 74 65 72 6e 61 6c  llowing internal
d620: 20 65 72 72 6f 72 20 77 61 73 20 65 6e 63 6f 75   error was encou
d630: 6e 74 65 72 65 64 20 77 68 69 6c 65 20 74 72 79  ntered while try
d640: 69 6e 67 0a 20 20 20 20 20 20 20 20 40 20 74 6f  ing.        @ to
d650: 20 73 65 6e 64 20 74 68 65 20 63 6f 6e 66 69 72   send the confir
d660: 6d 61 74 69 6f 6e 20 65 6d 61 69 6c 3a 0a 20 20  mation email:.  
d670: 20 20 20 20 20 20 40 20 3c 62 6c 6f 63 6b 71 75        @ <blockqu
d680: 6f 74 65 3e 3c 70 72 65 3e 0a 20 20 20 20 20 20  ote><pre>.      
d690: 20 20 40 20 25 68 28 70 53 65 6e 64 65 72 2d 3e    @ %h(pSender->
d6a0: 7a 45 72 72 29 0a 20 20 20 20 20 20 20 20 40 20  zErr).        @ 
d6b0: 3c 2f 70 72 65 3e 3c 2f 62 6c 6f 63 6b 71 75 6f  </pre></blockquo
d6c0: 74 65 3e 0a 20 20 20 20 20 20 7d 65 6c 73 65 7b  te>.      }else{
d6d0: 0a 20 20 20 20 20 20 20 20 40 20 3c 70 3e 41 6e  .        @ <p>An
d6e0: 20 65 6d 61 69 6c 20 68 61 73 20 62 65 65 6e 20   email has been 
d6f0: 73 65 6e 74 20 74 6f 20 22 25 68 28 7a 45 41 64  sent to "%h(zEAd
d700: 64 72 29 22 2e 20 54 68 61 74 20 65 6d 61 69 6c  dr)". That email
d710: 20 63 6f 6e 74 61 69 6e 73 20 61 0a 20 20 20 20   contains a.    
d720: 20 20 20 20 40 20 68 79 70 65 72 6c 69 6e 6b 20      @ hyperlink 
d730: 74 68 61 74 20 79 6f 75 20 6d 75 73 74 20 63 6c  that you must cl
d740: 69 63 6b 20 6f 6e 20 69 6e 20 6f 72 64 65 72 20  ick on in order 
d750: 74 6f 20 61 63 74 69 76 61 74 65 20 79 6f 75 72  to activate your
d760: 0a 20 20 20 20 20 20 20 20 40 20 73 75 62 73 63  .        @ subsc
d770: 72 69 70 74 69 6f 6e 2e 3c 2f 70 3e 0a 20 20 20  ription.</p>.   
d780: 20 20 20 7d 0a 20 20 20 20 20 20 65 6d 61 69 6c     }.      email
d790: 5f 73 65 6e 64 65 72 5f 66 72 65 65 28 70 53 65  _sender_free(pSe
d7a0: 6e 64 65 72 29 3b 0a 20 20 20 20 20 20 69 66 28  nder);.      if(
d7b0: 20 7a 47 6f 74 6f 20 29 7b 0a 20 20 20 20 20 20   zGoto ){.      
d7c0: 20 20 40 20 3c 70 3e 3c 61 20 68 72 65 66 3d 27    @ <p><a href='
d7d0: 25 68 28 7a 47 6f 74 6f 29 27 3e 43 6f 6e 74 69  %h(zGoto)'>Conti
d7e0: 6e 75 65 3c 2f 61 3e 0a 20 20 20 20 20 20 7d 0a  nue</a>.      }.
d7f0: 20 20 20 20 20 20 73 74 79 6c 65 5f 66 6f 6f 74        style_foot
d800: 65 72 28 29 3b 0a 20 20 20 20 20 20 72 65 74 75  er();.      retu
d810: 72 6e 3b 0a 20 20 20 20 7d 0a 20 20 20 20 72 65  rn;.    }.    re
d820: 64 69 72 65 63 74 5f 74 6f 5f 67 28 29 3b 0a 20  direct_to_g();. 
d830: 20 7d 0a 0a 20 20 2f 2a 20 50 72 65 70 61 72 65   }..  /* Prepare
d840: 20 74 68 65 20 63 61 70 74 63 68 61 2e 20 2a 2f   the captcha. */
d850: 0a 20 20 75 53 65 65 64 20 3d 20 63 61 70 74 63  .  uSeed = captc
d860: 68 61 5f 73 65 65 64 28 29 3b 0a 20 20 7a 44 65  ha_seed();.  zDe
d870: 63 6f 64 65 64 20 3d 20 63 61 70 74 63 68 61 5f  coded = captcha_
d880: 64 65 63 6f 64 65 28 75 53 65 65 64 29 3b 0a 20  decode(uSeed);. 
d890: 20 7a 43 61 70 74 63 68 61 20 3d 20 63 61 70 74   zCaptcha = capt
d8a0: 63 68 61 5f 72 65 6e 64 65 72 28 7a 44 65 63 6f  cha_render(zDeco
d8b0: 64 65 64 29 3b 0a 0a 20 20 73 74 79 6c 65 5f 68  ded);..  style_h
d8c0: 65 61 64 65 72 28 22 52 65 67 69 73 74 65 72 22  eader("Register"
d8d0: 29 3b 0a 20 20 2f 2a 20 50 72 69 6e 74 20 6f 75  );.  /* Print ou
d8e0: 74 20 74 68 65 20 72 65 67 69 73 74 72 61 74 69  t the registrati
d8f0: 6f 6e 20 66 6f 72 6d 2e 20 2a 2f 0a 20 20 66 6f  on form. */.  fo
d900: 72 6d 5f 62 65 67 69 6e 28 30 2c 20 22 25 52 2f  rm_begin(0, "%R/
d910: 72 65 67 69 73 74 65 72 22 29 3b 0a 20 20 69 66  register");.  if
d920: 28 20 50 28 22 67 22 29 20 29 7b 0a 20 20 20 20  ( P("g") ){.    
d930: 40 20 3c 69 6e 70 75 74 20 74 79 70 65 3d 22 68  @ <input type="h
d940: 69 64 64 65 6e 22 20 6e 61 6d 65 3d 22 67 22 20  idden" name="g" 
d950: 76 61 6c 75 65 3d 22 25 68 28 50 28 22 67 22 29  value="%h(P("g")
d960: 29 22 20 2f 3e 0a 20 20 7d 0a 20 20 40 20 3c 70  )" />.  }.  @ <p
d970: 3e 3c 69 6e 70 75 74 20 74 79 70 65 3d 22 68 69  ><input type="hi
d980: 64 64 65 6e 22 20 6e 61 6d 65 3d 22 63 61 70 74  dden" name="capt
d990: 63 68 61 73 65 65 64 22 20 76 61 6c 75 65 3d 22  chaseed" value="
d9a0: 25 75 28 75 53 65 65 64 29 22 20 2f 3e 0a 20 20  %u(uSeed)" />.  
d9b0: 40 20 3c 74 61 62 6c 65 20 63 6c 61 73 73 3d 22  @ <table class="
d9c0: 6c 6f 67 69 6e 5f 6f 75 74 22 3e 0a 20 20 40 20  login_out">.  @ 
d9d0: 3c 74 72 3e 0a 20 20 40 20 20 20 3c 74 64 20 63  <tr>.  @   <td c
d9e0: 6c 61 73 73 3d 22 66 6f 72 6d 5f 6c 61 62 65 6c  lass="form_label
d9f0: 22 20 61 6c 69 67 6e 3d 22 72 69 67 68 74 22 3e  " align="right">
da00: 55 73 65 72 20 49 44 3a 3c 2f 74 64 3e 0a 20 20  User ID:</td>.  
da10: 40 20 20 20 3c 74 64 3e 3c 69 6e 70 75 74 20 74  @   <td><input t
da20: 79 70 65 3d 22 74 65 78 74 22 20 6e 61 6d 65 3d  ype="text" name=
da30: 22 75 22 20 76 61 6c 75 65 3d 22 25 68 28 7a 55  "u" value="%h(zU
da40: 73 65 72 49 44 29 22 20 73 69 7a 65 3d 22 33 30  serID)" size="30
da50: 22 3e 3c 2f 74 64 3e 0a 20 20 69 66 28 20 69 45  "></td>.  if( iE
da60: 72 72 4c 69 6e 65 3d 3d 31 20 29 7b 0a 20 20 20  rrLine==1 ){.   
da70: 20 40 20 20 20 3c 74 64 3e 3c 73 70 61 6e 20 63   @   <td><span c
da80: 6c 61 73 73 3d 27 6c 6f 67 69 6e 45 72 72 6f 72  lass='loginError
da90: 27 3e 26 6c 61 72 72 3b 20 25 68 28 7a 45 72 72  '>&larr; %h(zErr
daa0: 29 3c 2f 73 70 61 6e 3e 3c 2f 74 64 3e 0a 20 20  )</span></td>.  
dab0: 7d 0a 20 20 40 20 3c 2f 74 72 3e 0a 20 20 40 20  }.  @ </tr>.  @ 
dac0: 3c 74 72 3e 0a 20 20 40 20 20 20 3c 74 64 20 63  <tr>.  @   <td c
dad0: 6c 61 73 73 3d 22 66 6f 72 6d 5f 6c 61 62 65 6c  lass="form_label
dae0: 22 20 61 6c 69 67 6e 3d 22 72 69 67 68 74 22 3e  " align="right">
daf0: 44 69 73 70 6c 61 79 20 4e 61 6d 65 3a 3c 2f 74  Display Name:</t
db00: 64 3e 0a 20 20 40 20 20 20 3c 74 64 3e 3c 69 6e  d>.  @   <td><in
db10: 70 75 74 20 74 79 70 65 3d 22 74 65 78 74 22 20  put type="text" 
db20: 6e 61 6d 65 3d 22 64 6e 22 20 76 61 6c 75 65 3d  name="dn" value=
db30: 22 25 68 28 7a 44 4e 61 6d 65 29 22 20 73 69 7a  "%h(zDName)" siz
db40: 65 3d 22 33 30 22 3e 3c 2f 74 64 3e 0a 20 20 69  e="30"></td>.  i
db50: 66 28 20 69 45 72 72 4c 69 6e 65 3d 3d 32 20 29  f( iErrLine==2 )
db60: 7b 0a 20 20 20 20 40 20 20 20 3c 74 64 3e 3c 73  {.    @   <td><s
db70: 70 61 6e 20 63 6c 61 73 73 3d 27 6c 6f 67 69 6e  pan class='login
db80: 45 72 72 6f 72 27 3e 26 6c 61 72 72 3b 20 25 68  Error'>&larr; %h
db90: 28 7a 45 72 72 29 3c 2f 73 70 61 6e 3e 3c 2f 74  (zErr)</span></t
dba0: 64 3e 0a 20 20 7d 0a 20 20 40 20 3c 2f 74 72 3e  d>.  }.  @ </tr>
dbb0: 0a 20 20 40 20 3c 74 72 3e 0a 20 20 40 20 20 20  .  @ <tr>.  @   
dbc0: 3c 74 64 20 63 6c 61 73 73 3d 22 66 6f 72 6d 5f  <td class="form_
dbd0: 6c 61 62 65 6c 22 20 61 6c 69 67 6e 3d 22 72 69  label" align="ri
dbe0: 67 68 74 22 3e 45 6d 61 69 6c 20 41 64 64 72 65  ght">Email Addre
dbf0: 73 73 3a 3c 2f 74 64 3e 0a 20 20 40 20 20 20 3c  ss:</td>.  @   <
dc00: 74 64 3e 3c 69 6e 70 75 74 20 74 79 70 65 3d 22  td><input type="
dc10: 74 65 78 74 22 20 6e 61 6d 65 3d 22 65 61 22 20  text" name="ea" 
dc20: 76 61 6c 75 65 3d 22 25 68 28 7a 45 41 64 64 72  value="%h(zEAddr
dc30: 29 22 20 73 69 7a 65 3d 22 33 30 22 3e 3c 2f 74  )" size="30"></t
dc40: 64 3e 0a 20 20 69 66 28 20 69 45 72 72 4c 69 6e  d>.  if( iErrLin
dc50: 65 3d 3d 33 20 29 7b 0a 20 20 20 20 40 20 20 20  e==3 ){.    @   
dc60: 3c 74 64 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d  <td><span class=
dc70: 27 6c 6f 67 69 6e 45 72 72 6f 72 27 3e 26 6c 61  'loginError'>&la
dc80: 72 72 3b 20 25 68 28 7a 45 72 72 29 3c 2f 73 70  rr; %h(zErr)</sp
dc90: 61 6e 3e 3c 2f 74 64 3e 0a 20 20 7d 0a 20 20 40  an></td>.  }.  @
dca0: 20 3c 2f 74 72 3e 0a 20 20 69 66 28 20 63 61 6e   </tr>.  if( can
dcb0: 44 6f 41 6c 65 72 74 73 20 29 7b 0a 20 20 20 20  DoAlerts ){.    
dcc0: 69 6e 74 20 61 20 3d 20 61 74 6f 69 28 50 44 28  int a = atoi(PD(
dcd0: 22 61 6c 65 72 74 73 22 2c 22 31 22 29 29 3b 0a  "alerts","1"));.
dce0: 20 20 20 20 40 20 3c 74 72 3e 0a 20 20 20 20 40      @ <tr>.    @
dcf0: 20 20 20 3c 74 64 20 63 6c 61 73 73 3d 22 66 6f     <td class="fo
dd00: 72 6d 5f 6c 61 62 65 6c 22 20 61 6c 69 67 6e 3d  rm_label" align=
dd10: 22 72 69 67 68 74 22 3e 52 65 63 65 69 76 65 20  "right">Receive 
dd20: 45 6d 61 69 6c 20 41 6c 65 72 74 73 3f 3c 2f 74  Email Alerts?</t
dd30: 64 3e 0a 20 20 20 20 40 20 20 20 3c 74 64 3e 3c  d>.    @   <td><
dd40: 73 65 6c 65 63 74 20 73 69 7a 65 3d 27 31 27 20  select size='1' 
dd50: 6e 61 6d 65 3d 27 61 6c 65 72 74 73 27 3e 0a 20  name='alerts'>. 
dd60: 20 20 20 40 20 20 20 20 20 20 20 3c 6f 70 74 69     @       <opti
dd70: 6f 6e 20 76 61 6c 75 65 3d 22 31 22 20 25 73 28  on value="1" %s(
dd80: 61 3f 22 73 65 6c 65 63 74 65 64 22 3a 22 22 29  a?"selected":"")
dd90: 3e 59 65 73 3c 2f 6f 70 74 69 6f 6e 3e 0a 20 20  >Yes</option>.  
dda0: 20 20 40 20 20 20 20 20 20 20 3c 6f 70 74 69 6f    @       <optio
ddb0: 6e 20 76 61 6c 75 65 3d 22 30 22 20 25 73 28 21  n value="0" %s(!
ddc0: 61 3f 22 73 65 6c 65 63 74 65 64 22 3a 22 22 29  a?"selected":"")
ddd0: 3e 4e 6f 3c 2f 6f 70 74 69 6f 6e 3e 0a 20 20 20  >No</option>.   
dde0: 20 40 20 20 20 3c 2f 73 65 6c 65 63 74 3e 3c 2f   @   </select></
ddf0: 74 64 3e 3c 2f 74 72 3e 0a 20 20 7d 0a 20 20 40  td></tr>.  }.  @
de00: 20 3c 74 72 3e 0a 20 20 40 20 20 20 3c 74 64 20   <tr>.  @   <td 
de10: 63 6c 61 73 73 3d 22 66 6f 72 6d 5f 6c 61 62 65  class="form_labe
de20: 6c 22 20 61 6c 69 67 6e 3d 22 72 69 67 68 74 22  l" align="right"
de30: 3e 50 61 73 73 77 6f 72 64 3a 3c 2f 74 64 3e 0a  >Password:</td>.
de40: 20 20 40 20 20 20 3c 74 64 3e 3c 69 6e 70 75 74    @   <td><input
de50: 20 74 79 70 65 3d 22 70 61 73 73 77 6f 72 64 22   type="password"
de60: 20 6e 61 6d 65 3d 22 70 22 20 76 61 6c 75 65 3d   name="p" value=
de70: 22 25 68 28 7a 50 61 73 73 77 64 29 22 20 73 69  "%h(zPasswd)" si
de80: 7a 65 3d 22 33 30 22 3e 3c 2f 74 64 3e 0a 20 20  ze="30"></td>.  
de90: 69 66 28 20 69 45 72 72 4c 69 6e 65 3d 3d 34 20  if( iErrLine==4 
dea0: 29 7b 0a 20 20 20 20 40 20 20 20 3c 74 64 3e 3c  ){.    @   <td><
deb0: 73 70 61 6e 20 63 6c 61 73 73 3d 27 6c 6f 67 69  span class='logi
dec0: 6e 45 72 72 6f 72 27 3e 26 6c 61 72 72 3b 20 25  nError'>&larr; %
ded0: 68 28 7a 45 72 72 29 3c 2f 73 70 61 6e 3e 3c 2f  h(zErr)</span></
dee0: 74 64 3e 0a 20 20 7d 0a 20 20 40 20 3c 2f 74 72  td>.  }.  @ </tr
def0: 3e 0a 20 20 40 20 3c 74 72 3e 0a 20 20 40 20 20  >.  @ <tr>.  @  
df00: 20 3c 74 64 20 63 6c 61 73 73 3d 22 66 6f 72 6d   <td class="form
df10: 5f 6c 61 62 65 6c 22 20 61 6c 69 67 6e 3d 22 72  _label" align="r
df20: 69 67 68 74 22 3e 43 6f 6e 66 69 72 6d 20 70 61  ight">Confirm pa
df30: 73 73 77 6f 72 64 3a 3c 2f 74 64 3e 0a 20 20 40  ssword:</td>.  @
df40: 20 20 20 3c 74 64 3e 3c 69 6e 70 75 74 20 74 79     <td><input ty
df50: 70 65 3d 22 70 61 73 73 77 6f 72 64 22 20 6e 61  pe="password" na
df60: 6d 65 3d 22 63 70 22 20 76 61 6c 75 65 3d 22 25  me="cp" value="%
df70: 68 28 7a 43 6f 6e 66 69 72 6d 29 22 20 73 69 7a  h(zConfirm)" siz
df80: 65 3d 22 33 30 22 3e 3c 2f 74 64 3e 0a 20 20 69  e="30"></td>.  i
df90: 66 28 20 69 45 72 72 4c 69 6e 65 3d 3d 35 20 29  f( iErrLine==5 )
dfa0: 7b 0a 20 20 20 20 40 20 20 20 3c 74 64 3e 3c 73  {.    @   <td><s
dfb0: 70 61 6e 20 63 6c 61 73 73 3d 27 6c 6f 67 69 6e  pan class='login
dfc0: 45 72 72 6f 72 27 3e 26 6c 61 72 72 3b 20 25 68  Error'>&larr; %h
dfd0: 28 7a 45 72 72 29 3c 2f 73 70 61 6e 3e 3c 2f 74  (zErr)</span></t
dfe0: 64 3e 0a 20 20 7d 0a 20 20 40 20 3c 2f 74 72 3e  d>.  }.  @ </tr>
dff0: 0a 20 20 40 20 3c 74 72 3e 0a 20 20 40 20 20 20  .  @ <tr>.  @   
e000: 3c 74 64 20 63 6c 61 73 73 3d 22 66 6f 72 6d 5f  <td class="form_
e010: 6c 61 62 65 6c 22 20 61 6c 69 67 6e 3d 22 72 69  label" align="ri
e020: 67 68 74 22 3e 43 61 70 74 63 68 61 20 74 65 78  ght">Captcha tex
e030: 74 20 28 62 65 6c 6f 77 29 3a 3c 2f 74 64 3e 0a  t (below):</td>.
e040: 20 20 40 20 20 20 3c 74 64 3e 3c 69 6e 70 75 74    @   <td><input
e050: 20 74 79 70 65 3d 22 74 65 78 74 22 20 6e 61 6d   type="text" nam
e060: 65 3d 22 63 61 70 74 63 68 61 22 20 76 61 6c 75  e="captcha" valu
e070: 65 3d 22 22 20 73 69 7a 65 3d 22 33 30 22 3e 3c  e="" size="30"><
e080: 2f 74 64 3e 0a 20 20 69 66 28 20 69 45 72 72 4c  /td>.  if( iErrL
e090: 69 6e 65 3d 3d 36 20 29 7b 0a 20 20 20 20 40 20  ine==6 ){.    @ 
e0a0: 20 20 3c 74 64 3e 3c 73 70 61 6e 20 63 6c 61 73    <td><span clas
e0b0: 73 3d 27 6c 6f 67 69 6e 45 72 72 6f 72 27 3e 26  s='loginError'>&
e0c0: 6c 61 72 72 3b 20 25 68 28 7a 45 72 72 29 3c 2f  larr; %h(zErr)</
e0d0: 73 70 61 6e 3e 3c 2f 74 64 3e 0a 20 20 7d 0a 20  span></td>.  }. 
e0e0: 20 40 20 3c 2f 74 72 3e 0a 20 20 40 20 3c 74 72   @ </tr>.  @ <tr
e0f0: 3e 3c 74 64 3e 3c 2f 74 64 3e 0a 20 20 40 20 3c  ><td></td>.  @ <
e100: 74 64 3e 3c 69 6e 70 75 74 20 74 79 70 65 3d 22  td><input type="
e110: 73 75 62 6d 69 74 22 20 6e 61 6d 65 3d 22 6e 65  submit" name="ne
e120: 77 22 20 76 61 6c 75 65 3d 22 52 65 67 69 73 74  w" value="Regist
e130: 65 72 22 20 2f 3e 3c 2f 74 64 3e 3c 2f 74 72 3e  er" /></td></tr>
e140: 0a 20 20 40 20 3c 2f 74 61 62 6c 65 3e 0a 20 20  .  @ </table>.  
e150: 40 20 3c 64 69 76 20 63 6c 61 73 73 3d 22 63 61  @ <div class="ca
e160: 70 74 63 68 61 22 3e 3c 74 61 62 6c 65 20 63 6c  ptcha"><table cl
e170: 61 73 73 3d 22 63 61 70 74 63 68 61 22 3e 3c 74  ass="captcha"><t
e180: 72 3e 3c 74 64 3e 3c 70 72 65 3e 0a 20 20 40 20  r><td><pre>.  @ 
e190: 25 68 28 7a 43 61 70 74 63 68 61 29 0a 20 20 40  %h(zCaptcha).  @
e1a0: 20 3c 2f 70 72 65 3e 3c 2f 74 64 3e 3c 2f 74 72   </pre></td></tr
e1b0: 3e 3c 2f 74 61 62 6c 65 3e 3c 2f 64 69 76 3e 0a  ></table></div>.
e1c0: 20 20 40 20 3c 2f 66 6f 72 6d 3e 0a 20 20 73 74    @ </form>.  st
e1d0: 79 6c 65 5f 66 6f 6f 74 65 72 28 29 3b 0a 0a 20  yle_footer();.. 
e1e0: 20 66 72 65 65 28 7a 43 61 70 74 63 68 61 29 3b   free(zCaptcha);
e1f0: 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 52 75 6e 20 53 51  .}../*.** Run SQ
e200: 4c 20 6f 6e 20 74 68 65 20 72 65 70 6f 73 69 74  L on the reposit
e210: 6f 72 79 20 64 61 74 61 62 61 73 65 20 66 6f 72  ory database for
e220: 20 65 76 65 72 79 20 72 65 70 6f 73 69 74 6f 72   every repositor
e230: 79 20 69 6e 20 6f 75 72 0a 2a 2a 20 6c 6f 67 69  y in our.** logi
e240: 6e 20 67 72 6f 75 70 2e 20 20 54 68 65 20 53 51  n group.  The SQ
e250: 4c 20 69 73 20 72 75 6e 20 69 6e 20 61 20 73 65  L is run in a se
e260: 70 61 72 61 74 65 20 64 61 74 61 62 61 73 65 20  parate database 
e270: 63 6f 6e 6e 65 63 74 69 6f 6e 2e 0a 2a 2a 0a 2a  connection..**.*
e280: 2a 20 41 6e 79 20 6d 65 6d 62 65 72 73 20 6f 66  * Any members of
e290: 20 74 68 65 20 6c 6f 67 69 6e 20 67 72 6f 75 70   the login group
e2a0: 20 77 68 6f 73 65 20 72 65 70 6f 73 69 74 6f 72   whose repositor
e2b0: 79 20 64 61 74 61 62 61 73 65 20 66 69 6c 65 0a  y database file.
e2c0: 2a 2a 20 63 61 6e 6e 6f 74 20 62 65 20 66 6f 75  ** cannot be fou
e2d0: 6e 64 20 69 73 20 73 69 6c 65 6e 74 6c 79 20 72  nd is silently r
e2e0: 65 6d 6f 76 65 64 20 66 72 6f 6d 20 74 68 65 20  emoved from the 
e2f0: 67 72 6f 75 70 2e 0a 2a 2a 0a 2a 2a 20 45 72 72  group..**.** Err
e300: 6f 72 20 6d 65 73 73 61 67 65 73 20 61 63 63 75  or messages accu
e310: 6d 75 6c 61 74 65 20 61 6e 64 20 61 72 65 20 72  mulate and are r
e320: 65 74 75 72 6e 65 64 20 69 6e 20 2a 70 7a 45 72  eturned in *pzEr
e330: 72 6f 72 4d 73 67 2e 20 20 54 68 65 0a 2a 2a 20  rorMsg.  The.** 
e340: 6d 65 6d 6f 72 79 20 75 73 65 64 20 74 6f 20 68  memory used to h
e350: 6f 6c 64 20 74 68 65 73 65 20 6d 65 73 73 61 67  old these messag
e360: 65 73 20 73 68 6f 75 6c 64 20 62 65 20 66 72 65  es should be fre
e370: 65 64 20 75 73 69 6e 67 0a 2a 2a 20 66 6f 73 73  ed using.** foss
e380: 69 6c 5f 66 72 65 65 28 29 20 69 66 20 6f 6e 65  il_free() if one
e390: 20 64 65 73 69 72 65 64 20 74 6f 20 61 76 6f 69   desired to avoi
e3a0: 64 20 61 20 6d 65 6d 6f 72 79 20 6c 65 61 6b 2e  d a memory leak.
e3b0: 20 20 54 68 65 0a 2a 2a 20 7a 50 72 65 66 69 78    The.** zPrefix
e3c0: 20 61 6e 64 20 7a 53 75 66 66 69 78 20 73 74 72   and zSuffix str
e3d0: 69 6e 67 73 20 73 75 72 72 6f 75 6e 64 20 65 61  ings surround ea
e3e0: 63 68 20 65 72 72 6f 72 20 6d 65 73 73 61 67 65  ch error message
e3f0: 2e 0a 2a 2a 0a 2a 2a 20 52 65 74 75 72 6e 20 74  ..**.** Return t
e400: 68 65 20 6e 75 6d 62 65 72 20 6f 66 20 65 72 72  he number of err
e410: 6f 72 73 2e 0a 2a 2f 0a 69 6e 74 20 6c 6f 67 69  ors..*/.int logi
e420: 6e 5f 67 72 6f 75 70 5f 73 71 6c 28 0a 20 20 63  n_group_sql(.  c
e430: 6f 6e 73 74 20 63 68 61 72 20 2a 7a 53 71 6c 2c  onst char *zSql,
e440: 20 20 20 20 20 20 20 20 2f 2a 20 54 68 65 20 53          /* The S
e450: 51 4c 20 74 6f 20 72 75 6e 20 2a 2f 0a 20 20 63  QL to run */.  c
e460: 6f 6e 73 74 20 63 68 61 72 20 2a 7a 50 72 65 66  onst char *zPref
e470: 69 78 2c 20 20 20 20 20 2f 2a 20 50 72 65 66 69  ix,     /* Prefi
e480: 78 20 74 6f 20 65 61 63 68 20 65 72 72 6f 72 20  x to each error 
e490: 6d 65 73 73 61 67 65 20 2a 2f 0a 20 20 63 6f 6e  message */.  con
e4a0: 73 74 20 63 68 61 72 20 2a 7a 53 75 66 66 69 78  st char *zSuffix
e4b0: 2c 20 20 20 20 20 2f 2a 20 53 75 66 66 69 78 20  ,     /* Suffix 
e4c0: 74 6f 20 65 61 63 68 20 65 72 72 6f 72 20 6d 65  to each error me
e4d0: 73 73 61 67 65 20 2a 2f 0a 20 20 63 68 61 72 20  ssage */.  char 
e4e0: 2a 2a 70 7a 45 72 72 6f 72 4d 73 67 20 20 20 20  **pzErrorMsg    
e4f0: 20 20 20 20 2f 2a 20 57 72 69 74 65 20 65 72 72      /* Write err
e500: 6f 72 20 6d 65 73 73 61 67 65 20 68 65 72 65 2c  or message here,
e510: 20 69 66 20 6e 6f 74 20 4e 55 4c 4c 20 2a 2f 0a   if not NULL */.
e520: 29 7b 0a 20 20 73 71 6c 69 74 65 33 20 2a 70 50  ){.  sqlite3 *pP
e530: 65 65 72 3b 20 20 20 20 20 20 20 20 20 20 2f 2a  eer;          /*
e540: 20 43 6f 6e 6e 65 63 74 69 6f 6e 20 74 6f 20 61   Connection to a
e550: 6e 6f 74 68 65 72 20 64 61 74 61 62 61 73 65 20  nother database 
e560: 2a 2f 0a 20 20 69 6e 74 20 6e 45 72 72 20 3d 20  */.  int nErr = 
e570: 30 3b 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a  0;            /*
e580: 20 4e 75 6d 62 65 72 20 6f 66 20 65 72 72 6f 72   Number of error
e590: 73 20 73 65 65 6e 20 73 6f 20 66 61 72 20 2a 2f  s seen so far */
e5a0: 0a 20 20 69 6e 74 20 72 63 3b 20 20 20 20 20 20  .  int rc;      
e5b0: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 52              /* R
e5c0: 65 73 75 6c 74 20 63 6f 64 65 20 66 72 6f 6d 20  esult code from 
e5d0: 73 75 62 72 6f 75 74 69 6e 65 20 63 61 6c 6c 73  subroutine calls
e5e0: 20 2a 2f 0a 20 20 63 68 61 72 20 2a 7a 45 72 72   */.  char *zErr
e5f0: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f  ;              /
e600: 2a 20 53 51 4c 69 74 65 20 65 72 72 6f 72 20 74  * SQLite error t
e610: 65 78 74 20 2a 2f 0a 20 20 63 68 61 72 20 2a 7a  ext */.  char *z
e620: 53 65 6c 66 43 6f 64 65 3b 20 20 20 20 20 20 20  SelfCode;       
e630: 20 20 2f 2a 20 50 72 6f 6a 65 63 74 20 63 6f 64    /* Project cod
e640: 65 20 66 6f 72 20 6f 75 72 73 65 6c 66 20 2a 2f  e for ourself */
e650: 0a 20 20 42 6c 6f 62 20 65 72 72 3b 20 20 20 20  .  Blob err;    
e660: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 41              /* A
e670: 63 63 75 6d 75 6c 61 74 65 20 65 72 72 6f 72 73  ccumulate errors
e680: 20 68 65 72 65 20 2a 2f 0a 20 20 53 74 6d 74 20   here */.  Stmt 
e690: 71 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  q;              
e6a0: 20 20 20 20 2f 2a 20 51 75 65 72 79 20 6f 66 20      /* Query of 
e6b0: 61 6c 6c 20 70 65 65 72 2d 2a 20 65 6e 74 72 69  all peer-* entri
e6c0: 65 73 20 69 6e 20 43 4f 4e 46 49 47 20 2a 2f 0a  es in CONFIG */.
e6d0: 0a 20 20 69 66 28 20 7a 50 72 65 66 69 78 3d 3d  .  if( zPrefix==
e6e0: 30 20 29 20 7a 50 72 65 66 69 78 20 3d 20 22 22  0 ) zPrefix = ""
e6f0: 3b 0a 20 20 69 66 28 20 7a 53 75 66 66 69 78 3d  ;.  if( zSuffix=
e700: 3d 30 20 29 20 7a 53 75 66 66 69 78 20 3d 20 22  =0 ) zSuffix = "
e710: 22 3b 0a 20 20 69 66 28 20 70 7a 45 72 72 6f 72  ";.  if( pzError
e720: 4d 73 67 20 29 20 2a 70 7a 45 72 72 6f 72 4d 73  Msg ) *pzErrorMs
e730: 67 20 3d 20 30 3b 0a 20 20 7a 53 65 6c 66 43 6f  g = 0;.  zSelfCo
e740: 64 65 20 3d 20 61 62 62 72 65 76 69 61 74 65 64  de = abbreviated
e750: 5f 70 72 6f 6a 65 63 74 5f 63 6f 64 65 28 64 62  _project_code(db
e760: 5f 67 65 74 28 22 70 72 6f 6a 65 63 74 2d 63 6f  _get("project-co
e770: 64 65 22 2c 20 22 78 22 29 29 3b 0a 20 20 62 6c  de", "x"));.  bl
e780: 6f 62 5f 7a 65 72 6f 28 26 65 72 72 29 3b 0a 20  ob_zero(&err);. 
e790: 20 64 62 5f 70 72 65 70 61 72 65 28 26 71 2c 0a   db_prepare(&q,.
e7a0: 20 20 20 20 22 53 45 4c 45 43 54 20 6e 61 6d 65      "SELECT name
e7b0: 2c 20 76 61 6c 75 65 20 46 52 4f 4d 20 63 6f 6e  , value FROM con
e7c0: 66 69 67 22 0a 20 20 20 20 22 20 57 48 45 52 45  fig".    " WHERE
e7d0: 20 6e 61 6d 65 20 47 4c 4f 42 20 27 70 65 65 72   name GLOB 'peer
e7e0: 2d 72 65 70 6f 2d 2a 27 22 0a 20 20 20 20 22 20  -repo-*'".    " 
e7f0: 20 20 41 4e 44 20 6e 61 6d 65 20 3c 3e 20 27 70    AND name <> 'p
e800: 65 65 72 2d 72 65 70 6f 2d 25 71 27 22 0a 20 20  eer-repo-%q'".  
e810: 20 20 22 20 4f 52 44 45 52 20 42 59 20 2b 76 61    " ORDER BY +va
e820: 6c 75 65 22 2c 0a 20 20 20 20 7a 53 65 6c 66 43  lue",.    zSelfC
e830: 6f 64 65 0a 20 20 29 3b 0a 20 20 77 68 69 6c 65  ode.  );.  while
e840: 28 20 64 62 5f 73 74 65 70 28 26 71 29 3d 3d 53  ( db_step(&q)==S
e850: 51 4c 49 54 45 5f 52 4f 57 20 29 7b 0a 20 20 20  QLITE_ROW ){.   
e860: 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 52 65   const char *zRe
e870: 70 6f 4e 61 6d 65 20 3d 20 64 62 5f 63 6f 6c 75  poName = db_colu
e880: 6d 6e 5f 74 65 78 74 28 26 71 2c 20 31 29 3b 0a  mn_text(&q, 1);.
e890: 20 20 20 20 69 66 28 20 66 69 6c 65 5f 73 69 7a      if( file_siz
e8a0: 65 28 7a 52 65 70 6f 4e 61 6d 65 2c 20 45 78 74  e(zRepoName, Ext
e8b0: 46 49 4c 45 29 3c 30 20 29 7b 0a 20 20 20 20 20  FILE)<0 ){.     
e8c0: 20 2f 2a 20 53 69 6c 65 6e 74 6c 79 20 72 65 6d   /* Silently rem
e8d0: 6f 76 65 20 6e 6f 6e 2d 65 78 69 73 74 65 6e 74  ove non-existent
e8e0: 20 72 65 70 6f 73 69 74 6f 72 69 65 73 20 66 72   repositories fr
e8f0: 6f 6d 20 74 68 65 20 6c 6f 67 69 6e 20 67 72 6f  om the login gro
e900: 75 70 2e 20 2a 2f 0a 20 20 20 20 20 20 63 6f 6e  up. */.      con
e910: 73 74 20 63 68 61 72 20 2a 7a 4c 61 62 65 6c 20  st char *zLabel 
e920: 3d 20 64 62 5f 63 6f 6c 75 6d 6e 5f 74 65 78 74  = db_column_text
e930: 28 26 71 2c 20 30 29 3b 0a 20 20 20 20 20 20 64  (&q, 0);.      d
e940: 62 5f 6d 75 6c 74 69 5f 65 78 65 63 28 0a 20 20  b_multi_exec(.  
e950: 20 20 20 20 20 20 20 22 44 45 4c 45 54 45 20 46         "DELETE F
e960: 52 4f 4d 20 63 6f 6e 66 69 67 20 57 48 45 52 45  ROM config WHERE
e970: 20 6e 61 6d 65 20 47 4c 4f 42 20 27 70 65 65 72   name GLOB 'peer
e980: 2d 2a 2d 25 71 27 22 2c 0a 20 20 20 20 20 20 20  -*-%q'",.       
e990: 20 20 26 7a 4c 61 62 65 6c 5b 31 30 5d 0a 20 20    &zLabel[10].  
e9a0: 20 20 20 20 29 3b 0a 20 20 20 20 20 20 63 6f 6e      );.      con
e9b0: 74 69 6e 75 65 3b 0a 20 20 20 20 7d 0a 20 20 20  tinue;.    }.   
e9c0: 20 72 63 20 3d 20 73 71 6c 69 74 65 33 5f 6f 70   rc = sqlite3_op
e9d0: 65 6e 5f 76 32 28 0a 20 20 20 20 20 20 20 20 20  en_v2(.         
e9e0: 7a 52 65 70 6f 4e 61 6d 65 2c 20 26 70 50 65 65  zRepoName, &pPee
e9f0: 72 2c 0a 20 20 20 20 20 20 20 20 20 53 51 4c 49  r,.         SQLI
ea00: 54 45 5f 4f 50 45 4e 5f 52 45 41 44 57 52 49 54  TE_OPEN_READWRIT
ea10: 45 2c 0a 20 20 20 20 20 20 20 20 20 67 2e 7a 56  E,.         g.zV
ea20: 66 73 4e 61 6d 65 0a 20 20 20 20 29 3b 0a 20 20  fsName.    );.  
ea30: 20 20 69 66 28 20 72 63 21 3d 53 51 4c 49 54 45    if( rc!=SQLITE
ea40: 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 62 6c 6f  _OK ){.      blo
ea50: 62 5f 61 70 70 65 6e 64 66 28 26 65 72 72 2c 20  b_appendf(&err, 
ea60: 22 25 73 25 73 3a 20 25 73 25 73 22 2c 20 7a 50  "%s%s: %s%s", zP
ea70: 72 65 66 69 78 2c 20 7a 52 65 70 6f 4e 61 6d 65  refix, zRepoName
ea80: 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,.              
ea90: 20 20 20 20 20 73 71 6c 69 74 65 33 5f 65 72 72       sqlite3_err
eaa0: 6d 73 67 28 70 50 65 65 72 29 2c 20 7a 53 75 66  msg(pPeer), zSuf
eab0: 66 69 78 29 3b 0a 20 20 20 20 20 20 6e 45 72 72  fix);.      nErr
eac0: 2b 2b 3b 0a 20 20 20 20 20 20 73 71 6c 69 74 65  ++;.      sqlite
ead0: 33 5f 63 6c 6f 73 65 28 70 50 65 65 72 29 3b 0a  3_close(pPeer);.
eae0: 20 20 20 20 20 20 63 6f 6e 74 69 6e 75 65 3b 0a        continue;.
eaf0: 20 20 20 20 7d 0a 20 20 20 20 73 71 6c 69 74 65      }.    sqlite
eb00: 33 5f 63 72 65 61 74 65 5f 66 75 6e 63 74 69 6f  3_create_functio
eb10: 6e 28 70 50 65 65 72 2c 20 22 73 68 61 72 65 64  n(pPeer, "shared
eb20: 5f 73 65 63 72 65 74 22 2c 20 33 2c 20 53 51 4c  _secret", 3, SQL
eb30: 49 54 45 5f 55 54 46 38 2c 0a 20 20 20 20 20 20  ITE_UTF8,.      
eb40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
eb50: 20 20 20 20 20 20 30 2c 20 73 68 61 31 5f 73 68        0, sha1_sh
eb60: 61 72 65 64 5f 73 65 63 72 65 74 5f 73 71 6c 5f  ared_secret_sql_
eb70: 66 75 6e 63 74 69 6f 6e 2c 20 30 2c 20 30 29 3b  function, 0, 0);
eb80: 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 63 72 65  .    sqlite3_cre
eb90: 61 74 65 5f 66 75 6e 63 74 69 6f 6e 28 70 50 65  ate_function(pPe
eba0: 65 72 2c 20 22 6e 6f 77 22 2c 20 30 2c 53 51 4c  er, "now", 0,SQL
ebb0: 49 54 45 5f 55 54 46 38 2c 30 2c 64 62 5f 6e 6f  ITE_UTF8,0,db_no
ebc0: 77 5f 66 75 6e 63 74 69 6f 6e 2c 30 2c 30 29 3b  w_function,0,0);
ebd0: 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 62 75 73  .    sqlite3_bus
ebe0: 79 5f 74 69 6d 65 6f 75 74 28 70 50 65 65 72 2c  y_timeout(pPeer,
ebf0: 20 35 30 30 30 29 3b 0a 20 20 20 20 7a 45 72 72   5000);.    zErr
ec00: 20 3d 20 30 3b 0a 20 20 20 20 72 63 20 3d 20 73   = 0;.    rc = s
ec10: 71 6c 69 74 65 33 5f 65 78 65 63 28 70 50 65 65  qlite3_exec(pPee
ec20: 72 2c 20 7a 53 71 6c 2c 20 30 2c 20 30 2c 20 26  r, zSql, 0, 0, &
ec30: 7a 45 72 72 29 3b 0a 20 20 20 20 69 66 28 20 7a  zErr);.    if( z
ec40: 45 72 72 20 29 7b 0a 20 20 20 20 20 20 62 6c 6f  Err ){.      blo
ec50: 62 5f 61 70 70 65 6e 64 66 28 26 65 72 72 2c 20  b_appendf(&err, 
ec60: 22 25 73 25 73 3a 20 25 73 25 73 22 2c 20 7a 50  "%s%s: %s%s", zP
ec70: 72 65 66 69 78 2c 20 7a 52 65 70 6f 4e 61 6d 65  refix, zRepoName
ec80: 2c 20 7a 45 72 72 2c 20 7a 53 75 66 66 69 78 29  , zErr, zSuffix)
ec90: 3b 0a 20 20 20 20 20 20 73 71 6c 69 74 65 33 5f  ;.      sqlite3_
eca0: 66 72 65 65 28 7a 45 72 72 29 3b 0a 20 20 20 20  free(zErr);.    
ecb0: 20 20 6e 45 72 72 2b 2b 3b 0a 20 20 20 20 7d 65    nErr++;.    }e
ecc0: 6c 73 65 20 69 66 28 20 72 63 21 3d 53 51 4c 49  lse if( rc!=SQLI
ecd0: 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 62  TE_OK ){.      b
ece0: 6c 6f 62 5f 61 70 70 65 6e 64 66 28 26 65 72 72  lob_appendf(&err
ecf0: 2c 20 22 25 73 25 73 3a 20 25 73 25 73 22 2c 20  , "%s%s: %s%s", 
ed00: 7a 50 72 65 66 69 78 2c 20 7a 52 65 70 6f 4e 61  zPrefix, zRepoNa
ed10: 6d 65 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20  me,.            
ed20: 20 20 20 20 20 20 20 73 71 6c 69 74 65 33 5f 65         sqlite3_e
ed30: 72 72 6d 73 67 28 70 50 65 65 72 29 2c 20 7a 53  rrmsg(pPeer), zS
ed40: 75 66 66 69 78 29 3b 0a 20 20 20 20 20 20 6e 45  uffix);.      nE
ed50: 72 72 2b 2b 3b 0a 20 20 20 20 7d 0a 20 20 20 20  rr++;.    }.    
ed60: 73 71 6c 69 74 65 33 5f 63 6c 6f 73 65 28 70 50  sqlite3_close(pP
ed70: 65 65 72 29 3b 0a 20 20 7d 0a 20 20 64 62 5f 66  eer);.  }.  db_f
ed80: 69 6e 61 6c 69 7a 65 28 26 71 29 3b 0a 20 20 69  inalize(&q);.  i
ed90: 66 28 20 70 7a 45 72 72 6f 72 4d 73 67 20 26 26  f( pzErrorMsg &&
eda0: 20 62 6c 6f 62 5f 73 69 7a 65 28 26 65 72 72 29   blob_size(&err)
edb0: 3e 30 20 29 7b 0a 20 20 20 20 2a 70 7a 45 72 72  >0 ){.    *pzErr
edc0: 6f 72 4d 73 67 20 3d 20 66 6f 73 73 69 6c 5f 73  orMsg = fossil_s
edd0: 74 72 64 75 70 28 62 6c 6f 62 5f 73 74 72 28 26  trdup(blob_str(&
ede0: 65 72 72 29 29 3b 0a 20 20 7d 0a 20 20 62 6c 6f  err));.  }.  blo
edf0: 62 5f 72 65 73 65 74 28 26 65 72 72 29 3b 0a 20  b_reset(&err);. 
ee00: 20 66 6f 73 73 69 6c 5f 66 72 65 65 28 7a 53 65   fossil_free(zSe
ee10: 6c 66 43 6f 64 65 29 3b 0a 20 20 72 65 74 75 72  lfCode);.  retur
ee20: 6e 20 6e 45 72 72 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a  n nErr;.}../*.**
ee30: 20 41 74 74 65 6d 70 74 20 74 6f 20 6a 6f 69 6e   Attempt to join
ee40: 20 61 20 6c 6f 67 69 6e 2d 67 72 6f 75 70 2e 0a   a login-group..
ee50: 2a 2a 0a 2a 2a 20 49 66 20 70 72 6f 62 6c 65 6d  **.** If problem
ee60: 73 20 61 72 69 73 65 2c 20 6c 65 61 76 65 20 61  s arise, leave a
ee70: 6e 20 65 72 72 6f 72 20 6d 65 73 73 61 67 65 20  n error message 
ee80: 69 6e 20 2a 70 7a 45 72 72 4d 73 67 2e 0a 2a 2f  in *pzErrMsg..*/
ee90: 0a 76 6f 69 64 20 6c 6f 67 69 6e 5f 67 72 6f 75  .void login_grou
eea0: 70 5f 6a 6f 69 6e 28 0a 20 20 63 6f 6e 73 74 20  p_join(.  const 
eeb0: 63 68 61 72 20 2a 7a 52 65 70 6f 2c 20 20 20 20  char *zRepo,    
eec0: 20 20 20 20 20 2f 2a 20 52 65 70 6f 73 69 74 6f       /* Reposito
eed0: 72 79 20 66 69 6c 65 20 69 6e 20 74 68 65 20 6c  ry file in the l
eee0: 6f 67 69 6e 20 67 72 6f 75 70 20 2a 2f 0a 20 20  ogin group */.  
eef0: 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 4c 6f 67  const char *zLog
ef00: 69 6e 2c 20 20 20 20 20 20 20 20 2f 2a 20 4c 6f  in,        /* Lo
ef10: 67 69 6e 20 6e 61 6d 65 20 66 6f 72 20 74 68 65  gin name for the
ef20: 20 6f 74 68 65 72 20 72 65 70 6f 20 2a 2f 0a 20   other repo */. 
ef30: 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 50 61   const char *zPa
ef40: 73 73 77 6f 72 64 2c 20 20 20 20 20 2f 2a 20 50  ssword,     /* P
ef50: 61 73 73 77 6f 72 64 20 74 6f 20 70 72 6f 76 65  assword to prove
ef60: 20 77 65 20 61 72 65 20 61 75 74 68 6f 72 69 7a   we are authoriz
ef70: 65 64 20 74 6f 20 6a 6f 69 6e 20 2a 2f 0a 20 20  ed to join */.  
ef80: 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 4e 65 77  const char *zNew
ef90: 4e 61 6d 65 2c 20 20 20 20 20 20 2f 2a 20 4e 61  Name,      /* Na
efa0: 6d 65 20 6f 66 20 6e 65 77 20 6c 6f 67 69 6e 20  me of new login 
efb0: 67 72 6f 75 70 20 69 66 20 6d 61 6b 69 6e 67 20  group if making 
efc0: 61 20 6e 65 77 20 6f 6e 65 20 2a 2f 0a 20 20 63  a new one */.  c
efd0: 68 61 72 20 2a 2a 70 7a 45 72 72 4d 73 67 20 20  har **pzErrMsg  
efe0: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4c 65 61            /* Lea
eff0: 76 65 20 61 6e 20 65 72 72 6f 72 20 6d 65 73 73  ve an error mess
f000: 61 67 65 20 68 65 72 65 20 2a 2f 0a 29 7b 0a 20  age here */.){. 
f010: 20 42 6c 6f 62 20 66 75 6c 6c 4e 61 6d 65 3b 20   Blob fullName; 
f020: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 42              /* B
f030: 6c 6f 62 20 66 6f 72 20 66 69 6e 64 69 6e 67 20  lob for finding 
f040: 66 75 6c 6c 20 70 61 74 68 6e 61 6d 65 73 20 2a  full pathnames *
f050: 2f 0a 20 20 73 71 6c 69 74 65 33 20 2a 70 4f 74  /.  sqlite3 *pOt
f060: 68 65 72 3b 20 20 20 20 20 20 20 20 20 20 20 2f  her;           /
f070: 2a 20 54 68 65 20 6f 74 68 65 72 20 72 65 70 6f  * The other repo
f080: 73 69 74 6f 72 79 20 2a 2f 0a 20 20 69 6e 74 20  sitory */.  int 
f090: 72 63 3b 20 20 20 20 20 20 20 20 20 20 20 20 20  rc;             
f0a0: 20 20 20 20 20 20 20 2f 2a 20 52 65 74 75 72 6e         /* Return
f0b0: 20 63 6f 64 65 20 66 72 6f 6d 20 73 71 6c 69 74   code from sqlit
f0c0: 65 33 20 66 75 6e 63 74 69 6f 6e 73 20 2a 2f 0a  e3 functions */.
f0d0: 20 20 63 68 61 72 20 2a 7a 4f 74 68 65 72 50 72    char *zOtherPr
f0e0: 6f 6a 43 6f 64 65 3b 20 20 20 20 20 20 2f 2a 20  ojCode;      /* 
f0f0: 50 72 6f 6a 65 63 74 20 63 6f 64 65 20 66 6f 72  Project code for
f100: 20 70 4f 74 68 65 72 20 2a 2f 0a 20 20 63 68 61   pOther */.  cha
f110: 72 20 2a 7a 50 77 48 61 73 68 3b 20 20 20 20 20  r *zPwHash;     
f120: 20 20 20 20 20 20 20 20 2f 2a 20 50 61 73 73 77          /* Passw
f130: 6f 72 64 20 68 61 73 68 20 6f 6e 20 70 4f 74 68  ord hash on pOth
f140: 65 72 20 2a 2f 0a 20 20 63 68 61 72 20 2a 7a 53  er */.  char *zS
f150: 65 6c 66 52 65 70 6f 3b 20 20 20 20 20 20 20 20  elfRepo;        
f160: 20 20 20 2f 2a 20 4e 61 6d 65 20 6f 66 20 6f 75     /* Name of ou
f170: 72 20 72 65 70 6f 73 69 74 6f 72 79 20 2a 2f 0a  r repository */.
f180: 20 20 63 68 61 72 20 2a 7a 53 65 6c 66 4c 61 62    char *zSelfLab
f190: 65 6c 3b 20 20 20 20 20 20 20 20 20 20 2f 2a 20  el;          /* 
f1a0: 50 72 6f 6a 65 63 74 2d 6e 61 6d 65 20 66 6f 72  Project-name for
f1b0: 20 6f 75 72 20 72 65 70 6f 73 69 74 6f 72 79 20   our repository 
f1c0: 2a 2f 0a 20 20 63 68 61 72 20 2a 7a 53 65 6c 66  */.  char *zSelf
f1d0: 50 72 6f 6a 43 6f 64 65 3b 20 20 20 20 20 20 20  ProjCode;       
f1e0: 2f 2a 20 4f 75 72 20 70 72 6f 6a 65 63 74 2d 63  /* Our project-c
f1f0: 6f 64 65 20 2a 2f 0a 20 20 63 68 61 72 20 2a 7a  ode */.  char *z
f200: 53 71 6c 3b 20 20 20 20 20 20 20 20 20 20 20 20  Sql;            
f210: 20 20 20 20 2f 2a 20 53 51 4c 20 74 6f 20 72 75      /* SQL to ru
f220: 6e 20 6f 6e 20 61 6c 6c 20 70 65 65 72 73 20 2a  n on all peers *
f230: 2f 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a  /.  const char *
f240: 7a 53 65 6c 66 3b 20 20 20 20 20 20 20 20 20 2f  zSelf;         /
f250: 2a 20 54 68 65 20 41 54 54 41 43 48 20 6e 61 6d  * The ATTACH nam
f260: 65 20 6f 66 20 6f 75 72 20 72 65 70 6f 73 69 74  e of our reposit
f270: 6f 72 79 20 2a 2f 0a 0a 20 20 2a 70 7a 45 72 72  ory */..  *pzErr
f280: 4d 73 67 20 3d 20 30 3b 20 20 20 2f 2a 20 44 65  Msg = 0;   /* De
f290: 66 61 75 6c 74 20 74 6f 20 6e 6f 20 65 72 72 6f  fault to no erro
f2a0: 72 73 20 2a 2f 0a 20 20 7a 53 65 6c 66 20 3d 20  rs */.  zSelf = 
f2b0: 22 72 65 70 6f 73 69 74 6f 72 79 22 3b 0a 0a 20  "repository";.. 
f2c0: 20 2f 2a 20 47 65 74 20 74 68 65 20 66 75 6c 6c   /* Get the full
f2d0: 20 70 61 74 68 6e 61 6d 65 20 6f 66 20 74 68 65   pathname of the
f2e0: 20 6f 74 68 65 72 20 72 65 70 6f 73 69 74 6f 72   other repositor
f2f0: 79 20 2a 2f 0a 20 20 66 69 6c 65 5f 63 61 6e 6f  y */.  file_cano
f300: 6e 69 63 61 6c 5f 6e 61 6d 65 28 7a 52 65 70 6f  nical_name(zRepo
f310: 2c 20 26 66 75 6c 6c 4e 61 6d 65 2c 20 30 29 3b  , &fullName, 0);
f320: 0a 20 20 7a 52 65 70 6f 20 3d 20 66 6f 73 73 69  .  zRepo = fossi
f330: 6c 5f 73 74 72 64 75 70 28 62 6c 6f 62 5f 73 74  l_strdup(blob_st
f340: 72 28 26 66 75 6c 6c 4e 61 6d 65 29 29 3b 0a 20  r(&fullName));. 
f350: 20 62 6c 6f 62 5f 72 65 73 65 74 28 26 66 75 6c   blob_reset(&ful
f360: 6c 4e 61 6d 65 29 3b 0a 0a 20 20 2f 2a 20 47 65  lName);..  /* Ge
f370: 74 20 74 68 65 20 66 75 6c 6c 20 70 61 74 68 6e  t the full pathn
f380: 61 6d 65 20 66 6f 72 20 6f 75 72 20 72 65 70 6f  ame for our repo
f390: 73 69 74 6f 72 79 2e 20 20 41 6c 73 6f 20 74 68  sitory.  Also th
f3a0: 65 20 70 72 6f 6a 65 63 74 20 63 6f 64 65 0a 20  e project code. 
f3b0: 20 2a 2a 20 61 6e 64 20 70 72 6f 6a 65 63 74 20   ** and project 
f3c0: 6e 61 6d 65 20 66 6f 72 20 6f 75 72 73 65 6c 66  name for ourself
f3d0: 2e 20 2a 2f 0a 20 20 66 69 6c 65 5f 63 61 6e 6f  . */.  file_cano
f3e0: 6e 69 63 61 6c 5f 6e 61 6d 65 28 67 2e 7a 52 65  nical_name(g.zRe
f3f0: 70 6f 73 69 74 6f 72 79 4e 61 6d 65 2c 20 26 66  positoryName, &f
f400: 75 6c 6c 4e 61 6d 65 2c 20 30 29 3b 0a 20 20 7a  ullName, 0);.  z
f410: 53 65 6c 66 52 65 70 6f 20 3d 20 66 6f 73 73 69  SelfRepo = fossi
f420: 6c 5f 73 74 72 64 75 70 28 62 6c 6f 62 5f 73 74  l_strdup(blob_st
f430: 72 28 26 66 75 6c 6c 4e 61 6d 65 29 29 3b 0a 20  r(&fullName));. 
f440: 20 62 6c 6f 62 5f 72 65 73 65 74 28 26 66 75 6c   blob_reset(&ful
f450: 6c 4e 61 6d 65 29 3b 0a 20 20 7a 53 65 6c 66 50  lName);.  zSelfP
f460: 72 6f 6a 43 6f 64 65 20 3d 20 64 62 5f 67 65 74  rojCode = db_get
f470: 28 22 70 72 6f 6a 65 63 74 2d 63 6f 64 65 22 2c  ("project-code",
f480: 20 22 75 6e 6b 6e 6f 77 6e 22 29 3b 0a 20 20 7a   "unknown");.  z
f490: 53 65 6c 66 4c 61 62 65 6c 20 3d 20 64 62 5f 67  SelfLabel = db_g
f4a0: 65 74 28 22 70 72 6f 6a 65 63 74 2d 6e 61 6d 65  et("project-name
f4b0: 22 2c 20 30 29 3b 0a 20 20 69 66 28 20 7a 53 65  ", 0);.  if( zSe
f4c0: 6c 66 4c 61 62 65 6c 3d 3d 30 20 29 7b 0a 20 20  lfLabel==0 ){.  
f4d0: 20 20 7a 53 65 6c 66 4c 61 62 65 6c 20 3d 20 7a    zSelfLabel = z
f4e0: 53 65 6c 66 50 72 6f 6a 43 6f 64 65 3b 0a 20 20  SelfProjCode;.  
f4f0: 7d 0a 0a 20 20 2f 2a 20 4d 61 6b 65 20 73 75 72  }..  /* Make sur
f500: 65 20 77 65 20 61 72 65 20 6e 6f 74 20 74 72 79  e we are not try
f510: 69 6e 67 20 74 6f 20 6a 6f 69 6e 20 6f 75 72 73  ing to join ours
f520: 65 6c 76 65 73 20 2a 2f 0a 20 20 69 66 28 20 66  elves */.  if( f
f530: 6f 73 73 69 6c 5f 73 74 72 63 6d 70 28 7a 52 65  ossil_strcmp(zRe
f540: 70 6f 2c 20 7a 53 65 6c 66 52 65 70 6f 29 3d 3d  po, zSelfRepo)==
f550: 30 20 29 7b 0a 20 20 20 20 2a 70 7a 45 72 72 4d  0 ){.    *pzErrM
f560: 73 67 20 3d 20 6d 70 72 69 6e 74 66 28 22 54 68  sg = mprintf("Th
f570: 65 20 5c 22 6f 74 68 65 72 5c 22 20 72 65 70 6f  e \"other\" repo
f580: 73 69 74 6f 72 79 20 69 73 20 74 68 65 20 73 61  sitory is the sa
f590: 6d 65 20 61 73 20 74 68 69 73 20 6f 6e 65 2e 22  me as this one."
f5a0: 29 3b 0a 20 20 20 20 72 65 74 75 72 6e 3b 0a 20  );.    return;. 
f5b0: 20 7d 0a 0a 20 20 2f 2a 20 4d 61 6b 65 20 73 75   }..  /* Make su
f5c0: 72 65 20 74 68 65 20 6f 74 68 65 72 20 72 65 70  re the other rep
f5d0: 6f 73 69 74 6f 72 79 20 69 73 20 61 20 76 61 6c  ository is a val
f5e0: 69 64 20 46 6f 73 73 69 6c 20 64 61 74 61 62 61  id Fossil databa
f5f0: 73 65 20 2a 2f 0a 20 20 69 66 28 20 66 69 6c 65  se */.  if( file
f600: 5f 73 69 7a 65 28 7a 52 65 70 6f 2c 20 45 78 74  _size(zRepo, Ext
f610: 46 49 4c 45 29 3c 30 20 29 7b 0a 20 20 20 20 2a  FILE)<0 ){.    *
f620: 70 7a 45 72 72 4d 73 67 20 3d 20 6d 70 72 69 6e  pzErrMsg = mprin
f630: 74 66 28 22 72 65 70 6f 73 69 74 6f 72 79 20 66  tf("repository f
f640: 69 6c 65 20 5c 22 25 73 5c 22 20 64 6f 65 73 20  ile \"%s\" does 
f650: 6e 6f 74 20 65 78 69 73 74 22 2c 20 7a 52 65 70  not exist", zRep
f660: 6f 29 3b 0a 20 20 20 20 72 65 74 75 72 6e 3b 0a  o);.    return;.
f670: 20 20 7d 0a 20 20 72 63 20 3d 20 73 71 6c 69 74    }.  rc = sqlit
f680: 65 33 5f 6f 70 65 6e 5f 76 32 28 0a 20 20 20 20  e3_open_v2(.    
f690: 20 20 20 7a 52 65 70 6f 2c 20 26 70 4f 74 68 65     zRepo, &pOthe
f6a0: 72 2c 0a 20 20 20 20 20 20 20 53 51 4c 49 54 45  r,.       SQLITE
f6b0: 5f 4f 50 45 4e 5f 52 45 41 44 57 52 49 54 45 20  _OPEN_READWRITE 
f6c0: 7c 20 53 51 4c 49 54 45 5f 4f 50 45 4e 5f 43 52  | SQLITE_OPEN_CR
f6d0: 45 41 54 45 2c 0a 20 20 20 20 20 20 20 67 2e 7a  EATE,.       g.z
f6e0: 56 66 73 4e 61 6d 65 0a 20 20 29 3b 0a 20 20 69  VfsName.  );.  i
f6f0: 66 28 20 72 63 21 3d 53 51 4c 49 54 45 5f 4f 4b  f( rc!=SQLITE_OK
f700: 20 29 7b 0a 20 20 20 20 2a 70 7a 45 72 72 4d 73   ){.    *pzErrMs
f710: 67 20 3d 20 66 6f 73 73 69 6c 5f 73 74 72 64 75  g = fossil_strdu
f720: 70 28 73 71 6c 69 74 65 33 5f 65 72 72 6d 73 67  p(sqlite3_errmsg
f730: 28 70 4f 74 68 65 72 29 29 3b 0a 20 20 7d 65 6c  (pOther));.  }el
f740: 73 65 7b 0a 20 20 20 20 72 63 20 3d 20 73 71 6c  se{.    rc = sql
f750: 69 74 65 33 5f 65 78 65 63 28 70 4f 74 68 65 72  ite3_exec(pOther
f760: 2c 20 22 53 45 4c 45 43 54 20 63 6f 75 6e 74 28  , "SELECT count(
f770: 2a 29 20 46 52 4f 4d 20 75 73 65 72 22 2c 20 30  *) FROM user", 0
f780: 2c 20 30 2c 20 70 7a 45 72 72 4d 73 67 29 3b 0a  , 0, pzErrMsg);.
f790: 20 20 7d 0a 20 20 73 71 6c 69 74 65 33 5f 63 6c    }.  sqlite3_cl
f7a0: 6f 73 65 28 70 4f 74 68 65 72 29 3b 0a 20 20 69  ose(pOther);.  i
f7b0: 66 28 20 72 63 20 29 20 72 65 74 75 72 6e 3b 0a  f( rc ) return;.
f7c0: 0a 20 20 2f 2a 20 41 74 74 61 63 68 20 74 68 65  .  /* Attach the
f7d0: 20 6f 74 68 65 72 20 72 65 70 6f 73 69 74 6f 72   other repositor
f7e0: 79 2e 20 20 4d 61 6b 65 20 73 75 72 65 20 74 68  y.  Make sure th
f7f0: 65 20 75 73 65 72 6e 61 6d 65 2f 70 61 73 73 77  e username/passw
f800: 6f 72 64 20 69 73 0a 20 20 2a 2a 20 76 61 6c 69  ord is.  ** vali
f810: 64 20 61 6e 64 20 68 61 73 20 53 65 74 75 70 20  d and has Setup 
f820: 70 65 72 6d 69 73 73 69 6f 6e 2e 0a 20 20 2a 2f  permission..  */
f830: 0a 20 20 64 62 5f 61 74 74 61 63 68 28 7a 52 65  .  db_attach(zRe
f840: 70 6f 2c 20 22 6f 74 68 65 72 22 29 3b 0a 20 20  po, "other");.  
f850: 7a 4f 74 68 65 72 50 72 6f 6a 43 6f 64 65 20 3d  zOtherProjCode =
f860: 20 64 62 5f 74 65 78 74 28 22 78 22 2c 20 22 53   db_text("x", "S
f870: 45 4c 45 43 54 20 76 61 6c 75 65 20 46 52 4f 4d  ELECT value FROM
f880: 20 6f 74 68 65 72 2e 63 6f 6e 66 69 67 22 0a 20   other.config". 
f890: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
f8a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 22                 "
f8b0: 20 57 48 45 52 45 20 6e 61 6d 65 3d 27 70 72 6f   WHERE name='pro
f8c0: 6a 65 63 74 2d 63 6f 64 65 27 22 29 3b 0a 20 20  ject-code'");.  
f8d0: 7a 50 77 48 61 73 68 20 3d 20 73 68 61 31 5f 73  zPwHash = sha1_s
f8e0: 68 61 72 65 64 5f 73 65 63 72 65 74 28 7a 50 61  hared_secret(zPa
f8f0: 73 73 77 6f 72 64 2c 20 7a 4c 6f 67 69 6e 2c 20  ssword, zLogin, 
f900: 7a 4f 74 68 65 72 50 72 6f 6a 43 6f 64 65 29 3b  zOtherProjCode);
f910: 0a 20 20 69 66 28 20 21 64 62 5f 65 78 69 73 74  .  if( !db_exist
f920: 73 28 0a 20 20 20 20 22 53 45 4c 45 43 54 20 31  s(.    "SELECT 1
f930: 20 46 52 4f 4d 20 6f 74 68 65 72 2e 75 73 65 72   FROM other.user
f940: 22 0a 20 20 20 20 22 20 57 48 45 52 45 20 6c 6f  ".    " WHERE lo
f950: 67 69 6e 3d 25 51 20 41 4e 44 20 63 61 70 20 47  gin=%Q AND cap G
f960: 4c 4f 42 20 27 2a 73 2a 27 22 0a 20 20 20 20 22  LOB '*s*'".    "
f970: 20 20 20 41 4e 44 20 28 70 77 3d 25 51 20 4f 52     AND (pw=%Q OR
f980: 20 70 77 3d 25 51 29 22 2c 0a 20 20 20 20 7a 4c   pw=%Q)",.    zL
f990: 6f 67 69 6e 2c 20 7a 50 61 73 73 77 6f 72 64 2c  ogin, zPassword,
f9a0: 20 7a 50 77 48 61 73 68 29 0a 20 20 29 7b 0a 20   zPwHash).  ){. 
f9b0: 20 20 20 64 62 5f 64 65 74 61 63 68 28 22 6f 74     db_detach("ot
f9c0: 68 65 72 22 29 3b 0a 20 20 20 20 2a 70 7a 45 72  her");.    *pzEr
f9d0: 72 4d 73 67 20 3d 20 22 54 68 65 20 73 75 70 70  rMsg = "The supp
f9e0: 6c 69 65 64 20 75 73 65 72 6e 61 6d 65 2f 70 61  lied username/pa
f9f0: 73 73 77 6f 72 64 20 64 6f 65 73 20 6e 6f 74 20  ssword does not 
fa00: 63 6f 72 72 65 73 70 6f 6e 64 20 74 6f 20 61 22  correspond to a"
fa10: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
fa20: 20 22 20 75 73 65 72 20 53 65 74 75 70 20 70 65   " user Setup pe
fa30: 72 6d 69 73 73 69 6f 6e 20 6f 6e 20 74 68 65 20  rmission on the 
fa40: 6f 74 68 65 72 20 72 65 70 6f 73 69 74 6f 72 79  other repository
fa50: 2e 22 3b 0a 20 20 20 20 72 65 74 75 72 6e 3b 0a  .";.    return;.
fa60: 20 20 7d 0a 0a 20 20 2f 2a 20 43 72 65 61 74 65    }..  /* Create
fa70: 20 61 6c 6c 20 74 68 65 20 6e 65 63 65 73 73 61   all the necessa
fa80: 72 79 20 43 4f 4e 46 49 47 20 74 61 62 6c 65 20  ry CONFIG table 
fa90: 65 6e 74 72 69 65 73 20 6f 6e 20 62 6f 74 68 20  entries on both 
faa0: 74 68 65 0a 20 20 2a 2a 20 6f 74 68 65 72 20 72  the.  ** other r
fab0: 65 70 6f 73 69 74 6f 72 79 20 61 6e 64 20 6f 6e  epository and on
fac0: 20 6f 75 72 20 6f 77 6e 20 72 65 70 6f 73 69 74   our own reposit
fad0: 6f 72 79 2e 0a 20 20 2a 2f 0a 20 20 7a 53 65 6c  ory..  */.  zSel
fae0: 66 50 72 6f 6a 43 6f 64 65 20 3d 20 61 62 62 72  fProjCode = abbr
faf0: 65 76 69 61 74 65 64 5f 70 72 6f 6a 65 63 74 5f  eviated_project_
fb00: 63 6f 64 65 28 7a 53 65 6c 66 50 72 6f 6a 43 6f  code(zSelfProjCo
fb10: 64 65 29 3b 0a 20 20 7a 4f 74 68 65 72 50 72 6f  de);.  zOtherPro
fb20: 6a 43 6f 64 65 20 3d 20 61 62 62 72 65 76 69 61  jCode = abbrevia
fb30: 74 65 64 5f 70 72 6f 6a 65 63 74 5f 63 6f 64 65  ted_project_code
fb40: 28 7a 4f 74 68 65 72 50 72 6f 6a 43 6f 64 65 29  (zOtherProjCode)
fb50: 3b 0a 20 20 64 62 5f 62 65 67 69 6e 5f 74 72 61  ;.  db_begin_tra
fb60: 6e 73 61 63 74 69 6f 6e 28 29 3b 0a 20 20 64 62  nsaction();.  db
fb70: 5f 6d 75 6c 74 69 5f 65 78 65 63 28 0a 20 20 20  _multi_exec(.   
fb80: 20 22 44 45 4c 45 54 45 20 46 52 4f 4d 20 5c 22   "DELETE FROM \"
fb90: 25 77 5c 22 2e 63 6f 6e 66 69 67 20 57 48 45 52  %w\".config WHER
fba0: 45 20 6e 61 6d 65 20 47 4c 4f 42 20 27 70 65 65  E name GLOB 'pee
fbb0: 72 2d 2a 27 3b 22 0a 20 20 20 20 22 49 4e 53 45  r-*';".    "INSE
fbc0: 52 54 20 49 4e 54 4f 20 5c 22 25 77 5c 22 2e 63  RT INTO \"%w\".c
fbd0: 6f 6e 66 69 67 28 6e 61 6d 65 2c 76 61 6c 75 65  onfig(name,value
fbe0: 29 20 56 41 4c 55 45 53 28 27 70 65 65 72 2d 72  ) VALUES('peer-r
fbf0: 65 70 6f 2d 25 71 27 2c 25 51 29 3b 22 0a 20 20  epo-%q',%Q);".  
fc00: 20 20 22 49 4e 53 45 52 54 20 49 4e 54 4f 20 5c    "INSERT INTO \
fc10: 22 25 77 5c 22 2e 63 6f 6e 66 69 67 28 6e 61 6d  "%w\".config(nam
fc20: 65 2c 76 61 6c 75 65 29 20 22 0a 20 20 20 20 22  e,value) ".    "
fc30: 20 20 53 45 4c 45 43 54 20 27 70 65 65 72 2d 6e    SELECT 'peer-n
fc40: 61 6d 65 2d 25 71 27 2c 20 76 61 6c 75 65 20 46  ame-%q', value F
fc50: 52 4f 4d 20 6f 74 68 65 72 2e 63 6f 6e 66 69 67  ROM other.config
fc60: 22 0a 20 20 20 20 22 20 20 20 57 48 45 52 45 20  ".    "   WHERE 
fc70: 6e 61 6d 65 3d 27 70 72 6f 6a 65 63 74 2d 6e 61  name='project-na
fc80: 6d 65 27 3b 22 2c 0a 20 20 20 20 7a 53 65 6c 66  me';",.    zSelf
fc90: 2c 0a 20 20 20 20 7a 53 65 6c 66 2c 20 7a 4f 74  ,.    zSelf, zOt
fca0: 68 65 72 50 72 6f 6a 43 6f 64 65 2c 20 7a 52 65  herProjCode, zRe
fcb0: 70 6f 2c 0a 20 20 20 20 7a 53 65 6c 66 2c 20 7a  po,.    zSelf, z
fcc0: 4f 74 68 65 72 50 72 6f 6a 43 6f 64 65 0a 20 20  OtherProjCode.  
fcd0: 29 3b 0a 20 20 64 62 5f 6d 75 6c 74 69 5f 65 78  );.  db_multi_ex
fce0: 65 63 28 0a 20 20 20 20 22 49 4e 53 45 52 54 20  ec(.    "INSERT 
fcf0: 4f 52 20 49 47 4e 4f 52 45 20 49 4e 54 4f 20 6f  OR IGNORE INTO o
fd00: 74 68 65 72 2e 63 6f 6e 66 69 67 28 6e 61 6d 65  ther.config(name
fd10: 2c 76 61 6c 75 65 29 22 0a 20 20 20 20 22 20 56  ,value)".    " V
fd20: 41 4c 55 45 53 28 27 6c 6f 67 69 6e 2d 67 72 6f  ALUES('login-gro
fd30: 75 70 2d 6e 61 6d 65 27 2c 25 51 29 3b 22 0a 20  up-name',%Q);". 
fd40: 20 20 20 22 49 4e 53 45 52 54 20 4f 52 20 49 47     "INSERT OR IG
fd50: 4e 4f 52 45 20 49 4e 54 4f 20 6f 74 68 65 72 2e  NORE INTO other.
fd60: 63 6f 6e 66 69 67 28 6e 61 6d 65 2c 76 61 6c 75  config(name,valu
fd70: 65 29 22 0a 20 20 20 20 22 20 56 41 4c 55 45 53  e)".    " VALUES
fd80: 28 27 6c 6f 67 69 6e 2d 67 72 6f 75 70 2d 63 6f  ('login-group-co
fd90: 64 65 27 2c 6c 6f 77 65 72 28 68 65 78 28 72 61  de',lower(hex(ra
fda0: 6e 64 6f 6d 62 6c 6f 62 28 38 29 29 29 29 3b 22  ndomblob(8))));"
fdb0: 2c 0a 20 20 20 20 7a 4e 65 77 4e 61 6d 65 0a 20  ,.    zNewName. 
fdc0: 20 29 3b 0a 20 20 64 62 5f 6d 75 6c 74 69 5f 65   );.  db_multi_e
fdd0: 78 65 63 28 0a 20 20 20 20 22 52 45 50 4c 41 43  xec(.    "REPLAC
fde0: 45 20 49 4e 54 4f 20 5c 22 25 77 5c 22 2e 63 6f  E INTO \"%w\".co
fdf0: 6e 66 69 67 28 6e 61 6d 65 2c 76 61 6c 75 65 29  nfig(name,value)
fe00: 22 0a 20 20 20 20 22 20 20 53 45 4c 45 43 54 20  ".    "  SELECT 
fe10: 6e 61 6d 65 2c 20 76 61 6c 75 65 20 46 52 4f 4d  name, value FROM
fe20: 20 6f 74 68 65 72 2e 63 6f 6e 66 69 67 22 0a 20   other.config". 
fe30: 20 20 20 22 20 20 20 57 48 45 52 45 20 6e 61 6d     "   WHERE nam
fe40: 65 20 47 4c 4f 42 20 27 70 65 65 72 2d 2a 27 20  e GLOB 'peer-*' 
fe50: 4f 52 20 6e 61 6d 65 20 47 4c 4f 42 20 27 6c 6f  OR name GLOB 'lo
fe60: 67 69 6e 2d 67 72 6f 75 70 2d 2a 27 22 2c 0a 20  gin-group-*'",. 
fe70: 20 20 20 7a 53 65 6c 66 0a 20 20 29 3b 0a 20 20     zSelf.  );.  
fe80: 64 62 5f 65 6e 64 5f 74 72 61 6e 73 61 63 74 69  db_end_transacti
fe90: 6f 6e 28 30 29 3b 0a 20 20 64 62 5f 6d 75 6c 74  on(0);.  db_mult
fea0: 69 5f 65 78 65 63 28 22 44 45 54 41 43 48 20 6f  i_exec("DETACH o
feb0: 74 68 65 72 22 29 3b 0a 0a 20 20 2f 2a 20 50 72  ther");..  /* Pr
fec0: 6f 70 61 67 61 74 65 20 74 68 65 20 63 68 61 6e  opagate the chan
fed0: 67 65 73 20 74 6f 20 61 6c 6c 20 6f 74 68 65 72  ges to all other
fee0: 20 6d 65 6d 62 65 72 73 20 6f 66 20 74 68 65 20   members of the 
fef0: 6c 6f 67 69 6e 2d 67 72 6f 75 70 20 2a 2f 0a 20  login-group */. 
ff00: 20 7a 53 71 6c 20 3d 20 6d 70 72 69 6e 74 66 28   zSql = mprintf(
ff10: 0a 20 20 20 20 22 42 45 47 49 4e 3b 22 0a 20 20  .    "BEGIN;".  
ff20: 20 20 22 52 45 50 4c 41 43 45 20 49 4e 54 4f 20    "REPLACE INTO 
ff30: 63 6f 6e 66 69 67 28 6e 61 6d 65 2c 76 61 6c 75  config(name,valu
ff40: 65 2c 6d 74 69 6d 65 29 20 56 41 4c 55 45 53 28  e,mtime) VALUES(
ff50: 27 70 65 65 72 2d 6e 61 6d 65 2d 25 71 27 2c 25  'peer-name-%q',%
ff60: 51 2c 6e 6f 77 28 29 29 3b 22 0a 20 20 20 20 22  Q,now());".    "
ff70: 52 45 50 4c 41 43 45 20 49 4e 54 4f 20 63 6f 6e  REPLACE INTO con
ff80: 66 69 67 28 6e 61 6d 65 2c 76 61 6c 75 65 2c 6d  fig(name,value,m
ff90: 74 69 6d 65 29 20 56 41 4c 55 45 53 28 27 70 65  time) VALUES('pe
ffa0: 65 72 2d 72 65 70 6f 2d 25 71 27 2c 25 51 2c 6e  er-repo-%q',%Q,n
ffb0: 6f 77 28 29 29 3b 22 0a 20 20 20 20 22 43 4f 4d  ow());".    "COM
ffc0: 4d 49 54 3b 22 2c 0a 20 20 20 20 7a 53 65 6c 66  MIT;",.    zSelf
ffd0: 50 72 6f 6a 43 6f 64 65 2c 20 7a 53 65 6c 66 4c  ProjCode, zSelfL
ffe0: 61 62 65 6c 2c 20 7a 53 65 6c 66 50 72 6f 6a 43  abel, zSelfProjC
fff0: 6f 64 65 2c 20 7a 53 65 6c 66 52 65 70 6f 0a 20  ode, zSelfRepo. 
10000 20 29 3b 0a 20 20 6c 6f 67 69 6e 5f 67 72 6f 75   );.  login_grou
10010 70 5f 73 71 6c 28 7a 53 71 6c 2c 20 22 3c 6c 69  p_sql(zSql, "<li
10020 3e 20 22 2c 20 22 3c 2f 6c 69 3e 22 2c 20 70 7a  > ", "</li>", pz
10030 45 72 72 4d 73 67 29 3b 0a 20 20 66 6f 73 73 69  ErrMsg);.  fossi
10040 6c 5f 66 72 65 65 28 7a 53 71 6c 29 3b 0a 7d 0a  l_free(zSql);.}.
10050 0a 2f 2a 0a 2a 2a 20 4c 65 61 76 65 20 74 68 65  ./*.** Leave the
10060 20 6c 6f 67 69 6e 20 67 72 6f 75 70 20 74 68 61   login group tha
10070 74 20 77 65 20 61 72 65 20 63 75 72 72 65 6e 74  t we are current
10080 6c 79 20 70 61 72 74 20 6f 66 2e 0a 2a 2f 0a 76  ly part of..*/.v
10090 6f 69 64 20 6c 6f 67 69 6e 5f 67 72 6f 75 70 5f  oid login_group_
100a0 6c 65 61 76 65 28 63 68 61 72 20 2a 2a 70 7a 45  leave(char **pzE
100b0 72 72 4d 73 67 29 7b 0a 20 20 63 68 61 72 20 2a  rrMsg){.  char *
100c0 7a 50 72 6f 6a 43 6f 64 65 3b 0a 20 20 63 68 61  zProjCode;.  cha
100d0 72 20 2a 7a 53 71 6c 3b 0a 0a 20 20 2a 70 7a 45  r *zSql;..  *pzE
100e0 72 72 4d 73 67 20 3d 20 30 3b 0a 20 20 7a 50 72  rrMsg = 0;.  zPr
100f0 6f 6a 43 6f 64 65 20 3d 20 61 62 62 72 65 76 69  ojCode = abbrevi
10100 61 74 65 64 5f 70 72 6f 6a 65 63 74 5f 63 6f 64  ated_project_cod
10110 65 28 64 62 5f 67 65 74 28 22 70 72 6f 6a 65 63  e(db_get("projec
10120 74 2d 63 6f 64 65 22 2c 22 78 22 29 29 3b 0a 20  t-code","x"));. 
10130 20 7a 53 71 6c 20 3d 20 6d 70 72 69 6e 74 66 28   zSql = mprintf(
10140 0a 20 20 20 20 22 44 45 4c 45 54 45 20 46 52 4f  .    "DELETE FRO
10150 4d 20 63 6f 6e 66 69 67 20 57 48 45 52 45 20 6e  M config WHERE n
10160 61 6d 65 20 47 4c 4f 42 20 27 70 65 65 72 2d 2a  ame GLOB 'peer-*
10170 2d 25 71 27 3b 22 0a 20 20 20 20 22 44 45 4c 45  -%q';".    "DELE
10180 54 45 20 46 52 4f 4d 20 63 6f 6e 66 69 67 22 0a  TE FROM config".
10190 20 20 20 20 22 20 57 48 45 52 45 20 6e 61 6d 65      " WHERE name
101a0 3d 27 6c 6f 67 69 6e 2d 67 72 6f 75 70 2d 6e 61  ='login-group-na
101b0 6d 65 27 22 0a 20 20 20 20 22 20 20 20 41 4e 44  me'".    "   AND
101c0 20 28 53 45 4c 45 43 54 20 63 6f 75 6e 74 28 2a   (SELECT count(*
101d0 29 20 46 52 4f 4d 20 63 6f 6e 66 69 67 20 57 48  ) FROM config WH
101e0 45 52 45 20 6e 61 6d 65 20 47 4c 4f 42 20 27 70  ERE name GLOB 'p
101f0 65 65 72 2d 2a 27 29 3d 3d 30 3b 22 2c 0a 20 20  eer-*')==0;",.  
10200 20 20 7a 50 72 6f 6a 43 6f 64 65 0a 20 20 29 3b    zProjCode.  );
10210 0a 20 20 66 6f 73 73 69 6c 5f 66 72 65 65 28 7a  .  fossil_free(z
10220 50 72 6f 6a 43 6f 64 65 29 3b 0a 20 20 6c 6f 67  ProjCode);.  log
10230 69 6e 5f 67 72 6f 75 70 5f 73 71 6c 28 7a 53 71  in_group_sql(zSq
10240 6c 2c 20 22 3c 6c 69 3e 20 22 2c 20 22 3c 2f 6c  l, "<li> ", "</l
10250 69 3e 22 2c 20 70 7a 45 72 72 4d 73 67 29 3b 0a  i>", pzErrMsg);.
10260 20 20 66 6f 73 73 69 6c 5f 66 72 65 65 28 7a 53    fossil_free(zS
10270 71 6c 29 3b 0a 20 20 64 62 5f 6d 75 6c 74 69 5f  ql);.  db_multi_
10280 65 78 65 63 28 0a 20 20 20 20 22 44 45 4c 45 54  exec(.    "DELET
10290 45 20 46 52 4f 4d 20 63 6f 6e 66 69 67 20 22 0a  E FROM config ".
102a0 20 20 20 20 22 20 57 48 45 52 45 20 6e 61 6d 65      " WHERE name
102b0 20 47 4c 4f 42 20 27 70 65 65 72 2d 2a 27 22 0a   GLOB 'peer-*'".
102c0 20 20 20 20 22 20 20 20 20 4f 52 20 6e 61 6d 65      "    OR name
102d0 20 47 4c 4f 42 20 27 6c 6f 67 69 6e 2d 67 72 6f   GLOB 'login-gro
102e0 75 70 2d 2a 27 3b 22 0a 20 20 29 3b 0a 7d 0a     up-*';".  );.}.