Fossil

Hex Artifact Content
Login

Artifact 889d6724939894d2825d5be2292f097caae7742ebe8019974abc102fc0e54c4d:


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 55 73 65 72 6e 61 6d 65  .**.** zUsername
18b0: 20 75 73 65 73 20 64 6f 75 62 6c 65 20 69 6e 64   uses double ind
18c0: 69 72 65 63 74 69 6f 6e 20 62 65 63 61 75 73 65  irection because
18d0: 20 77 65 20 6d 61 79 20 72 65 2d 70 6f 69 6e 74   we may re-point
18e0: 20 2a 7a 55 73 65 72 6e 61 6d 65 0a 2a 2a 20 61   *zUsername.** a
18f0: 74 20 61 20 43 20 73 74 72 69 6e 67 20 61 6c 6c  t a C string all
1900: 6f 63 61 74 65 64 20 77 69 74 68 20 66 6f 73 73  ocated with foss
1910: 69 6c 5f 73 74 72 64 75 70 28 29 20 69 66 20 79  il_strdup() if y
1920: 6f 75 20 70 61 73 73 20 61 6e 20 65 6d 61 69 6c  ou pass an email
1930: 0a 2a 2a 20 61 64 64 72 65 73 73 20 69 6e 73 74  .** address inst
1940: 65 61 64 20 61 6e 64 20 77 65 20 66 69 6e 64 20  ead and we find 
1950: 74 68 61 74 20 61 64 64 72 65 73 73 20 69 6e 20  that address in 
1960: 74 68 65 20 75 73 65 72 20 74 61 62 6c 65 27 73  the user table's
1970: 20 69 6e 66 6f 0a 2a 2a 20 66 69 65 6c 64 2c 20   info.** field, 
1980: 77 68 69 63 68 20 69 73 20 65 78 70 65 63 74 65  which is expecte
1990: 64 20 74 6f 20 63 6f 6e 74 61 69 6e 20 61 20 73  d to contain a s
19a0: 74 72 69 6e 67 20 6f 66 20 74 68 65 20 66 6f 72  tring of the for
19b0: 6d 20 22 48 75 6d 61 6e 20 4e 61 6d 65 0a 2a 2a  m "Human Name.**
19c0: 20 3c 68 75 6d 61 6e 40 65 78 61 6d 70 6c 65 2e   <human@example.
19d0: 63 6f 6d 3e 22 2e 20 20 49 6e 20 74 68 61 74 20  com>".  In that 
19e0: 63 61 73 65 2c 20 2a 7a 55 73 65 72 6e 61 6d 65  case, *zUsername
19f0: 20 77 69 6c 6c 20 70 6f 69 6e 74 20 74 6f 20 74   will point to t
1a00: 68 61 74 0a 2a 2a 20 75 73 65 72 27 73 20 61 63  hat.** user's ac
1a10: 74 75 61 6c 20 6c 6f 67 69 6e 20 6e 61 6d 65 20  tual login name 
1a20: 6f 6e 20 72 65 74 75 72 6e 2c 20 63 61 75 73 69  on return, causi
1a30: 6e 67 20 61 20 6c 65 61 6b 20 75 6e 6c 65 73 73  ng a leak unless
1a40: 20 74 68 65 20 63 61 6c 6c 65 72 0a 2a 2a 20 69   the caller.** i
1a50: 73 20 64 69 6c 69 67 65 6e 74 20 65 6e 6f 75 67  s diligent enoug
1a60: 68 20 74 6f 20 63 68 65 63 6b 20 77 68 65 74 68  h to check wheth
1a70: 65 72 20 69 74 73 20 70 6f 69 6e 74 65 72 20 77  er its pointer w
1a80: 61 73 20 72 65 2d 70 6f 69 6e 74 65 64 2e 0a 2a  as re-pointed..*
1a90: 2a 0a 2a 2a 20 7a 50 61 73 73 77 6f 72 64 20 6d  *.** zPassword m
1aa0: 61 79 20 62 65 20 65 69 74 68 65 72 20 74 68 65  ay be either the
1ab0: 20 70 6c 61 69 6e 2d 74 65 78 74 20 66 6f 72 6d   plain-text form
1ac0: 20 6f 72 20 74 68 65 20 65 6e 63 72 79 70 74 65   or the encrypte
1ad0: 64 0a 2a 2a 20 66 6f 72 6d 20 6f 66 20 74 68 65  d.** form of the
1ae0: 20 75 73 65 72 27 73 20 70 61 73 73 77 6f 72 64   user's password
1af0: 2e 0a 2a 2f 0a 69 6e 74 20 6c 6f 67 69 6e 5f 73  ..*/.int login_s
1b00: 65 61 72 63 68 5f 75 69 64 28 63 6f 6e 73 74 20  earch_uid(const 
1b10: 63 68 61 72 20 2a 2a 70 7a 55 73 65 72 6e 61 6d  char **pzUsernam
1b20: 65 2c 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a  e, const char *z
1b30: 50 61 73 73 77 64 29 7b 0a 20 20 63 68 61 72 20  Passwd){.  char 
1b40: 2a 7a 53 68 61 31 50 77 20 3d 20 73 68 61 31 5f  *zSha1Pw = sha1_
1b50: 73 68 61 72 65 64 5f 73 65 63 72 65 74 28 7a 50  shared_secret(zP
1b60: 61 73 73 77 64 2c 20 2a 70 7a 55 73 65 72 6e 61  asswd, *pzUserna
1b70: 6d 65 2c 20 30 29 3b 0a 20 20 69 6e 74 20 75 69  me, 0);.  int ui
1b80: 64 20 3d 20 64 62 5f 69 6e 74 28 30 2c 0a 20 20  d = db_int(0,.  
1b90: 20 20 22 53 45 4c 45 43 54 20 75 69 64 20 46 52    "SELECT uid FR
1ba0: 4f 4d 20 75 73 65 72 22 0a 20 20 20 20 22 20 57  OM user".    " W
1bb0: 48 45 52 45 20 6c 6f 67 69 6e 3d 25 51 22 0a 20  HERE login=%Q". 
1bc0: 20 20 20 22 20 20 20 41 4e 44 20 6c 65 6e 67 74     "   AND lengt
1bd0: 68 28 63 61 70 29 3e 30 20 41 4e 44 20 6c 65 6e  h(cap)>0 AND len
1be0: 67 74 68 28 70 77 29 3e 30 22 0a 20 20 20 20 22  gth(pw)>0".    "
1bf0: 20 20 20 41 4e 44 20 6c 6f 67 69 6e 20 4e 4f 54     AND login NOT
1c00: 20 49 4e 20 28 27 61 6e 6f 6e 79 6d 6f 75 73 27   IN ('anonymous'
1c10: 2c 27 6e 6f 62 6f 64 79 27 2c 27 64 65 76 65 6c  ,'nobody','devel
1c20: 6f 70 65 72 27 2c 27 72 65 61 64 65 72 27 29 22  oper','reader')"
1c30: 0a 20 20 20 20 22 20 20 20 41 4e 44 20 28 70 77  .    "   AND (pw
1c40: 3d 25 51 20 4f 52 20 28 6c 65 6e 67 74 68 28 70  =%Q OR (length(p
1c50: 77 29 3c 3e 34 30 20 41 4e 44 20 70 77 3d 25 51  w)<>40 AND pw=%Q
1c60: 29 29 22 0a 20 20 20 20 22 20 20 20 41 4e 44 20  ))".    "   AND 
1c70: 28 69 6e 66 6f 20 4e 4f 54 20 4c 49 4b 45 20 27  (info NOT LIKE '
1c80: 25 25 65 78 70 69 72 65 73 20 32 30 25 25 27 22  %%expires 20%%'"
1c90: 0a 20 20 20 20 22 20 20 20 20 20 20 4f 52 20 73  .    "      OR s
1ca0: 75 62 73 74 72 28 69 6e 66 6f 2c 69 6e 73 74 72  ubstr(info,instr
1cb0: 28 6c 6f 77 65 72 28 69 6e 66 6f 29 2c 27 65 78  (lower(info),'ex
1cc0: 70 69 72 65 73 27 29 2b 38 2c 31 30 29 3e 64 61  pires')+8,10)>da
1cd0: 74 65 74 69 6d 65 28 27 6e 6f 77 27 29 29 22 2c  tetime('now'))",
1ce0: 0a 20 20 20 20 2a 70 7a 55 73 65 72 6e 61 6d 65  .    *pzUsername
1cf0: 2c 20 7a 53 68 61 31 50 77 2c 20 7a 50 61 73 73  , zSha1Pw, zPass
1d00: 77 64 0a 20 20 29 3b 0a 0a 20 20 2f 2a 20 49 66  wd.  );..  /* If
1d10: 20 77 65 20 64 69 64 20 6e 6f 74 20 66 69 6e 64   we did not find
1d20: 20 61 20 6c 6f 67 69 6e 20 6f 6e 20 74 68 65 20   a login on the 
1d30: 66 69 72 73 74 20 61 74 74 65 6d 70 74 2c 20 61  first attempt, a
1d40: 6e 64 20 74 68 65 20 75 73 65 72 6e 61 6d 65 0a  nd the username.
1d50: 20 20 2a 2a 20 6c 6f 6f 6b 73 20 6c 69 6b 65 20    ** looks like 
1d60: 61 6e 20 65 6d 61 69 6c 20 61 64 64 72 65 73 73  an email address
1d70: 2c 20 74 68 65 6e 20 70 65 72 68 61 70 73 20 74  , then perhaps t
1d80: 68 65 20 75 73 65 72 20 65 6e 74 65 72 65 64 20  he user entered 
1d90: 74 68 65 69 72 0a 20 20 2a 2a 20 65 6d 61 69 6c  their.  ** email
1da0: 20 61 64 64 72 65 73 73 20 69 6e 73 74 65 61 64   address instead
1db0: 20 6f 66 20 74 68 65 69 72 20 6c 6f 67 69 6e 2e   of their login.
1dc0: 20 20 54 72 79 20 61 67 61 69 6e 20 74 6f 20 6d    Try again to m
1dd0: 61 74 63 68 20 74 68 65 20 75 73 65 72 0a 20 20  atch the user.  
1de0: 2a 2a 20 61 67 61 69 6e 73 74 20 65 6d 61 69 6c  ** against email
1df0: 20 61 64 64 72 65 73 73 65 73 20 63 6f 6e 74 61   addresses conta
1e00: 69 6e 65 64 20 69 6e 20 74 68 65 20 22 69 6e 66  ined in the "inf
1e10: 6f 22 20 66 69 65 6c 64 2e 0a 20 20 2a 2f 0a 20  o" field..  */. 
1e20: 20 69 66 28 20 75 69 64 3d 3d 30 20 26 26 20 73   if( uid==0 && s
1e30: 74 72 63 68 72 28 2a 70 7a 55 73 65 72 6e 61 6d  trchr(*pzUsernam
1e40: 65 2c 27 40 27 29 21 3d 30 20 29 7b 0a 20 20 20  e,'@')!=0 ){.   
1e50: 20 53 74 6d 74 20 71 3b 0a 20 20 20 20 64 62 5f   Stmt q;.    db_
1e60: 70 72 65 70 61 72 65 28 26 71 2c 0a 20 20 20 20  prepare(&q,.    
1e70: 20 20 22 53 45 4c 45 43 54 20 6c 6f 67 69 6e 20    "SELECT login 
1e80: 46 52 4f 4d 20 75 73 65 72 22 0a 20 20 20 20 20  FROM user".     
1e90: 20 22 20 57 48 45 52 45 20 66 69 6e 64 5f 65 6d   " WHERE find_em
1ea0: 61 69 6c 61 64 64 72 28 69 6e 66 6f 29 3d 25 51  ailaddr(info)=%Q
1eb0: 22 0a 20 20 20 20 20 20 22 20 20 20 41 4e 44 20  ".      "   AND 
1ec0: 69 6e 73 74 72 28 6c 6f 67 69 6e 2c 27 40 27 29  instr(login,'@')
1ed0: 3d 3d 30 22 2c 0a 20 20 20 20 20 20 2a 70 7a 55  ==0",.      *pzU
1ee0: 73 65 72 6e 61 6d 65 0a 20 20 20 20 29 3b 0a 20  sername.    );. 
1ef0: 20 20 20 77 68 69 6c 65 28 20 64 62 5f 73 74 65     while( db_ste
1f00: 70 28 26 71 29 3d 3d 53 51 4c 49 54 45 5f 52 4f  p(&q)==SQLITE_RO
1f10: 57 20 29 7b 0a 20 20 20 20 20 20 63 6f 6e 73 74  W ){.      const
1f20: 20 63 68 61 72 20 2a 7a 4c 6f 67 69 6e 20 3d 20   char *zLogin = 
1f30: 64 62 5f 63 6f 6c 75 6d 6e 5f 74 65 78 74 28 26  db_column_text(&
1f40: 71 2c 30 29 3b 0a 20 20 20 20 20 20 69 66 28 20  q,0);.      if( 
1f50: 28 75 69 64 20 3d 20 6c 6f 67 69 6e 5f 73 65 61  (uid = login_sea
1f60: 72 63 68 5f 75 69 64 28 26 7a 4c 6f 67 69 6e 2c  rch_uid(&zLogin,
1f70: 20 7a 50 61 73 73 77 64 29 20 29 20 21 3d 20 30   zPasswd) ) != 0
1f80: 20 29 7b 0a 20 20 20 20 20 20 20 20 2a 70 7a 55   ){.        *pzU
1f90: 73 65 72 6e 61 6d 65 20 3d 20 66 6f 73 73 69 6c  sername = fossil
1fa0: 5f 73 74 72 64 75 70 28 7a 4c 6f 67 69 6e 29 3b  _strdup(zLogin);
1fb0: 0a 20 20 20 20 20 20 20 20 62 72 65 61 6b 3b 0a  .        break;.
1fc0: 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a 20 20        }.    }.  
1fd0: 20 20 64 62 5f 66 69 6e 61 6c 69 7a 65 28 26 71    db_finalize(&q
1fe0: 29 3b 0a 20 20 7d 20 20 20 20 0a 20 20 66 72 65  );.  }    .  fre
1ff0: 65 28 7a 53 68 61 31 50 77 29 3b 0a 20 20 72 65  e(zSha1Pw);.  re
2000: 74 75 72 6e 20 75 69 64 3b 0a 7d 0a 0a 2f 2a 0a  turn uid;.}../*.
2010: 2a 2a 20 47 65 6e 65 72 61 74 65 73 20 61 20 6c  ** Generates a l
2020: 6f 67 69 6e 20 63 6f 6f 6b 69 65 20 76 61 6c 75  ogin cookie valu
2030: 65 20 66 6f 72 20 61 20 6e 6f 6e 2d 61 6e 6f 6e  e for a non-anon
2040: 79 6d 6f 75 73 20 75 73 65 72 2e 0a 2a 2a 0a 2a  ymous user..**.*
2050: 2a 20 54 68 65 20 7a 48 61 73 68 20 70 61 72 61  * The zHash para
2060: 6d 65 74 65 72 20 6d 75 73 74 20 62 65 20 61 20  meter must be a 
2070: 72 61 6e 64 6f 6d 20 76 61 6c 75 65 20 77 68 69  random value whi
2080: 63 68 20 6d 75 73 74 20 62 65 0a 2a 2a 20 73 75  ch must be.** su
2090: 62 73 65 71 75 65 6e 74 6c 79 20 73 74 6f 72 65  bsequently store
20a0: 64 20 69 6e 20 75 73 65 72 2e 63 6f 6f 6b 69 65  d in user.cookie
20b0: 20 66 6f 72 20 6c 61 74 65 72 20 76 61 6c 69 64   for later valid
20c0: 61 74 69 6f 6e 2e 0a 2a 2a 0a 2a 2a 20 54 68 65  ation..**.** The
20d0: 20 72 65 74 75 72 6e 65 64 20 6d 65 6d 6f 72 79   returned memory
20e0: 20 73 68 6f 75 6c 64 20 62 65 20 66 72 65 65 28   should be free(
20f0: 29 64 20 61 66 74 65 72 20 75 73 65 2e 0a 2a 2f  )d after use..*/
2100: 0a 63 68 61 72 20 2a 6c 6f 67 69 6e 5f 67 65 6e  .char *login_gen
2110: 5f 75 73 65 72 5f 63 6f 6f 6b 69 65 5f 76 61 6c  _user_cookie_val
2120: 75 65 28 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a  ue(const char *z
2130: 55 73 65 72 6e 61 6d 65 2c 20 63 6f 6e 73 74 20  Username, const 
2140: 63 68 61 72 20 2a 7a 48 61 73 68 29 7b 0a 20 20  char *zHash){.  
2150: 63 68 61 72 20 2a 7a 50 72 6f 6a 43 6f 64 65 20  char *zProjCode 
2160: 3d 20 64 62 5f 67 65 74 28 22 70 72 6f 6a 65 63  = db_get("projec
2170: 74 2d 63 6f 64 65 22 2c 4e 55 4c 4c 29 3b 0a 20  t-code",NULL);. 
2180: 20 63 68 61 72 20 2a 7a 43 6f 64 65 20 3d 20 61   char *zCode = a
2190: 62 62 72 65 76 69 61 74 65 64 5f 70 72 6f 6a 65  bbreviated_proje
21a0: 63 74 5f 63 6f 64 65 28 7a 50 72 6f 6a 43 6f 64  ct_code(zProjCod
21b0: 65 29 3b 0a 20 20 66 72 65 65 28 7a 50 72 6f 6a  e);.  free(zProj
21c0: 43 6f 64 65 29 3b 0a 20 20 61 73 73 65 72 74 28  Code);.  assert(
21d0: 28 7a 55 73 65 72 6e 61 6d 65 20 26 26 20 2a 7a  (zUsername && *z
21e0: 55 73 65 72 6e 61 6d 65 29 20 26 26 20 22 49 6e  Username) && "In
21f0: 76 61 6c 69 64 20 75 73 65 72 20 64 61 74 61 2e  valid user data.
2200: 22 29 3b 0a 20 20 72 65 74 75 72 6e 20 6d 70 72  ");.  return mpr
2210: 69 6e 74 66 28 22 25 73 2f 25 7a 2f 25 73 22 2c  intf("%s/%z/%s",
2220: 20 7a 48 61 73 68 2c 20 7a 43 6f 64 65 2c 20 7a   zHash, zCode, z
2230: 55 73 65 72 6e 61 6d 65 29 3b 0a 7d 0a 0a 2f 2a  Username);.}../*
2240: 0a 2a 2a 20 47 65 6e 65 72 61 74 65 73 20 61 20  .** Generates a 
2250: 6c 6f 67 69 6e 20 63 6f 6f 6b 69 65 20 66 6f 72  login cookie for
2260: 20 4e 4f 4e 2d 41 4e 4f 4e 59 4d 4f 55 53 20 75   NON-ANONYMOUS u
2270: 73 65 72 73 2e 20 20 4e 6f 74 65 20 74 68 61 74  sers.  Note that
2280: 20 74 68 69 73 0a 2a 2a 20 66 75 6e 63 74 69 6f   this.** functio
2290: 6e 20 22 63 6f 75 6c 64 22 20 66 69 67 75 72 65  n "could" figure
22a0: 20 6f 75 74 20 74 68 65 20 75 69 64 20 62 79 20   out the uid by 
22b0: 69 74 73 65 6c 66 20 62 75 74 20 69 74 20 63 75  itself but it cu
22c0: 72 72 65 6e 74 6c 79 0a 2a 2a 20 64 6f 65 73 6e  rrently.** doesn
22d0: 27 74 20 62 65 63 61 75 73 65 20 74 68 65 20 63  't because the c
22e0: 6f 64 65 20 77 68 69 63 68 20 63 61 6c 6c 73 20  ode which calls 
22f0: 74 68 69 73 20 61 6c 72 65 61 64 79 20 68 61 73  this already has
2300: 20 74 68 65 20 75 69 64 2e 0a 2a 2a 0a 2a 2a 20   the uid..**.** 
2310: 54 68 69 73 20 66 75 6e 63 74 69 6f 6e 20 61 6c  This function al
2320: 73 6f 20 75 70 64 61 74 65 73 20 74 68 65 20 75  so updates the u
2330: 73 65 72 2e 63 6f 6f 6b 69 65 2c 20 75 73 65 72  ser.cookie, user
2340: 2e 69 70 61 64 64 72 2c 0a 2a 2a 20 61 6e 64 20  .ipaddr,.** and 
2350: 75 73 65 72 2e 63 65 78 70 69 72 65 20 66 69 65  user.cexpire fie
2360: 6c 64 73 20 66 6f 72 20 74 68 65 20 67 69 76 65  lds for the give
2370: 6e 20 75 73 65 72 2e 0a 2a 2a 0a 2a 2a 20 49 66  n user..**.** If
2380: 20 7a 44 65 73 74 20 69 73 20 6e 6f 74 20 4e 55   zDest is not NU
2390: 4c 4c 20 74 68 65 6e 20 74 68 65 20 67 65 6e 65  LL then the gene
23a0: 72 61 74 65 64 20 63 6f 6f 6b 69 65 20 69 73 20  rated cookie is 
23b0: 63 6f 70 69 65 64 20 74 6f 0a 2a 2a 20 2a 7a 44  copied to.** *zD
23c0: 64 65 73 74 20 61 6e 64 20 6f 77 6e 65 72 73 68  dest and ownersh
23d0: 69 70 20 69 73 20 74 72 61 6e 73 66 65 72 65 64  ip is transfered
23e0: 20 74 6f 20 74 68 65 20 63 61 6c 6c 65 72 20 28   to the caller (
23f0: 77 68 6f 20 73 68 6f 75 6c 64 0a 2a 2a 20 65 76  who should.** ev
2400: 65 6e 74 75 61 6c 6c 79 20 70 61 73 73 20 69 74  entually pass it
2410: 20 74 6f 20 66 72 65 65 28 29 29 2e 0a 2a 2f 0a   to free())..*/.
2420: 76 6f 69 64 20 6c 6f 67 69 6e 5f 73 65 74 5f 75  void login_set_u
2430: 73 65 72 5f 63 6f 6f 6b 69 65 28 0a 20 20 63 6f  ser_cookie(.  co
2440: 6e 73 74 20 63 68 61 72 20 2a 7a 55 73 65 72 6e  nst char *zUsern
2450: 61 6d 65 2c 20 20 2f 2a 20 55 73 65 72 27 73 20  ame,  /* User's 
2460: 6e 61 6d 65 20 2a 2f 0a 20 20 69 6e 74 20 75 69  name */.  int ui
2470: 64 2c 20 20 20 20 20 20 20 20 20 20 20 20 20 20  d,              
2480: 20 20 2f 2a 20 55 73 65 72 27 73 20 49 44 20 2a    /* User's ID *
2490: 2f 0a 20 20 63 68 61 72 20 2a 2a 7a 44 65 73 74  /.  char **zDest
24a0: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4f              /* O
24b0: 70 74 69 6f 6e 61 6c 3a 20 73 74 6f 72 65 20 67  ptional: store g
24c0: 65 6e 65 72 61 74 65 64 20 63 6f 6f 6b 69 65 20  enerated cookie 
24d0: 76 61 6c 75 65 2e 20 2a 2f 0a 29 7b 0a 20 20 63  value. */.){.  c
24e0: 6f 6e 73 74 20 63 68 61 72 20 2a 7a 43 6f 6f 6b  onst char *zCook
24f0: 69 65 4e 61 6d 65 20 3d 20 6c 6f 67 69 6e 5f 63  ieName = login_c
2500: 6f 6f 6b 69 65 5f 6e 61 6d 65 28 29 3b 0a 20 20  ookie_name();.  
2510: 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 45 78 70  const char *zExp
2520: 69 72 65 20 3d 20 64 62 5f 67 65 74 28 22 63 6f  ire = db_get("co
2530: 6f 6b 69 65 2d 65 78 70 69 72 65 22 2c 22 38 37  okie-expire","87
2540: 36 36 22 29 3b 0a 20 20 69 6e 74 20 65 78 70 69  66");.  int expi
2550: 72 65 73 20 3d 20 61 74 6f 69 28 7a 45 78 70 69  res = atoi(zExpi
2560: 72 65 29 2a 33 36 30 30 3b 0a 20 20 63 68 61 72  re)*3600;.  char
2570: 20 2a 7a 48 61 73 68 3b 0a 20 20 63 68 61 72 20   *zHash;.  char 
2580: 2a 7a 43 6f 6f 6b 69 65 3b 0a 20 20 63 6f 6e 73  *zCookie;.  cons
2590: 74 20 63 68 61 72 20 2a 7a 49 70 41 64 64 72 20  t char *zIpAddr 
25a0: 3d 20 50 44 28 22 52 45 4d 4f 54 45 5f 41 44 44  = PD("REMOTE_ADD
25b0: 52 22 2c 22 6e 69 6c 22 29 3b 20 2f 2a 20 49 50  R","nil"); /* IP
25c0: 20 61 64 64 72 65 73 73 20 6f 66 20 75 73 65 72   address of user
25d0: 20 2a 2f 0a 20 20 63 68 61 72 20 2a 7a 52 65 6d   */.  char *zRem
25e0: 6f 74 65 41 64 64 72 20 3d 20 69 70 50 72 65 66  oteAddr = ipPref
25f0: 69 78 28 7a 49 70 41 64 64 72 29 3b 20 20 20 20  ix(zIpAddr);    
2600: 20 20 20 20 20 2f 2a 20 41 62 62 72 65 76 69 61       /* Abbrevia
2610: 74 65 64 20 49 50 20 61 64 64 72 65 73 73 20 2a  ted IP address *
2620: 2f 0a 0a 20 20 61 73 73 65 72 74 28 28 7a 55 73  /..  assert((zUs
2630: 65 72 6e 61 6d 65 20 26 26 20 2a 7a 55 73 65 72  ername && *zUser
2640: 6e 61 6d 65 29 20 26 26 20 28 75 69 64 20 3e 20  name) && (uid > 
2650: 30 29 20 26 26 20 22 49 6e 76 61 6c 69 64 20 75  0) && "Invalid u
2660: 73 65 72 20 64 61 74 61 2e 22 29 3b 0a 20 20 7a  ser data.");.  z
2670: 48 61 73 68 20 3d 20 64 62 5f 74 65 78 74 28 30  Hash = db_text(0
2680: 2c 0a 20 20 20 20 20 20 22 53 45 4c 45 43 54 20  ,.      "SELECT 
2690: 63 6f 6f 6b 69 65 20 46 52 4f 4d 20 75 73 65 72  cookie FROM user
26a0: 22 0a 20 20 20 20 20 20 22 20 57 48 45 52 45 20  ".      " WHERE 
26b0: 75 69 64 3d 25 64 22 0a 20 20 20 20 20 20 22 20  uid=%d".      " 
26c0: 20 20 41 4e 44 20 69 70 61 64 64 72 3d 25 51 22    AND ipaddr=%Q"
26d0: 0a 20 20 20 20 20 20 22 20 20 20 41 4e 44 20 63  .      "   AND c
26e0: 65 78 70 69 72 65 3e 6a 75 6c 69 61 6e 64 61 79  expire>julianday
26f0: 28 27 6e 6f 77 27 29 22 0a 20 20 20 20 20 20 22  ('now')".      "
2700: 20 20 20 41 4e 44 20 6c 65 6e 67 74 68 28 63 6f     AND length(co
2710: 6f 6b 69 65 29 3e 33 30 22 2c 0a 20 20 20 20 20  okie)>30",.     
2720: 20 75 69 64 2c 20 7a 52 65 6d 6f 74 65 41 64 64   uid, zRemoteAdd
2730: 72 29 3b 0a 20 20 69 66 28 20 7a 48 61 73 68 3d  r);.  if( zHash=
2740: 3d 30 20 29 20 7a 48 61 73 68 20 3d 20 64 62 5f  =0 ) zHash = db_
2750: 74 65 78 74 28 30 2c 20 22 53 45 4c 45 43 54 20  text(0, "SELECT 
2760: 68 65 78 28 72 61 6e 64 6f 6d 62 6c 6f 62 28 32  hex(randomblob(2
2770: 35 29 29 22 29 3b 0a 20 20 7a 43 6f 6f 6b 69 65  5))");.  zCookie
2780: 20 3d 20 6c 6f 67 69 6e 5f 67 65 6e 5f 75 73 65   = login_gen_use
2790: 72 5f 63 6f 6f 6b 69 65 5f 76 61 6c 75 65 28 7a  r_cookie_value(z
27a0: 55 73 65 72 6e 61 6d 65 2c 20 7a 48 61 73 68 29  Username, zHash)
27b0: 3b 0a 20 20 63 67 69 5f 73 65 74 5f 63 6f 6f 6b  ;.  cgi_set_cook
27c0: 69 65 28 7a 43 6f 6f 6b 69 65 4e 61 6d 65 2c 20  ie(zCookieName, 
27d0: 7a 43 6f 6f 6b 69 65 2c 20 6c 6f 67 69 6e 5f 63  zCookie, login_c
27e0: 6f 6f 6b 69 65 5f 70 61 74 68 28 29 2c 20 65 78  ookie_path(), ex
27f0: 70 69 72 65 73 29 3b 0a 20 20 72 65 63 6f 72 64  pires);.  record
2800: 5f 6c 6f 67 69 6e 5f 61 74 74 65 6d 70 74 28 7a  _login_attempt(z
2810: 55 73 65 72 6e 61 6d 65 2c 20 7a 49 70 41 64 64  Username, zIpAdd
2820: 72 2c 20 31 29 3b 0a 20 20 64 62 5f 6d 75 6c 74  r, 1);.  db_mult
2830: 69 5f 65 78 65 63 28 0a 20 20 20 20 20 20 20 20  i_exec(.        
2840: 20 20 20 20 20 20 20 20 22 55 50 44 41 54 45 20          "UPDATE 
2850: 75 73 65 72 20 53 45 54 20 63 6f 6f 6b 69 65 3d  user SET cookie=
2860: 25 51 2c 20 69 70 61 64 64 72 3d 25 51 2c 20 22  %Q, ipaddr=%Q, "
2870: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
2880: 20 22 20 20 63 65 78 70 69 72 65 3d 6a 75 6c 69   "  cexpire=juli
2890: 61 6e 64 61 79 28 27 6e 6f 77 27 29 2b 25 64 2f  anday('now')+%d/
28a0: 38 36 34 30 30 2e 30 20 57 48 45 52 45 20 75 69  86400.0 WHERE ui
28b0: 64 3d 25 64 22 2c 0a 20 20 20 20 20 20 20 20 20  d=%d",.         
28c0: 20 20 20 20 20 20 20 7a 48 61 73 68 2c 20 7a 52         zHash, zR
28d0: 65 6d 6f 74 65 41 64 64 72 2c 20 65 78 70 69 72  emoteAddr, expir
28e0: 65 73 2c 20 75 69 64 0a 20 20 20 20 20 20 20 20  es, uid.        
28f0: 20 20 20 20 20 20 20 20 29 3b 0a 20 20 66 72 65          );.  fre
2900: 65 28 7a 52 65 6d 6f 74 65 41 64 64 72 29 3b 0a  e(zRemoteAddr);.
2910: 20 20 66 72 65 65 28 7a 48 61 73 68 29 3b 0a 20    free(zHash);. 
2920: 20 69 66 28 20 7a 44 65 73 74 20 29 7b 0a 20 20   if( zDest ){.  
2930: 20 20 2a 7a 44 65 73 74 20 3d 20 7a 43 6f 6f 6b    *zDest = zCook
2940: 69 65 3b 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20  ie;.  }else{.   
2950: 20 66 72 65 65 28 7a 43 6f 6f 6b 69 65 29 3b 0a   free(zCookie);.
2960: 20 20 7d 0a 7d 0a 0a 2f 2a 20 53 65 74 73 20 61    }.}../* Sets a
2970: 20 63 6f 6f 6b 69 65 20 66 6f 72 20 61 6e 20 61   cookie for an a
2980: 6e 6f 6e 79 6d 6f 75 73 20 75 73 65 72 20 6c 6f  nonymous user lo
2990: 67 69 6e 2c 20 77 68 69 63 68 20 6c 6f 6f 6b 73  gin, which looks
29a0: 20 6c 69 6b 65 20 74 68 69 73 3a 0a 2a 2a 0a 2a   like this:.**.*
29b0: 2a 20 20 20 20 48 41 53 48 2f 54 49 4d 45 2f 61  *    HASH/TIME/a
29c0: 6e 6f 6e 79 6d 6f 75 73 0a 2a 2a 0a 2a 2a 20 57  nonymous.**.** W
29d0: 68 65 72 65 20 48 41 53 48 20 69 73 20 74 68 65  here HASH is the
29e0: 20 73 68 61 31 73 75 6d 20 6f 66 20 54 49 4d 45   sha1sum of TIME
29f0: 2f 49 50 41 44 44 52 2f 53 45 43 52 45 54 2c 20  /IPADDR/SECRET, 
2a00: 69 6e 20 77 68 69 63 68 20 49 50 41 44 44 52 0a  in which IPADDR.
2a10: 2a 2a 20 69 73 20 74 68 65 20 61 62 62 72 65 76  ** is the abbrev
2a20: 69 61 74 65 64 20 49 50 20 61 64 64 72 65 73 73  iated IP address
2a30: 20 61 6e 64 20 53 45 43 52 45 54 20 69 73 20 63   and SECRET is c
2a40: 61 70 74 63 68 61 2d 73 65 63 72 65 74 2e 0a 2a  aptcha-secret..*
2a50: 2a 0a 2a 2a 20 49 66 20 65 69 74 68 65 72 20 7a  *.** If either z
2a60: 49 70 41 64 64 72 20 6f 72 20 7a 52 65 6d 6f 74  IpAddr or zRemot
2a70: 65 41 64 64 72 20 61 72 65 20 4e 55 4c 4c 20 74  eAddr are NULL t
2a80: 68 65 6e 20 52 45 4d 4f 54 45 5f 41 44 44 52 0a  hen REMOTE_ADDR.
2a90: 2a 2a 20 69 73 20 75 73 65 64 2e 0a 2a 2a 0a 2a  ** is used..**.*
2aa0: 2a 20 49 66 20 7a 43 6f 6f 6b 69 65 44 65 73 74  * If zCookieDest
2ab0: 20 69 73 20 6e 6f 74 20 4e 55 4c 4c 20 74 68 65   is not NULL the
2ac0: 6e 20 74 68 65 20 67 65 6e 65 72 61 74 65 64 20  n the generated 
2ad0: 63 6f 6f 6b 69 65 20 69 73 20 61 73 73 69 67 6e  cookie is assign
2ae0: 65 64 20 74 6f 0a 2a 2a 20 2a 7a 43 6f 6f 6b 69  ed to.** *zCooki
2af0: 65 44 65 73 74 20 61 6e 64 20 74 68 65 20 63 61  eDest and the ca
2b00: 6c 6c 65 72 20 6d 75 73 74 20 65 76 65 6e 74 75  ller must eventu
2b10: 61 6c 6c 79 20 66 72 65 65 28 29 20 69 74 2e 0a  ally free() it..
2b20: 2a 2f 0a 76 6f 69 64 20 6c 6f 67 69 6e 5f 73 65  */.void login_se
2b30: 74 5f 61 6e 6f 6e 5f 63 6f 6f 6b 69 65 28 63 6f  t_anon_cookie(co
2b40: 6e 73 74 20 63 68 61 72 20 2a 7a 49 70 41 64 64  nst char *zIpAdd
2b50: 72 2c 20 63 68 61 72 20 2a 2a 7a 43 6f 6f 6b 69  r, char **zCooki
2b60: 65 44 65 73 74 20 29 7b 0a 20 20 63 6f 6e 73 74  eDest ){.  const
2b70: 20 63 68 61 72 20 2a 7a 4e 6f 77 3b 20 20 20 20   char *zNow;    
2b80: 20 20 20 20 20 20 20 20 2f 2a 20 43 75 72 72 65          /* Curre
2b90: 6e 74 20 74 69 6d 65 20 28 6a 75 6c 69 61 6e 20  nt time (julian 
2ba0: 64 61 79 20 6e 75 6d 62 65 72 29 20 2a 2f 0a 20  day number) */. 
2bb0: 20 63 68 61 72 20 2a 7a 43 6f 6f 6b 69 65 3b 20   char *zCookie; 
2bc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
2bd0: 20 54 68 65 20 6c 6f 67 69 6e 20 63 6f 6f 6b 69   The login cooki
2be0: 65 20 2a 2f 0a 20 20 63 6f 6e 73 74 20 63 68 61  e */.  const cha
2bf0: 72 20 2a 7a 43 6f 6f 6b 69 65 4e 61 6d 65 3b 20  r *zCookieName; 
2c00: 20 20 20 20 2f 2a 20 4e 61 6d 65 20 6f 66 20 74      /* Name of t
2c10: 68 65 20 6c 6f 67 69 6e 20 63 6f 6f 6b 69 65 20  he login cookie 
2c20: 2a 2f 0a 20 20 42 6c 6f 62 20 62 3b 20 20 20 20  */.  Blob b;    
2c30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2c40: 20 20 2f 2a 20 42 6c 6f 62 20 75 73 65 64 20 64    /* Blob used d
2c50: 75 72 69 6e 67 20 63 6f 6f 6b 69 65 20 63 6f 6e  uring cookie con
2c60: 73 74 72 75 63 74 69 6f 6e 20 2a 2f 0a 20 20 63  struction */.  c
2c70: 68 61 72 20 2a 7a 52 65 6d 6f 74 65 41 64 64 72  har *zRemoteAddr
2c80: 3b 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 41  ;           /* A
2c90: 62 62 72 65 76 69 61 74 65 64 20 49 50 20 61 64  bbreviated IP ad
2ca0: 64 72 65 73 73 20 2a 2f 0a 20 20 69 66 28 21 7a  dress */.  if(!z
2cb0: 49 70 41 64 64 72 29 7b 0a 20 20 20 20 7a 49 70  IpAddr){.    zIp
2cc0: 41 64 64 72 20 3d 20 50 44 28 22 52 45 4d 4f 54  Addr = PD("REMOT
2cd0: 45 5f 41 44 44 52 22 2c 22 6e 69 6c 22 29 3b 0a  E_ADDR","nil");.
2ce0: 20 20 7d 0a 20 20 7a 52 65 6d 6f 74 65 41 64 64    }.  zRemoteAdd
2cf0: 72 20 3d 20 69 70 50 72 65 66 69 78 28 7a 49 70  r = ipPrefix(zIp
2d00: 41 64 64 72 29 3b 0a 20 20 7a 43 6f 6f 6b 69 65  Addr);.  zCookie
2d10: 4e 61 6d 65 20 3d 20 6c 6f 67 69 6e 5f 63 6f 6f  Name = login_coo
2d20: 6b 69 65 5f 6e 61 6d 65 28 29 3b 0a 20 20 7a 4e  kie_name();.  zN
2d30: 6f 77 20 3d 20 64 62 5f 74 65 78 74 28 22 30 22  ow = db_text("0"
2d40: 2c 20 22 53 45 4c 45 43 54 20 6a 75 6c 69 61 6e  , "SELECT julian
2d50: 64 61 79 28 27 6e 6f 77 27 29 22 29 3b 0a 20 20  day('now')");.  
2d60: 61 73 73 65 72 74 28 20 7a 43 6f 6f 6b 69 65 4e  assert( zCookieN
2d70: 61 6d 65 20 26 26 20 7a 52 65 6d 6f 74 65 41 64  ame && zRemoteAd
2d80: 64 72 20 26 26 20 7a 49 70 41 64 64 72 20 26 26  dr && zIpAddr &&
2d90: 20 7a 4e 6f 77 20 29 3b 0a 20 20 62 6c 6f 62 5f   zNow );.  blob_
2da0: 69 6e 69 74 28 26 62 2c 20 7a 4e 6f 77 2c 20 2d  init(&b, zNow, -
2db0: 31 29 3b 0a 20 20 62 6c 6f 62 5f 61 70 70 65 6e  1);.  blob_appen
2dc0: 64 66 28 26 62 2c 20 22 2f 25 73 2f 25 73 22 2c  df(&b, "/%s/%s",
2dd0: 20 7a 52 65 6d 6f 74 65 41 64 64 72 2c 20 64 62   zRemoteAddr, db
2de0: 5f 67 65 74 28 22 63 61 70 74 63 68 61 2d 73 65  _get("captcha-se
2df0: 63 72 65 74 22 2c 22 22 29 29 3b 0a 20 20 73 68  cret",""));.  sh
2e00: 61 31 73 75 6d 5f 62 6c 6f 62 28 26 62 2c 20 26  a1sum_blob(&b, &
2e10: 62 29 3b 0a 20 20 7a 43 6f 6f 6b 69 65 20 3d 20  b);.  zCookie = 
2e20: 6d 70 72 69 6e 74 66 28 22 25 73 2f 25 73 2f 61  mprintf("%s/%s/a
2e30: 6e 6f 6e 79 6d 6f 75 73 22 2c 20 62 6c 6f 62 5f  nonymous", blob_
2e40: 62 75 66 66 65 72 28 26 62 29 2c 20 7a 4e 6f 77  buffer(&b), zNow
2e50: 29 3b 0a 20 20 62 6c 6f 62 5f 72 65 73 65 74 28  );.  blob_reset(
2e60: 26 62 29 3b 0a 20 20 63 67 69 5f 73 65 74 5f 63  &b);.  cgi_set_c
2e70: 6f 6f 6b 69 65 28 7a 43 6f 6f 6b 69 65 4e 61 6d  ookie(zCookieNam
2e80: 65 2c 20 7a 43 6f 6f 6b 69 65 2c 20 6c 6f 67 69  e, zCookie, logi
2e90: 6e 5f 63 6f 6f 6b 69 65 5f 70 61 74 68 28 29 2c  n_cookie_path(),
2ea0: 20 36 2a 33 36 30 30 29 3b 0a 20 20 69 66 28 20   6*3600);.  if( 
2eb0: 7a 43 6f 6f 6b 69 65 44 65 73 74 20 29 7b 0a 20  zCookieDest ){. 
2ec0: 20 20 20 2a 7a 43 6f 6f 6b 69 65 44 65 73 74 20     *zCookieDest 
2ed0: 3d 20 7a 43 6f 6f 6b 69 65 3b 0a 20 20 7d 65 6c  = zCookie;.  }el
2ee0: 73 65 7b 0a 20 20 20 20 66 72 65 65 28 7a 43 6f  se{.    free(zCo
2ef0: 6f 6b 69 65 29 3b 0a 20 20 7d 0a 0a 7d 0a 0a 2f  okie);.  }..}../
2f00: 2a 0a 2a 2a 20 22 55 6e 73 65 74 73 22 20 74 68  *.** "Unsets" th
2f10: 65 20 6c 6f 67 69 6e 20 63 6f 6f 6b 69 65 20 28  e login cookie (
2f20: 69 6e 73 6f 66 61 72 20 61 73 20 63 6f 6f 6b 69  insofar as cooki
2f30: 65 73 20 63 61 6e 20 62 65 20 75 6e 73 65 74 29  es can be unset)
2f40: 20 61 6e 64 0a 2a 2a 20 63 6c 65 61 72 73 20 74   and.** clears t
2f50: 68 65 20 63 75 72 72 65 6e 74 20 75 73 65 72 27  he current user'
2f60: 73 20 28 67 2e 75 73 65 72 55 69 64 29 20 6c 6f  s (g.userUid) lo
2f70: 67 69 6e 20 69 6e 66 6f 72 6d 61 74 69 6f 6e 20  gin information 
2f80: 66 72 6f 6d 20 74 68 65 0a 2a 2a 20 75 73 65 72  from the.** user
2f90: 20 74 61 62 6c 65 2e 20 53 65 74 73 3a 20 75 73   table. Sets: us
2fa0: 65 72 2e 63 6f 6f 6b 69 65 2c 20 75 73 65 72 2e  er.cookie, user.
2fb0: 69 70 61 64 64 72 2c 20 75 73 65 72 2e 63 65 78  ipaddr, user.cex
2fc0: 70 69 72 65 2e 0a 2a 2a 0a 2a 2a 20 57 65 20 63  pire..**.** We c
2fd0: 6f 75 6c 64 2f 73 68 6f 75 6c 64 20 61 72 67 75  ould/should argu
2fe0: 61 62 6c 79 20 63 6c 65 61 72 20 6f 75 74 20 67  ably clear out g
2ff0: 2e 75 73 65 72 55 69 64 20 61 6e 64 20 67 2e 70  .userUid and g.p
3000: 65 72 6d 20 68 65 72 65 2c 20 62 75 74 0a 2a 2a  erm here, but.**
3010: 20 77 65 20 64 6f 6e 27 74 20 63 75 72 72 65 6e   we don't curren
3020: 74 6c 79 20 64 6f 20 6e 6f 74 2e 0a 2a 2a 0a 2a  tly do not..**.*
3030: 2a 20 54 68 69 73 20 69 73 20 61 20 6e 6f 2d 6f  * This is a no-o
3040: 70 20 69 66 20 67 2e 75 73 65 72 55 69 64 20 69  p if g.userUid i
3050: 73 20 30 2e 0a 2a 2f 0a 76 6f 69 64 20 6c 6f 67  s 0..*/.void log
3060: 69 6e 5f 63 6c 65 61 72 5f 6c 6f 67 69 6e 5f 64  in_clear_login_d
3070: 61 74 61 28 29 7b 0a 20 20 69 66 28 21 67 2e 75  ata(){.  if(!g.u
3080: 73 65 72 55 69 64 29 7b 0a 20 20 20 20 72 65 74  serUid){.    ret
3090: 75 72 6e 3b 0a 20 20 7d 65 6c 73 65 7b 0a 20 20  urn;.  }else{.  
30a0: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 63 6f    const char *co
30b0: 6f 6b 69 65 20 3d 20 6c 6f 67 69 6e 5f 63 6f 6f  okie = login_coo
30c0: 6b 69 65 5f 6e 61 6d 65 28 29 3b 0a 20 20 20 20  kie_name();.    
30d0: 2f 2a 20 54 6f 20 6c 6f 67 6f 75 74 2c 20 63 68  /* To logout, ch
30e0: 61 6e 67 65 20 74 68 65 20 63 6f 6f 6b 69 65 20  ange the cookie 
30f0: 76 61 6c 75 65 20 74 6f 20 61 6e 20 65 6d 70 74  value to an empt
3100: 79 20 73 74 72 69 6e 67 20 2a 2f 0a 20 20 20 20  y string */.    
3110: 63 67 69 5f 73 65 74 5f 63 6f 6f 6b 69 65 28 63  cgi_set_cookie(c
3120: 6f 6f 6b 69 65 2c 20 22 22 2c 0a 20 20 20 20 20  ookie, "",.     
3130: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 6c 6f                lo
3140: 67 69 6e 5f 63 6f 6f 6b 69 65 5f 70 61 74 68 28  gin_cookie_path(
3150: 29 2c 20 2d 38 36 34 30 30 29 3b 0a 20 20 20 20  ), -86400);.    
3160: 64 62 5f 6d 75 6c 74 69 5f 65 78 65 63 28 22 55  db_multi_exec("U
3170: 50 44 41 54 45 20 75 73 65 72 20 53 45 54 20 63  PDATE user SET c
3180: 6f 6f 6b 69 65 3d 4e 55 4c 4c 2c 20 69 70 61 64  ookie=NULL, ipad
3190: 64 72 3d 4e 55 4c 4c 2c 20 22 0a 20 20 20 20 20  dr=NULL, ".     
31a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 22 20 20               "  
31b0: 63 65 78 70 69 72 65 3d 30 20 57 48 45 52 45 20  cexpire=0 WHERE 
31c0: 75 69 64 3d 25 64 22 0a 20 20 20 20 20 20 20 20  uid=%d".        
31d0: 20 20 20 20 20 20 20 20 20 20 22 20 20 41 4e 44            "  AND
31e0: 20 6c 6f 67 69 6e 20 4e 4f 54 20 49 4e 20 28 27   login NOT IN ('
31f0: 61 6e 6f 6e 79 6d 6f 75 73 27 2c 27 6e 6f 62 6f  anonymous','nobo
3200: 64 79 27 2c 22 0a 20 20 20 20 20 20 20 20 20 20  dy',".          
3210: 20 20 20 20 20 20 20 20 22 20 20 27 64 65 76 65          "  'deve
3220: 6c 6f 70 65 72 27 2c 27 72 65 61 64 65 72 27 29  loper','reader')
3230: 22 2c 20 67 2e 75 73 65 72 55 69 64 29 3b 0a 20  ", g.userUid);. 
3240: 20 20 20 63 67 69 5f 72 65 70 6c 61 63 65 5f 70     cgi_replace_p
3250: 61 72 61 6d 65 74 65 72 28 63 6f 6f 6b 69 65 2c  arameter(cookie,
3260: 20 4e 55 4c 4c 29 3b 0a 20 20 20 20 63 67 69 5f   NULL);.    cgi_
3270: 72 65 70 6c 61 63 65 5f 70 61 72 61 6d 65 74 65  replace_paramete
3280: 72 28 22 61 6e 6f 6e 22 2c 20 4e 55 4c 4c 29 3b  r("anon", NULL);
3290: 0a 20 20 7d 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 52 65  .  }.}../*.** Re
32a0: 74 75 72 6e 20 74 72 75 65 20 69 66 20 74 68 65  turn true if the
32b0: 20 70 72 65 66 69 78 20 6f 66 20 7a 53 74 72 20   prefix of zStr 
32c0: 6d 61 74 63 68 65 73 20 7a 50 61 74 74 65 72 6e  matches zPattern
32d0: 2e 20 20 52 65 74 75 72 6e 20 66 61 6c 73 65 20  .  Return false 
32e0: 69 66 0a 2a 2a 20 74 68 65 79 20 61 72 65 20 64  if.** they are d
32f0: 69 66 66 65 72 65 6e 74 2e 0a 2a 2a 0a 2a 2a 20  ifferent..**.** 
3300: 41 20 6c 6f 77 65 72 63 61 73 65 20 63 68 61 72  A lowercase char
3310: 61 63 74 65 72 20 69 6e 20 7a 50 61 74 74 65 72  acter in zPatter
3320: 6e 20 77 69 6c 6c 20 6d 61 74 63 68 20 65 69 74  n will match eit
3330: 68 65 72 20 75 70 70 65 72 20 6f 72 20 6c 6f 77  her upper or low
3340: 65 72 0a 2a 2a 20 63 61 73 65 20 69 6e 20 7a 53  er.** case in zS
3350: 74 72 2e 20 20 42 75 74 20 61 6e 20 75 70 70 65  tr.  But an uppe
3360: 72 63 61 73 65 20 69 6e 20 7a 50 61 74 74 65 72  rcase in zPatter
3370: 6e 20 77 69 6c 6c 20 6f 6e 6c 79 20 6d 61 74 63  n will only matc
3380: 68 20 61 6e 0a 2a 2a 20 75 70 70 65 72 63 61 73  h an.** uppercas
3390: 65 20 69 6e 20 7a 53 74 72 2e 0a 2a 2f 0a 73 74  e in zStr..*/.st
33a0: 61 74 69 63 20 69 6e 74 20 70 72 65 66 69 78 5f  atic int prefix_
33b0: 6d 61 74 63 68 28 63 6f 6e 73 74 20 63 68 61 72  match(const char
33c0: 20 2a 7a 50 61 74 74 65 72 6e 2c 20 63 6f 6e 73   *zPattern, cons
33d0: 74 20 63 68 61 72 20 2a 7a 53 74 72 29 7b 0a 20  t char *zStr){. 
33e0: 20 69 6e 74 20 69 3b 0a 20 20 63 68 61 72 20 63   int i;.  char c
33f0: 3b 0a 20 20 66 6f 72 28 69 3d 30 3b 20 28 63 20  ;.  for(i=0; (c 
3400: 3d 20 7a 50 61 74 74 65 72 6e 5b 69 5d 29 21 3d  = zPattern[i])!=
3410: 30 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 69 66 28  0; i++){.    if(
3420: 20 7a 53 74 72 5b 69 5d 21 3d 63 20 26 26 20 66   zStr[i]!=c && f
3430: 6f 73 73 69 6c 5f 74 6f 6c 6f 77 65 72 28 7a 53  ossil_tolower(zS
3440: 74 72 5b 69 5d 29 21 3d 63 20 29 20 72 65 74 75  tr[i])!=c ) retu
3450: 72 6e 20 30 3b 0a 20 20 7d 0a 20 20 72 65 74 75  rn 0;.  }.  retu
3460: 72 6e 20 31 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 4c  rn 1;.}../*.** L
3470: 6f 6f 6b 20 61 74 20 74 68 65 20 48 54 54 50 5f  ook at the HTTP_
3480: 55 53 45 52 5f 41 47 45 4e 54 20 70 61 72 61 6d  USER_AGENT param
3490: 65 74 65 72 20 61 6e 64 20 74 72 79 20 74 6f 20  eter and try to 
34a0: 64 65 74 65 72 6d 69 6e 65 20 69 66 20 74 68 65  determine if the
34b0: 20 75 73 65 72 20 61 67 65 6e 74 0a 2a 2a 20 69   user agent.** i
34c0: 73 20 61 20 6d 61 6e 75 61 6c 6c 79 20 6f 70 65  s a manually ope
34d0: 72 61 74 65 64 20 62 72 6f 77 73 65 72 20 6f 72  rated browser or
34e0: 20 61 20 62 6f 74 2e 20 20 57 68 65 6e 20 69 6e   a bot.  When in
34f0: 20 64 6f 75 62 74 2c 20 61 73 73 75 6d 65 20 61   doubt, assume a
3500: 20 62 6f 74 2e 0a 2a 2a 20 52 65 74 75 72 6e 20   bot..** Return 
3510: 74 72 75 65 20 69 66 20 77 65 20 62 65 6c 69 65  true if we belie
3520: 76 65 20 74 68 65 20 61 67 65 6e 74 20 69 73 20  ve the agent is 
3530: 61 20 72 65 61 6c 20 70 65 72 73 6f 6e 2e 0a 2a  a real person..*
3540: 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 69 73 48  /.static int isH
3550: 75 6d 61 6e 28 63 6f 6e 73 74 20 63 68 61 72 20  uman(const char 
3560: 2a 7a 41 67 65 6e 74 29 7b 0a 20 20 69 6e 74 20  *zAgent){.  int 
3570: 69 3b 0a 20 20 69 66 28 20 7a 41 67 65 6e 74 3d  i;.  if( zAgent=
3580: 3d 30 20 29 20 72 65 74 75 72 6e 20 30 3b 20 20  =0 ) return 0;  
3590: 2f 2a 20 49 66 20 6e 6f 20 55 73 65 72 41 67 65  /* If no UserAge
35a0: 6e 74 2c 20 74 68 65 6e 20 70 72 6f 62 61 62 6c  nt, then probabl
35b0: 79 20 61 20 62 6f 74 20 2a 2f 0a 20 20 66 6f 72  y a bot */.  for
35c0: 28 69 3d 30 3b 20 7a 41 67 65 6e 74 5b 69 5d 3b  (i=0; zAgent[i];
35d0: 20 69 2b 2b 29 7b 0a 20 20 20 20 69 66 28 20 70   i++){.    if( p
35e0: 72 65 66 69 78 5f 6d 61 74 63 68 28 22 62 6f 74  refix_match("bot
35f0: 22 2c 20 7a 41 67 65 6e 74 2b 69 29 20 29 20 72  ", zAgent+i) ) r
3600: 65 74 75 72 6e 20 30 3b 0a 20 20 20 20 69 66 28  eturn 0;.    if(
3610: 20 70 72 65 66 69 78 5f 6d 61 74 63 68 28 22 73   prefix_match("s
3620: 70 69 64 65 72 22 2c 20 7a 41 67 65 6e 74 2b 69  pider", zAgent+i
3630: 29 20 29 20 72 65 74 75 72 6e 20 30 3b 0a 20 20  ) ) return 0;.  
3640: 20 20 69 66 28 20 70 72 65 66 69 78 5f 6d 61 74    if( prefix_mat
3650: 63 68 28 22 63 72 61 77 6c 22 2c 20 7a 41 67 65  ch("crawl", zAge
3660: 6e 74 2b 69 29 20 29 20 72 65 74 75 72 6e 20 30  nt+i) ) return 0
3670: 3b 0a 20 20 20 20 2f 2a 20 49 66 20 61 20 55 52  ;.    /* If a UR
3680: 49 20 61 70 70 65 61 72 73 20 69 6e 20 74 68 65  I appears in the
3690: 20 55 73 65 72 2d 41 67 65 6e 74 2c 20 69 74 20   User-Agent, it 
36a0: 69 73 20 70 72 6f 62 61 62 6c 79 20 61 20 62 6f  is probably a bo
36b0: 74 20 2a 2f 0a 20 20 20 20 69 66 28 20 73 74 72  t */.    if( str
36c0: 6e 63 6d 70 28 22 68 74 74 70 22 2c 20 7a 41 67  ncmp("http", zAg
36d0: 65 6e 74 2b 69 2c 34 29 3d 3d 30 20 29 20 72 65  ent+i,4)==0 ) re
36e0: 74 75 72 6e 20 30 3b 0a 20 20 7d 0a 20 20 69 66  turn 0;.  }.  if
36f0: 28 20 73 74 72 6e 63 6d 70 28 7a 41 67 65 6e 74  ( strncmp(zAgent
3700: 2c 20 22 4d 6f 7a 69 6c 6c 61 2f 22 2c 20 38 29  , "Mozilla/", 8)
3710: 3d 3d 30 20 29 7b 0a 20 20 20 20 69 66 28 20 61  ==0 ){.    if( a
3720: 74 6f 69 28 26 7a 41 67 65 6e 74 5b 38 5d 29 3c  toi(&zAgent[8])<
3730: 34 20 29 20 72 65 74 75 72 6e 20 30 3b 20 20 2f  4 ) return 0;  /
3740: 2a 20 4d 61 6e 79 20 62 6f 74 73 20 61 64 76 65  * Many bots adve
3750: 72 74 69 73 65 20 61 73 20 4d 6f 7a 69 6c 6c 61  rtise as Mozilla
3760: 2f 33 20 2a 2f 0a 0a 20 20 20 20 2f 2a 20 32 30  /3 */..    /* 20
3770: 31 36 2d 30 35 2d 33 30 3a 20 20 41 20 70 65 72  16-05-30:  A per
3780: 6e 69 63 69 6f 75 73 20 73 70 69 64 65 72 20 74  nicious spider t
3790: 68 61 74 20 6c 69 6b 65 73 20 74 6f 20 77 61 6c  hat likes to wal
37a0: 6b 20 46 6f 73 73 69 6c 20 74 69 6d 65 6c 69 6e  k Fossil timelin
37b0: 65 73 20 68 61 73 0a 20 20 20 20 2a 2a 20 62 65  es has.    ** be
37c0: 65 6e 20 64 65 74 65 63 74 65 64 20 6f 6e 20 74  en detected on t
37d0: 68 65 20 53 51 4c 69 74 65 20 77 65 62 73 69 74  he SQLite websit
37e0: 65 2e 20 20 54 68 65 20 73 70 69 64 65 72 20 63  e.  The spider c
37f0: 68 61 6e 67 65 73 20 69 74 73 20 75 73 65 72 2d  hanges its user-
3800: 61 67 65 6e 74 0a 20 20 20 20 2a 2a 20 73 74 72  agent.    ** str
3810: 69 6e 67 20 66 72 65 71 75 65 6e 74 6c 79 2c 20  ing frequently, 
3820: 62 75 74 20 69 74 20 61 6c 77 61 79 73 20 73 65  but it always se
3830: 65 6d 73 20 74 6f 20 69 6e 63 6c 75 64 65 20 74  ems to include t
3840: 68 65 20 66 6f 6c 6c 6f 77 69 6e 67 20 74 65 78  he following tex
3850: 74 3a 0a 20 20 20 20 2a 2f 0a 20 20 20 20 69 66  t:.    */.    if
3860: 28 20 73 71 6c 69 74 65 33 5f 73 74 72 67 6c 6f  ( sqlite3_strglo
3870: 62 28 22 2a 53 61 66 61 72 69 2f 35 33 37 2e 33  b("*Safari/537.3
3880: 36 4d 6f 7a 69 6c 6c 61 2f 35 2e 30 2a 22 2c 20  6Mozilla/5.0*", 
3890: 7a 41 67 65 6e 74 29 3d 3d 30 20 29 20 72 65 74  zAgent)==0 ) ret
38a0: 75 72 6e 20 30 3b 0a 0a 20 20 20 20 69 66 28 20  urn 0;..    if( 
38b0: 73 71 6c 69 74 65 33 5f 73 74 72 67 6c 6f 62 28  sqlite3_strglob(
38c0: 22 2a 46 69 72 65 66 6f 78 2f 5b 31 2d 39 5d 2a  "*Firefox/[1-9]*
38d0: 22 2c 20 7a 41 67 65 6e 74 29 3d 3d 30 20 29 20  ", zAgent)==0 ) 
38e0: 72 65 74 75 72 6e 20 31 3b 0a 20 20 20 20 69 66  return 1;.    if
38f0: 28 20 73 71 6c 69 74 65 33 5f 73 74 72 67 6c 6f  ( sqlite3_strglo
3900: 62 28 22 2a 43 68 72 6f 6d 65 2f 5b 31 2d 39 5d  b("*Chrome/[1-9]
3910: 2a 22 2c 20 7a 41 67 65 6e 74 29 3d 3d 30 20 29  *", zAgent)==0 )
3920: 20 72 65 74 75 72 6e 20 31 3b 0a 20 20 20 20 69   return 1;.    i
3930: 66 28 20 73 71 6c 69 74 65 33 5f 73 74 72 67 6c  f( sqlite3_strgl
3940: 6f 62 28 22 2a 28 63 6f 6d 70 61 74 69 62 6c 65  ob("*(compatible
3950: 3b 3f 4d 53 49 45 3f 5b 31 37 38 39 5d 2a 22 2c  ;?MSIE?[1789]*",
3960: 20 7a 41 67 65 6e 74 29 3d 3d 30 20 29 20 72 65   zAgent)==0 ) re
3970: 74 75 72 6e 20 31 3b 0a 20 20 20 20 69 66 28 20  turn 1;.    if( 
3980: 73 71 6c 69 74 65 33 5f 73 74 72 67 6c 6f 62 28  sqlite3_strglob(
3990: 22 2a 54 72 69 64 65 6e 74 2f 5b 31 2d 39 5d 2a  "*Trident/[1-9]*
39a0: 3b 3f 72 76 3a 5b 31 2d 39 5d 2a 22 2c 20 7a 41  ;?rv:[1-9]*", zA
39b0: 67 65 6e 74 29 3d 3d 30 20 29 7b 0a 20 20 20 20  gent)==0 ){.    
39c0: 20 20 72 65 74 75 72 6e 20 31 3b 20 2f 2a 20 49    return 1; /* I
39d0: 45 31 31 2b 20 2a 2f 0a 20 20 20 20 7d 0a 20 20  E11+ */.    }.  
39e0: 20 20 69 66 28 20 73 71 6c 69 74 65 33 5f 73 74    if( sqlite3_st
39f0: 72 67 6c 6f 62 28 22 2a 41 70 70 6c 65 57 65 62  rglob("*AppleWeb
3a00: 4b 69 74 2f 5b 31 2d 39 5d 2a 28 4b 48 54 4d 4c  Kit/[1-9]*(KHTML
3a10: 2a 22 2c 20 7a 41 67 65 6e 74 29 3d 3d 30 20 29  *", zAgent)==0 )
3a20: 20 72 65 74 75 72 6e 20 31 3b 0a 20 20 20 20 72   return 1;.    r
3a30: 65 74 75 72 6e 20 30 3b 0a 20 20 7d 0a 20 20 69  eturn 0;.  }.  i
3a40: 66 28 20 73 74 72 6e 63 6d 70 28 7a 41 67 65 6e  f( strncmp(zAgen
3a50: 74 2c 20 22 4f 70 65 72 61 2f 22 2c 20 36 29 3d  t, "Opera/", 6)=
3a60: 3d 30 20 29 20 72 65 74 75 72 6e 20 31 3b 0a 20  =0 ) return 1;. 
3a70: 20 69 66 28 20 73 74 72 6e 63 6d 70 28 7a 41 67   if( strncmp(zAg
3a80: 65 6e 74 2c 20 22 53 61 66 61 72 69 2f 22 2c 20  ent, "Safari/", 
3a90: 37 29 3d 3d 30 20 29 20 72 65 74 75 72 6e 20 31  7)==0 ) return 1
3aa0: 3b 0a 20 20 69 66 28 20 73 74 72 6e 63 6d 70 28  ;.  if( strncmp(
3ab0: 7a 41 67 65 6e 74 2c 20 22 4c 79 6e 78 2f 22 2c  zAgent, "Lynx/",
3ac0: 20 35 29 3d 3d 30 20 29 20 72 65 74 75 72 6e 20   5)==0 ) return 
3ad0: 31 3b 0a 20 20 69 66 28 20 73 74 72 6e 63 6d 70  1;.  if( strncmp
3ae0: 28 7a 41 67 65 6e 74 2c 20 22 4e 65 74 53 75 72  (zAgent, "NetSur
3af0: 66 2f 22 2c 20 38 29 3d 3d 30 20 29 20 72 65 74  f/", 8)==0 ) ret
3b00: 75 72 6e 20 31 3b 0a 20 20 72 65 74 75 72 6e 20  urn 1;.  return 
3b10: 30 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 43 4f 4d 4d  0;.}../*.** COMM
3b20: 41 4e 44 3a 20 74 65 73 74 2d 69 73 68 75 6d 61  AND: test-ishuma
3b30: 6e 0a 2a 2a 0a 2a 2a 20 52 65 61 64 20 6c 69 6e  n.**.** Read lin
3b40: 65 73 20 6f 66 20 74 65 78 74 20 66 72 6f 6d 20  es of text from 
3b50: 73 74 61 6e 64 61 72 64 20 69 6e 70 75 74 2e 20  standard input. 
3b60: 20 49 6e 74 65 72 70 72 65 74 20 65 61 63 68 20   Interpret each 
3b70: 6c 69 6e 65 20 6f 66 20 74 65 78 74 0a 2a 2a 20  line of text.** 
3b80: 61 73 20 61 20 55 73 65 72 2d 41 67 65 6e 74 20  as a User-Agent 
3b90: 73 74 72 69 6e 67 20 66 72 6f 6d 20 61 6e 20 48  string from an H
3ba0: 54 54 50 20 68 65 61 64 65 72 2e 20 20 4c 61 62  TTP header.  Lab
3bb0: 65 6c 20 65 61 63 68 20 6c 69 6e 65 20 61 73 20  el each line as 
3bc0: 48 55 4d 41 4e 0a 2a 2a 20 6f 72 20 52 4f 42 4f  HUMAN.** or ROBO
3bd0: 54 2e 0a 2a 2f 0a 76 6f 69 64 20 74 65 73 74 5f  T..*/.void test_
3be0: 69 73 68 75 6d 61 6e 28 76 6f 69 64 29 7b 0a 20  ishuman(void){. 
3bf0: 20 63 68 61 72 20 7a 4c 69 6e 65 5b 33 30 30 30   char zLine[3000
3c00: 5d 3b 0a 20 20 77 68 69 6c 65 28 20 66 67 65 74  ];.  while( fget
3c10: 73 28 7a 4c 69 6e 65 2c 20 73 69 7a 65 6f 66 28  s(zLine, sizeof(
3c20: 7a 4c 69 6e 65 29 2c 20 73 74 64 69 6e 29 20 29  zLine), stdin) )
3c30: 7b 0a 20 20 20 20 66 6f 73 73 69 6c 5f 70 72 69  {.    fossil_pri
3c40: 6e 74 28 22 25 73 20 25 73 22 2c 20 69 73 48 75  nt("%s %s", isHu
3c50: 6d 61 6e 28 7a 4c 69 6e 65 29 20 3f 20 22 48 55  man(zLine) ? "HU
3c60: 4d 41 4e 22 20 3a 20 22 52 4f 42 4f 54 22 2c 20  MAN" : "ROBOT", 
3c70: 7a 4c 69 6e 65 29 3b 0a 20 20 7d 0a 7d 0a 0a 2f  zLine);.  }.}../
3c80: 2a 0a 2a 2a 20 53 51 4c 20 66 75 6e 63 74 69 6f  *.** SQL functio
3c90: 6e 20 66 6f 72 20 63 6f 6e 73 74 61 6e 74 20 74  n for constant t
3ca0: 69 6d 65 20 63 6f 6d 70 61 72 69 73 6f 6e 20 6f  ime comparison o
3cb0: 66 20 74 77 6f 20 76 61 6c 75 65 73 2e 0a 2a 2a  f two values..**
3cc0: 20 53 65 74 73 20 72 65 73 75 6c 74 20 74 6f 20   Sets result to 
3cd0: 30 20 69 66 20 74 77 6f 20 76 61 6c 75 65 73 20  0 if two values 
3ce0: 61 72 65 20 65 71 75 61 6c 2e 0a 2a 2f 0a 73 74  are equal..*/.st
3cf0: 61 74 69 63 20 76 6f 69 64 20 63 6f 6e 73 74 61  atic void consta
3d00: 6e 74 5f 74 69 6d 65 5f 63 6d 70 5f 66 75 6e 63  nt_time_cmp_func
3d10: 74 69 6f 6e 28 0a 20 73 71 6c 69 74 65 33 5f 63  tion(. sqlite3_c
3d20: 6f 6e 74 65 78 74 20 2a 63 6f 6e 74 65 78 74 2c  ontext *context,
3d30: 0a 20 69 6e 74 20 61 72 67 63 2c 0a 20 73 71 6c  . int argc,. sql
3d40: 69 74 65 33 5f 76 61 6c 75 65 20 2a 2a 61 72 67  ite3_value **arg
3d50: 76 0a 29 7b 0a 20 20 63 6f 6e 73 74 20 75 6e 73  v.){.  const uns
3d60: 69 67 6e 65 64 20 63 68 61 72 20 2a 62 75 66 31  igned char *buf1
3d70: 2c 20 2a 62 75 66 32 3b 0a 20 20 69 6e 74 20 6c  , *buf2;.  int l
3d80: 65 6e 2c 20 69 3b 0a 20 20 75 6e 73 69 67 6e 65  en, i;.  unsigne
3d90: 64 20 63 68 61 72 20 72 63 20 3d 20 30 3b 0a 0a  d char rc = 0;..
3da0: 20 20 61 73 73 65 72 74 28 20 61 72 67 63 3d 3d    assert( argc==
3db0: 32 20 29 3b 0a 20 20 6c 65 6e 20 3d 20 73 71 6c  2 );.  len = sql
3dc0: 69 74 65 33 5f 76 61 6c 75 65 5f 62 79 74 65 73  ite3_value_bytes
3dd0: 28 61 72 67 76 5b 30 5d 29 3b 0a 20 20 69 66 28  (argv[0]);.  if(
3de0: 20 6c 65 6e 3d 3d 30 20 7c 7c 20 6c 65 6e 21 3d   len==0 || len!=
3df0: 73 71 6c 69 74 65 33 5f 76 61 6c 75 65 5f 62 79  sqlite3_value_by
3e00: 74 65 73 28 61 72 67 76 5b 31 5d 29 20 29 7b 0a  tes(argv[1]) ){.
3e10: 20 20 20 20 72 63 20 3d 20 31 3b 0a 20 20 7d 65      rc = 1;.  }e
3e20: 6c 73 65 7b 0a 20 20 20 20 62 75 66 31 20 3d 20  lse{.    buf1 = 
3e30: 73 71 6c 69 74 65 33 5f 76 61 6c 75 65 5f 74 65  sqlite3_value_te
3e40: 78 74 28 61 72 67 76 5b 30 5d 29 3b 0a 20 20 20  xt(argv[0]);.   
3e50: 20 62 75 66 32 20 3d 20 73 71 6c 69 74 65 33 5f   buf2 = sqlite3_
3e60: 76 61 6c 75 65 5f 74 65 78 74 28 61 72 67 76 5b  value_text(argv[
3e70: 31 5d 29 3b 0a 20 20 20 20 66 6f 72 28 20 69 3d  1]);.    for( i=
3e80: 30 3b 20 69 3c 6c 65 6e 3b 20 69 2b 2b 20 29 7b  0; i<len; i++ ){
3e90: 0a 20 20 20 20 20 20 72 63 20 3d 20 72 63 20 7c  .      rc = rc |
3ea0: 20 28 62 75 66 31 5b 69 5d 20 5e 20 62 75 66 32   (buf1[i] ^ buf2
3eb0: 5b 69 5d 29 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a  [i]);.    }.  }.
3ec0: 20 20 73 71 6c 69 74 65 33 5f 72 65 73 75 6c 74    sqlite3_result
3ed0: 5f 69 6e 74 28 63 6f 6e 74 65 78 74 2c 20 72 63  _int(context, rc
3ee0: 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 52 65 74 75  );.}../*.** Retu
3ef0: 72 6e 20 74 72 75 65 20 69 66 20 74 68 65 20 63  rn true if the c
3f00: 75 72 72 65 6e 74 20 70 61 67 65 20 77 61 73 20  urrent page was 
3f10: 72 65 61 63 68 65 64 20 62 79 20 61 20 72 65 64  reached by a red
3f20: 69 72 65 63 74 20 66 72 6f 6d 20 74 68 65 20 2f  irect from the /
3f30: 6c 6f 67 69 6e 0a 2a 2a 20 70 61 67 65 2e 0a 2a  login.** page..*
3f40: 2f 0a 69 6e 74 20 72 65 66 65 72 72 65 64 5f 66  /.int referred_f
3f50: 72 6f 6d 5f 6c 6f 67 69 6e 28 76 6f 69 64 29 7b  rom_login(void){
3f60: 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a  .  const char *z
3f70: 52 65 66 65 72 65 72 20 3d 20 50 28 22 48 54 54  Referer = P("HTT
3f80: 50 5f 52 45 46 45 52 45 52 22 29 3b 0a 20 20 63  P_REFERER");.  c
3f90: 68 61 72 20 2a 7a 50 61 74 74 65 72 6e 3b 0a 20  har *zPattern;. 
3fa0: 20 69 6e 74 20 72 63 3b 0a 20 20 69 66 28 20 7a   int rc;.  if( z
3fb0: 52 65 66 65 72 65 72 3d 3d 30 20 29 20 72 65 74  Referer==0 ) ret
3fc0: 75 72 6e 20 30 3b 0a 20 20 7a 50 61 74 74 65 72  urn 0;.  zPatter
3fd0: 6e 20 3d 20 6d 70 72 69 6e 74 66 28 22 25 73 2f  n = mprintf("%s/
3fe0: 6c 6f 67 69 6e 2a 22 2c 20 67 2e 7a 42 61 73 65  login*", g.zBase
3ff0: 55 52 4c 29 3b 0a 20 20 72 63 20 3d 20 73 71 6c  URL);.  rc = sql
4000: 69 74 65 33 5f 73 74 72 67 6c 6f 62 28 7a 50 61  ite3_strglob(zPa
4010: 74 74 65 72 6e 2c 20 7a 52 65 66 65 72 65 72 29  ttern, zReferer)
4020: 3d 3d 30 3b 0a 20 20 66 6f 73 73 69 6c 5f 66 72  ==0;.  fossil_fr
4030: 65 65 28 7a 50 61 74 74 65 72 6e 29 3b 0a 20 20  ee(zPattern);.  
4040: 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a  return rc;.}../*
4050: 0a 2a 2a 20 52 65 74 75 72 6e 20 54 52 55 45 20  .** Return TRUE 
4060: 69 66 20 73 65 6c 66 2d 72 65 67 69 73 74 72 61  if self-registra
4070: 74 69 6f 6e 20 69 73 20 61 76 61 69 6c 61 62 6c  tion is availabl
4080: 65 2e 20 20 49 66 20 74 68 65 20 7a 4e 65 65 64  e.  If the zNeed
4090: 65 64 0a 2a 2a 20 61 72 67 75 6d 65 6e 74 20 69  ed.** argument i
40a0: 73 20 6e 6f 74 20 4e 55 4c 4c 2c 20 74 68 65 6e  s not NULL, then
40b0: 20 6f 6e 6c 79 20 72 65 74 75 72 6e 20 74 72 75   only return tru
40c0: 65 20 69 66 20 73 65 6c 66 2d 72 65 67 69 73 74  e if self-regist
40d0: 72 61 74 69 6f 6e 20 69 73 0a 2a 2a 20 61 76 61  ration is.** ava
40e0: 69 6c 61 62 6c 65 20 61 6e 64 20 61 6e 79 20 6f  ilable and any o
40f0: 66 20 74 68 65 20 63 61 70 61 62 69 6c 69 74 69  f the capabiliti
4100: 65 73 20 6e 61 6d 65 64 20 69 6e 20 7a 4e 65 65  es named in zNee
4110: 64 65 64 20 61 72 65 20 61 76 61 69 6c 61 62 6c  ded are availabl
4120: 65 0a 2a 2a 20 74 6f 20 73 65 6c 66 2d 72 65 67  e.** to self-reg
4130: 69 73 74 65 72 65 64 20 75 73 65 72 73 2e 0a 2a  istered users..*
4140: 2f 0a 69 6e 74 20 6c 6f 67 69 6e 5f 73 65 6c 66  /.int login_self
4150: 5f 72 65 67 69 73 74 65 72 5f 61 76 61 69 6c 61  _register_availa
4160: 62 6c 65 28 63 6f 6e 73 74 20 63 68 61 72 20 2a  ble(const char *
4170: 7a 4e 65 65 64 65 64 29 7b 0a 20 20 43 61 70 61  zNeeded){.  Capa
4180: 62 69 6c 69 74 79 53 74 72 69 6e 67 20 2a 70 43  bilityString *pC
4190: 61 70 3b 0a 20 20 69 6e 74 20 72 63 3b 0a 20 20  ap;.  int rc;.  
41a0: 69 66 28 20 21 64 62 5f 67 65 74 5f 62 6f 6f 6c  if( !db_get_bool
41b0: 65 61 6e 28 22 73 65 6c 66 2d 72 65 67 69 73 74  ean("self-regist
41c0: 65 72 22 2c 30 29 20 29 20 72 65 74 75 72 6e 20  er",0) ) return 
41d0: 30 3b 0a 20 20 69 66 28 20 7a 4e 65 65 64 65 64  0;.  if( zNeeded
41e0: 3d 3d 30 20 29 20 72 65 74 75 72 6e 20 31 3b 0a  ==0 ) return 1;.
41f0: 20 20 70 43 61 70 20 3d 20 63 61 70 61 62 69 6c    pCap = capabil
4200: 69 74 79 5f 61 64 64 28 30 2c 20 64 62 5f 67 65  ity_add(0, db_ge
4210: 74 28 22 64 65 66 61 75 6c 74 2d 70 65 72 6d 73  t("default-perms
4220: 22 2c 22 22 29 29 3b 0a 20 20 63 61 70 61 62 69  ",""));.  capabi
4230: 6c 69 74 79 5f 65 78 70 61 6e 64 28 70 43 61 70  lity_expand(pCap
4240: 29 3b 0a 20 20 72 63 20 3d 20 63 61 70 61 62 69  );.  rc = capabi
4250: 6c 69 74 79 5f 68 61 73 5f 61 6e 79 28 70 43 61  lity_has_any(pCa
4260: 70 2c 20 7a 4e 65 65 64 65 64 29 3b 0a 20 20 63  p, zNeeded);.  c
4270: 61 70 61 62 69 6c 69 74 79 5f 66 72 65 65 28 70  apability_free(p
4280: 43 61 70 29 3b 0a 20 20 72 65 74 75 72 6e 20 72  Cap);.  return r
4290: 63 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54 68 65 72  c;.}../*.** Ther
42a0: 65 20 75 73 65 64 20 74 6f 20 62 65 20 61 20 70  e used to be a p
42b0: 61 67 65 20 6e 61 6d 65 64 20 22 6d 79 22 20 74  age named "my" t
42c0: 68 61 74 20 77 61 73 20 64 65 73 69 67 6e 65 64  hat was designed
42d0: 20 74 6f 20 73 68 6f 77 20 69 6e 66 6f 72 6d 61   to show informa
42e0: 74 69 6f 6e 0a 2a 2a 20 61 62 6f 75 74 20 61 20  tion.** about a 
42f0: 73 70 65 63 69 66 69 63 20 75 73 65 72 2e 20 20  specific user.  
4300: 54 68 65 20 22 6d 79 22 20 70 61 67 65 20 77 61  The "my" page wa
4310: 73 20 6c 69 6e 6b 65 64 20 66 72 6f 6d 20 74 68  s linked from th
4320: 65 20 22 4c 6f 67 67 65 64 20 69 6e 20 61 73 20  e "Logged in as 
4330: 55 53 45 52 22 0a 2a 2a 20 6c 69 6e 65 20 6f 6e  USER".** line on
4340: 20 74 68 65 20 74 69 74 6c 65 20 62 61 72 2e 20   the title bar. 
4350: 20 54 68 65 20 22 6d 79 22 20 70 61 67 65 20 77   The "my" page w
4360: 61 73 20 6e 65 76 65 72 20 63 6f 6d 70 6c 65 74  as never complet
4370: 65 64 20 73 6f 20 69 74 20 69 73 20 6e 6f 77 0a  ed so it is now.
4380: 2a 2a 20 72 65 6d 6f 76 65 64 2e 20 20 55 73 65  ** removed.  Use
4390: 20 74 68 69 73 20 70 61 67 65 20 61 73 20 61 20   this page as a 
43a0: 70 6c 61 63 65 68 6f 6c 64 65 72 20 69 6e 20 6f  placeholder in o
43b0: 6c 64 65 72 20 69 6e 73 74 61 6c 6c 61 74 69 6f  lder installatio
43c0: 6e 73 2e 0a 2a 2a 0a 2a 2a 20 57 45 42 50 41 47  ns..**.** WEBPAG
43d0: 45 3a 20 6c 6f 67 69 6e 0a 2a 2a 20 57 45 42 50  E: login.** WEBP
43e0: 41 47 45 3a 20 6c 6f 67 6f 75 74 0a 2a 2a 20 57  AGE: logout.** W
43f0: 45 42 50 41 47 45 3a 20 6d 79 0a 2a 2a 0a 2a 2a  EBPAGE: my.**.**
4400: 20 54 68 65 20 6c 6f 67 69 6e 2f 6c 6f 67 6f 75   The login/logou
4410: 74 20 70 61 67 65 2e 20 20 50 61 72 61 6d 65 74  t page.  Paramet
4420: 65 72 73 3a 0a 2a 2a 0a 2a 2a 20 20 20 20 67 3d  ers:.**.**    g=
4430: 55 52 4c 20 20 20 20 20 20 20 20 20 20 20 20 20  URL             
4440: 4a 75 6d 70 20 62 61 63 6b 20 74 6f 20 74 68 69  Jump back to thi
4450: 73 20 55 52 4c 20 61 66 74 65 72 20 6c 6f 67 69  s URL after logi
4460: 6e 20 63 6f 6d 70 6c 65 74 65 73 0a 2a 2a 20 20  n completes.**  
4470: 20 20 61 6e 6f 6e 20 20 20 20 20 20 20 20 20 20    anon          
4480: 20 20 20 20 54 68 65 20 67 3d 55 52 4c 20 69 73      The g=URL is
4490: 20 6e 6f 74 20 61 63 63 65 73 73 69 62 6c 65 20   not accessible 
44a0: 62 79 20 22 6e 6f 62 6f 64 79 22 20 62 75 74 20  by "nobody" but 
44b0: 69 73 0a 2a 2a 20 20 20 20 20 20 20 20 20 20 20  is.**           
44c0: 20 20 20 20 20 20 20 20 20 20 20 61 63 63 65 73             acces
44d0: 73 69 62 6c 65 20 62 79 20 22 61 6e 6f 6e 79 6d  sible by "anonym
44e0: 6f 75 73 22 0a 2a 2f 0a 76 6f 69 64 20 6c 6f 67  ous".*/.void log
44f0: 69 6e 5f 70 61 67 65 28 76 6f 69 64 29 7b 0a 20  in_page(void){. 
4500: 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 55 73   const char *zUs
4510: 65 72 6e 61 6d 65 2c 20 2a 7a 50 61 73 73 77 64  ername, *zPasswd
4520: 3b 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a  ;.  const char *
4530: 7a 4e 65 77 31 2c 20 2a 7a 4e 65 77 32 3b 0a 20  zNew1, *zNew2;. 
4540: 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 41 6e   const char *zAn
4550: 6f 6e 50 77 20 3d 20 30 3b 0a 20 20 63 6f 6e 73  onPw = 0;.  cons
4560: 74 20 63 68 61 72 20 2a 7a 47 6f 74 6f 20 3d 20  t char *zGoto = 
4570: 50 28 22 67 22 29 3b 0a 20 20 69 6e 74 20 61 6e  P("g");.  int an
4580: 6f 6e 46 6c 61 67 3b 20 20 20 20 20 20 20 20 20  onFlag;         
4590: 20 20 20 20 20 20 20 2f 2a 20 4c 6f 67 69 6e 20         /* Login 
45a0: 61 73 20 22 61 6e 6f 6e 79 6d 6f 75 73 22 20 77  as "anonymous" w
45b0: 6f 75 6c 64 20 62 65 20 75 73 65 66 75 6c 20 2a  ould be useful *
45c0: 2f 0a 20 20 63 68 61 72 20 2a 7a 45 72 72 4d 73  /.  char *zErrMs
45d0: 67 20 3d 20 22 22 3b 0a 20 20 69 6e 74 20 75 69  g = "";.  int ui
45e0: 64 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  d;              
45f0: 20 20 20 20 20 20 20 2f 2a 20 55 73 65 72 20 69         /* User i
4600: 64 20 6c 6f 67 67 65 64 20 69 6e 20 75 73 65 72  d logged in user
4610: 20 2a 2f 0a 20 20 63 68 61 72 20 2a 7a 53 68 61   */.  char *zSha
4620: 31 50 77 3b 0a 20 20 63 6f 6e 73 74 20 63 68 61  1Pw;.  const cha
4630: 72 20 2a 7a 49 70 41 64 64 72 3b 20 20 20 20 20  r *zIpAddr;     
4640: 20 20 20 20 2f 2a 20 49 50 20 61 64 64 72 65 73      /* IP addres
4650: 73 20 6f 66 20 72 65 71 75 65 73 74 6f 72 20 2a  s of requestor *
4660: 2f 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a  /.  const char *
4670: 7a 52 65 66 65 72 65 72 3b 0a 20 20 69 6e 74 20  zReferer;.  int 
4680: 6e 6f 41 6e 6f 6e 20 3d 20 50 28 22 6e 6f 61 6e  noAnon = P("noan
4690: 6f 6e 22 29 21 3d 30 3b 0a 0a 20 20 6c 6f 67 69  on")!=0;..  logi
46a0: 6e 5f 63 68 65 63 6b 5f 63 72 65 64 65 6e 74 69  n_check_credenti
46b0: 61 6c 73 28 29 3b 0a 20 20 66 6f 73 73 69 6c 5f  als();.  fossil_
46c0: 72 65 64 69 72 65 63 74 5f 74 6f 5f 68 74 74 70  redirect_to_http
46d0: 73 5f 69 66 5f 6e 65 65 64 65 64 28 31 29 3b 0a  s_if_needed(1);.
46e0: 20 20 73 71 6c 69 74 65 33 5f 63 72 65 61 74 65    sqlite3_create
46f0: 5f 66 75 6e 63 74 69 6f 6e 28 67 2e 64 62 2c 20  _function(g.db, 
4700: 22 63 6f 6e 73 74 61 6e 74 5f 74 69 6d 65 5f 63  "constant_time_c
4710: 6d 70 22 2c 20 32 2c 20 53 51 4c 49 54 45 5f 55  mp", 2, SQLITE_U
4720: 54 46 38 2c 20 30 2c 0a 20 20 20 20 20 20 20 20  TF8, 0,.        
4730: 20 20 20 20 20 20 20 20 20 20 63 6f 6e 73 74 61            consta
4740: 6e 74 5f 74 69 6d 65 5f 63 6d 70 5f 66 75 6e 63  nt_time_cmp_func
4750: 74 69 6f 6e 2c 20 30 2c 20 30 29 3b 0a 20 20 7a  tion, 0, 0);.  z
4760: 55 73 65 72 6e 61 6d 65 20 3d 20 50 28 22 75 22  Username = P("u"
4770: 29 3b 0a 20 20 7a 50 61 73 73 77 64 20 3d 20 50  );.  zPasswd = P
4780: 28 22 70 22 29 3b 0a 20 20 61 6e 6f 6e 46 6c 61  ("p");.  anonFla
4790: 67 20 3d 20 67 2e 7a 4c 6f 67 69 6e 3d 3d 30 20  g = g.zLogin==0 
47a0: 26 26 20 50 42 28 22 61 6e 6f 6e 22 29 3b 0a 0a  && PB("anon");..
47b0: 20 20 2f 2a 20 48 61 6e 64 6c 65 20 6c 6f 67 2d    /* Handle log-
47c0: 6f 75 74 20 72 65 71 75 65 73 74 73 20 2a 2f 0a  out requests */.
47d0: 20 20 69 66 28 20 50 28 22 6f 75 74 22 29 20 29    if( P("out") )
47e0: 7b 0a 20 20 20 20 6c 6f 67 69 6e 5f 63 6c 65 61  {.    login_clea
47f0: 72 5f 6c 6f 67 69 6e 5f 64 61 74 61 28 29 3b 0a  r_login_data();.
4800: 20 20 20 20 72 65 64 69 72 65 63 74 5f 74 6f 5f      redirect_to_
4810: 67 28 29 3b 0a 20 20 20 20 72 65 74 75 72 6e 3b  g();.    return;
4820: 0a 20 20 7d 0a 0a 20 20 2f 2a 20 52 65 64 69 72  .  }..  /* Redir
4830: 65 63 74 20 66 6f 72 20 63 72 65 61 74 65 2d 6e  ect for create-n
4840: 65 77 2d 61 63 63 6f 75 6e 74 20 72 65 71 75 65  ew-account reque
4850: 73 74 73 20 2a 2f 0a 20 20 69 66 28 20 50 28 22  sts */.  if( P("
4860: 73 65 6c 66 22 29 20 29 7b 0a 20 20 20 20 63 67  self") ){.    cg
4870: 69 5f 72 65 64 69 72 65 63 74 66 28 22 25 52 2f  i_redirectf("%R/
4880: 72 65 67 69 73 74 65 72 22 29 3b 0a 20 20 20 20  register");.    
4890: 72 65 74 75 72 6e 3b 0a 20 20 7d 0a 0a 20 20 2f  return;.  }..  /
48a0: 2a 20 44 65 61 6c 20 77 69 74 68 20 70 61 73 73  * Deal with pass
48b0: 77 6f 72 64 2d 63 68 61 6e 67 65 20 72 65 71 75  word-change requ
48c0: 65 73 74 73 20 2a 2f 0a 20 20 69 66 28 20 67 2e  ests */.  if( g.
48d0: 70 65 72 6d 2e 50 61 73 73 77 6f 72 64 20 26 26  perm.Password &&
48e0: 20 7a 50 61 73 73 77 64 0a 20 20 20 26 26 20 28   zPasswd.   && (
48f0: 7a 4e 65 77 31 20 3d 20 50 28 22 6e 31 22 29 29  zNew1 = P("n1"))
4900: 21 3d 30 20 26 26 20 28 7a 4e 65 77 32 20 3d 20  !=0 && (zNew2 = 
4910: 50 28 22 6e 32 22 29 29 21 3d 30 0a 20 20 29 7b  P("n2"))!=0.  ){
4920: 0a 20 20 20 20 2f 2a 20 49 66 20 74 68 65 72 65  .    /* If there
4930: 20 69 73 20 6e 6f 74 20 61 20 22 72 65 61 6c 22   is not a "real"
4940: 20 6c 6f 67 69 6e 2c 20 77 65 20 63 61 6e 6e 6f   login, we canno
4950: 74 20 63 68 61 6e 67 65 20 61 6e 79 20 70 61 73  t change any pas
4960: 73 77 6f 72 64 2e 20 2a 2f 0a 20 20 20 20 69 66  sword. */.    if
4970: 28 20 67 2e 7a 4c 6f 67 69 6e 20 29 7b 0a 20 20  ( g.zLogin ){.  
4980: 20 20 20 20 2f 2a 20 54 68 65 20 75 73 65 72 20      /* The user 
4990: 72 65 71 75 65 73 74 73 20 61 20 70 61 73 73 77  requests a passw
49a0: 6f 72 64 20 63 68 61 6e 67 65 20 2a 2f 0a 20 20  ord change */.  
49b0: 20 20 20 20 7a 53 68 61 31 50 77 20 3d 20 73 68      zSha1Pw = sh
49c0: 61 31 5f 73 68 61 72 65 64 5f 73 65 63 72 65 74  a1_shared_secret
49d0: 28 7a 50 61 73 73 77 64 2c 20 67 2e 7a 4c 6f 67  (zPasswd, g.zLog
49e0: 69 6e 2c 20 30 29 3b 0a 20 20 20 20 20 20 69 66  in, 0);.      if
49f0: 28 20 64 62 5f 69 6e 74 28 31 2c 20 22 53 45 4c  ( db_int(1, "SEL
4a00: 45 43 54 20 30 20 46 52 4f 4d 20 75 73 65 72 22  ECT 0 FROM user"
4a10: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
4a20: 20 20 20 20 20 22 20 57 48 45 52 45 20 75 69 64       " WHERE uid
4a30: 3d 25 64 22 0a 20 20 20 20 20 20 20 20 20 20 20  =%d".           
4a40: 20 20 20 20 20 20 20 20 20 22 20 41 4e 44 20 28           " AND (
4a50: 63 6f 6e 73 74 61 6e 74 5f 74 69 6d 65 5f 63 6d  constant_time_cm
4a60: 70 28 70 77 2c 25 51 29 3d 30 22 0a 20 20 20 20  p(pw,%Q)=0".    
4a70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4a80: 22 20 20 20 20 20 20 4f 52 20 63 6f 6e 73 74 61  "      OR consta
4a90: 6e 74 5f 74 69 6d 65 5f 63 6d 70 28 70 77 2c 25  nt_time_cmp(pw,%
4aa0: 51 29 3d 30 29 22 2c 0a 20 20 20 20 20 20 20 20  Q)=0)",.        
4ab0: 20 20 20 20 20 20 20 20 20 20 20 20 67 2e 75 73              g.us
4ac0: 65 72 55 69 64 2c 20 7a 53 68 61 31 50 77 2c 20  erUid, zSha1Pw, 
4ad0: 7a 50 61 73 73 77 64 29 20 29 7b 0a 20 20 20 20  zPasswd) ){.    
4ae0: 20 20 20 20 73 6c 65 65 70 28 31 29 3b 0a 20 20      sleep(1);.  
4af0: 20 20 20 20 20 20 7a 45 72 72 4d 73 67 20 3d 0a        zErrMsg =.
4b00: 20 20 20 20 20 20 20 20 20 20 20 40 20 3c 70 3e             @ <p>
4b10: 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6c 6f 67  <span class="log
4b20: 69 6e 45 72 72 6f 72 22 3e 0a 20 20 20 20 20 20  inError">.      
4b30: 20 20 20 20 20 40 20 59 6f 75 20 65 6e 74 65 72       @ You enter
4b40: 65 64 20 61 6e 20 69 6e 63 6f 72 72 65 63 74 20  ed an incorrect 
4b50: 6f 6c 64 20 70 61 73 73 77 6f 72 64 20 77 68 69  old password whi
4b60: 6c 65 20 61 74 74 65 6d 70 74 69 6e 67 20 74 6f  le attempting to
4b70: 20 63 68 61 6e 67 65 0a 20 20 20 20 20 20 20 20   change.        
4b80: 20 20 20 40 20 79 6f 75 72 20 70 61 73 73 77 6f     @ your passwo
4b90: 72 64 2e 20 20 59 6f 75 72 20 70 61 73 73 77 6f  rd.  Your passwo
4ba0: 72 64 20 69 73 20 75 6e 63 68 61 6e 67 65 64 2e  rd is unchanged.
4bb0: 0a 20 20 20 20 20 20 20 20 20 20 20 40 20 3c 2f  .           @ </
4bc0: 73 70 61 6e 3e 3c 2f 70 3e 0a 20 20 20 20 20 20  span></p>.      
4bd0: 20 20 3b 0a 20 20 20 20 20 20 7d 65 6c 73 65 20    ;.      }else 
4be0: 69 66 28 20 66 6f 73 73 69 6c 5f 73 74 72 63 6d  if( fossil_strcm
4bf0: 70 28 7a 4e 65 77 31 2c 7a 4e 65 77 32 29 21 3d  p(zNew1,zNew2)!=
4c00: 30 20 29 7b 0a 20 20 20 20 20 20 20 20 7a 45 72  0 ){.        zEr
4c10: 72 4d 73 67 20 3d 0a 20 20 20 20 20 20 20 20 20  rMsg =.         
4c20: 20 20 40 20 3c 70 3e 3c 73 70 61 6e 20 63 6c 61    @ <p><span cla
4c30: 73 73 3d 22 6c 6f 67 69 6e 45 72 72 6f 72 22 3e  ss="loginError">
4c40: 0a 20 20 20 20 20 20 20 20 20 20 20 40 20 54 68  .           @ Th
4c50: 65 20 74 77 6f 20 63 6f 70 69 65 73 20 6f 66 20  e two copies of 
4c60: 79 6f 75 72 20 6e 65 77 20 70 61 73 73 77 6f 72  your new passwor
4c70: 64 73 20 64 6f 20 6e 6f 74 20 6d 61 74 63 68 2e  ds do not match.
4c80: 0a 20 20 20 20 20 20 20 20 20 20 20 40 20 59 6f  .           @ Yo
4c90: 75 72 20 70 61 73 73 77 6f 72 64 20 69 73 20 75  ur password is u
4ca0: 6e 63 68 61 6e 67 65 64 2e 0a 20 20 20 20 20 20  nchanged..      
4cb0: 20 20 20 20 20 40 20 3c 2f 73 70 61 6e 3e 3c 2f       @ </span></
4cc0: 70 3e 0a 20 20 20 20 20 20 20 20 3b 0a 20 20 20  p>.        ;.   
4cd0: 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20     }else{.      
4ce0: 20 20 63 68 61 72 20 2a 7a 4e 65 77 50 77 20 3d    char *zNewPw =
4cf0: 20 73 68 61 31 5f 73 68 61 72 65 64 5f 73 65 63   sha1_shared_sec
4d00: 72 65 74 28 7a 4e 65 77 31 2c 20 67 2e 7a 4c 6f  ret(zNew1, g.zLo
4d10: 67 69 6e 2c 20 30 29 3b 0a 20 20 20 20 20 20 20  gin, 0);.       
4d20: 20 63 68 61 72 20 2a 7a 43 68 6e 67 50 77 3b 0a   char *zChngPw;.
4d30: 20 20 20 20 20 20 20 20 63 68 61 72 20 2a 7a 45          char *zE
4d40: 72 72 3b 0a 20 20 20 20 20 20 20 20 64 62 5f 6d  rr;.        db_m
4d50: 75 6c 74 69 5f 65 78 65 63 28 0a 20 20 20 20 20  ulti_exec(.     
4d60: 20 20 20 20 20 20 22 55 50 44 41 54 45 20 75 73        "UPDATE us
4d70: 65 72 20 53 45 54 20 70 77 3d 25 51 20 57 48 45  er SET pw=%Q WHE
4d80: 52 45 20 75 69 64 3d 25 64 22 2c 20 7a 4e 65 77  RE uid=%d", zNew
4d90: 50 77 2c 20 67 2e 75 73 65 72 55 69 64 0a 20 20  Pw, g.userUid.  
4da0: 20 20 20 20 20 20 29 3b 0a 20 20 20 20 20 20 20        );.       
4db0: 20 66 6f 73 73 69 6c 5f 66 72 65 65 28 7a 4e 65   fossil_free(zNe
4dc0: 77 50 77 29 3b 0a 20 20 20 20 20 20 20 20 7a 43  wPw);.        zC
4dd0: 68 6e 67 50 77 20 3d 20 6d 70 72 69 6e 74 66 28  hngPw = mprintf(
4de0: 0a 20 20 20 20 20 20 20 20 20 20 20 22 55 50 44  .           "UPD
4df0: 41 54 45 20 75 73 65 72 22 0a 20 20 20 20 20 20  ATE user".      
4e00: 20 20 20 20 20 22 20 20 20 53 45 54 20 70 77 3d       "   SET pw=
4e10: 73 68 61 72 65 64 5f 73 65 63 72 65 74 28 25 51  shared_secret(%Q
4e20: 2c 25 51 2c 22 0a 20 20 20 20 20 20 20 20 20 20  ,%Q,".          
4e30: 20 22 20 20 20 20 20 20 20 20 28 53 45 4c 45 43   "        (SELEC
4e40: 54 20 76 61 6c 75 65 20 46 52 4f 4d 20 63 6f 6e  T value FROM con
4e50: 66 69 67 20 57 48 45 52 45 20 6e 61 6d 65 3d 27  fig WHERE name='
4e60: 70 72 6f 6a 65 63 74 2d 63 6f 64 65 27 29 29 22  project-code'))"
4e70: 0a 20 20 20 20 20 20 20 20 20 20 20 22 20 57 48  .           " WH
4e80: 45 52 45 20 6c 6f 67 69 6e 3d 25 51 22 2c 0a 20  ERE login=%Q",. 
4e90: 20 20 20 20 20 20 20 20 20 20 7a 4e 65 77 31 2c            zNew1,
4ea0: 20 67 2e 7a 4c 6f 67 69 6e 2c 20 67 2e 7a 4c 6f   g.zLogin, g.zLo
4eb0: 67 69 6e 0a 20 20 20 20 20 20 20 20 29 3b 0a 20  gin.        );. 
4ec0: 20 20 20 20 20 20 20 69 66 28 20 6c 6f 67 69 6e         if( login
4ed0: 5f 67 72 6f 75 70 5f 73 71 6c 28 7a 43 68 6e 67  _group_sql(zChng
4ee0: 50 77 2c 20 22 3c 70 3e 22 2c 20 22 3c 2f 70 3e  Pw, "<p>", "</p>
4ef0: 5c 6e 22 2c 20 26 7a 45 72 72 29 20 29 7b 0a 20  \n", &zErr) ){. 
4f00: 20 20 20 20 20 20 20 20 20 7a 45 72 72 4d 73 67           zErrMsg
4f10: 20 3d 20 6d 70 72 69 6e 74 66 28 22 3c 73 70 61   = mprintf("<spa
4f20: 6e 20 63 6c 61 73 73 3d 5c 22 6c 6f 67 69 6e 45  n class=\"loginE
4f30: 72 72 6f 72 5c 22 3e 25 73 3c 2f 73 70 61 6e 3e  rror\">%s</span>
4f40: 22 2c 20 7a 45 72 72 29 3b 0a 20 20 20 20 20 20  ", zErr);.      
4f50: 20 20 20 20 66 6f 73 73 69 6c 5f 66 72 65 65 28      fossil_free(
4f60: 7a 45 72 72 29 3b 0a 20 20 20 20 20 20 20 20 7d  zErr);.        }
4f70: 65 6c 73 65 7b 0a 20 20 20 20 20 20 20 20 20 20  else{.          
4f80: 72 65 64 69 72 65 63 74 5f 74 6f 5f 67 28 29 3b  redirect_to_g();
4f90: 0a 20 20 20 20 20 20 20 20 20 20 72 65 74 75 72  .          retur
4fa0: 6e 3b 0a 20 20 20 20 20 20 20 20 7d 0a 20 20 20  n;.        }.   
4fb0: 20 20 20 7d 0a 20 20 20 20 7d 65 6c 73 65 7b 0a     }.    }else{.
4fc0: 20 20 20 20 20 20 7a 45 72 72 4d 73 67 20 3d 0a        zErrMsg =.
4fd0: 20 20 20 20 20 20 20 20 20 40 20 3c 70 3e 3c 73           @ <p><s
4fe0: 70 61 6e 20 63 6c 61 73 73 3d 22 6c 6f 67 69 6e  pan class="login
4ff0: 45 72 72 6f 72 22 3e 0a 20 20 20 20 20 20 20 20  Error">.        
5000: 20 40 20 54 68 65 20 70 61 73 73 77 6f 72 64 20   @ The password 
5010: 63 61 6e 6e 6f 74 20 62 65 20 63 68 61 6e 67 65  cannot be change
5020: 64 20 66 6f 72 20 74 68 69 73 20 74 79 70 65 20  d for this type 
5030: 6f 66 20 6c 6f 67 69 6e 2e 0a 20 20 20 20 20 20  of login..      
5040: 20 20 20 40 20 54 68 65 20 70 61 73 73 77 6f 72     @ The passwor
5050: 64 20 69 73 20 75 6e 63 68 61 6e 67 65 64 2e 0a  d is unchanged..
5060: 20 20 20 20 20 20 20 20 20 40 20 3c 2f 73 70 61           @ </spa
5070: 6e 3e 3c 2f 70 3e 0a 20 20 20 20 20 20 3b 0a 20  n></p>.      ;. 
5080: 20 20 20 7d 0a 20 20 7d 0a 20 20 7a 49 70 41 64     }.  }.  zIpAd
5090: 64 72 20 3d 20 50 44 28 22 52 45 4d 4f 54 45 5f  dr = PD("REMOTE_
50a0: 41 44 44 52 22 2c 22 6e 69 6c 22 29 3b 20 20 20  ADDR","nil");   
50b0: 2f 2a 20 43 6f 6d 70 6c 65 74 65 20 49 50 20 61  /* Complete IP a
50c0: 64 64 72 65 73 73 20 66 6f 72 20 6c 6f 67 67 69  ddress for loggi
50d0: 6e 67 20 2a 2f 0a 20 20 7a 52 65 66 65 72 65 72  ng */.  zReferer
50e0: 20 3d 20 50 28 22 48 54 54 50 5f 52 45 46 45 52   = P("HTTP_REFER
50f0: 45 52 22 29 3b 0a 20 20 75 69 64 20 3d 20 6c 6f  ER");.  uid = lo
5100: 67 69 6e 5f 69 73 5f 76 61 6c 69 64 5f 61 6e 6f  gin_is_valid_ano
5110: 6e 79 6d 6f 75 73 28 7a 55 73 65 72 6e 61 6d 65  nymous(zUsername
5120: 2c 20 7a 50 61 73 73 77 64 2c 20 50 28 22 63 73  , zPasswd, P("cs
5130: 22 29 29 3b 0a 20 20 69 66 28 20 75 69 64 3e 30  "));.  if( uid>0
5140: 20 29 7b 0a 20 20 20 20 6c 6f 67 69 6e 5f 73 65   ){.    login_se
5150: 74 5f 61 6e 6f 6e 5f 63 6f 6f 6b 69 65 28 7a 49  t_anon_cookie(zI
5160: 70 41 64 64 72 2c 20 4e 55 4c 4c 29 3b 0a 20 20  pAddr, NULL);.  
5170: 20 20 72 65 63 6f 72 64 5f 6c 6f 67 69 6e 5f 61    record_login_a
5180: 74 74 65 6d 70 74 28 22 61 6e 6f 6e 79 6d 6f 75  ttempt("anonymou
5190: 73 22 2c 20 7a 49 70 41 64 64 72 2c 20 31 29 3b  s", zIpAddr, 1);
51a0: 0a 20 20 20 20 72 65 64 69 72 65 63 74 5f 74 6f  .    redirect_to
51b0: 5f 67 28 29 3b 0a 20 20 7d 0a 20 20 69 66 28 20  _g();.  }.  if( 
51c0: 7a 55 73 65 72 6e 61 6d 65 21 3d 30 20 26 26 20  zUsername!=0 && 
51d0: 7a 50 61 73 73 77 64 21 3d 30 20 26 26 20 7a 50  zPasswd!=0 && zP
51e0: 61 73 73 77 64 5b 30 5d 21 3d 30 20 29 7b 0a 20  asswd[0]!=0 ){. 
51f0: 20 20 20 2f 2a 20 41 74 74 65 6d 70 74 69 6e 67     /* Attempting
5200: 20 74 6f 20 6c 6f 67 20 69 6e 20 61 73 20 61 20   to log in as a 
5210: 75 73 65 72 20 6f 74 68 65 72 20 74 68 61 6e 20  user other than 
5220: 61 6e 6f 6e 79 6d 6f 75 73 2e 0a 20 20 20 20 2a  anonymous..    *
5230: 2f 0a 20 20 20 20 75 69 64 20 3d 20 6c 6f 67 69  /.    uid = logi
5240: 6e 5f 73 65 61 72 63 68 5f 75 69 64 28 26 7a 55  n_search_uid(&zU
5250: 73 65 72 6e 61 6d 65 2c 20 7a 50 61 73 73 77 64  sername, zPasswd
5260: 29 3b 0a 20 20 20 20 69 66 28 20 75 69 64 3c 3d  );.    if( uid<=
5270: 30 20 29 7b 0a 20 20 20 20 20 20 73 6c 65 65 70  0 ){.      sleep
5280: 28 31 29 3b 0a 20 20 20 20 20 20 7a 45 72 72 4d  (1);.      zErrM
5290: 73 67 20 3d 0a 20 20 20 20 20 20 20 20 20 40 20  sg =.         @ 
52a0: 3c 70 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22  <p><span class="
52b0: 6c 6f 67 69 6e 45 72 72 6f 72 22 3e 0a 20 20 20  loginError">.   
52c0: 20 20 20 20 20 20 40 20 59 6f 75 20 65 6e 74 65        @ You ente
52d0: 72 65 64 20 61 6e 20 75 6e 6b 6e 6f 77 6e 20 75  red an unknown u
52e0: 73 65 72 20 6f 72 20 61 6e 20 69 6e 63 6f 72 72  ser or an incorr
52f0: 65 63 74 20 70 61 73 73 77 6f 72 64 2e 0a 20 20  ect password..  
5300: 20 20 20 20 20 20 20 40 20 3c 2f 73 70 61 6e 3e         @ </span>
5310: 3c 2f 70 3e 0a 20 20 20 20 20 20 3b 0a 20 20 20  </p>.      ;.   
5320: 20 20 20 72 65 63 6f 72 64 5f 6c 6f 67 69 6e 5f     record_login_
5330: 61 74 74 65 6d 70 74 28 7a 55 73 65 72 6e 61 6d  attempt(zUsernam
5340: 65 2c 20 7a 49 70 41 64 64 72 2c 20 30 29 3b 0a  e, zIpAddr, 0);.
5350: 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20      }else{.     
5360: 20 2f 2a 20 4e 6f 6e 2d 61 6e 6f 6e 79 6d 6f 75   /* Non-anonymou
5370: 73 20 6c 6f 67 69 6e 20 69 73 20 73 75 63 63 65  s login is succe
5380: 73 73 66 75 6c 2e 20 20 53 65 74 20 61 20 63 6f  ssful.  Set a co
5390: 6f 6b 69 65 20 6f 66 20 74 68 65 20 66 6f 72 6d  okie of the form
53a0: 3a 0a 20 20 20 20 20 20 2a 2a 0a 20 20 20 20 20  :.      **.     
53b0: 20 2a 2a 20 20 20 20 48 41 53 48 2f 50 52 4f 4a   **    HASH/PROJ
53c0: 45 43 54 2f 4c 4f 47 49 4e 0a 20 20 20 20 20 20  ECT/LOGIN.      
53d0: 2a 2a 0a 20 20 20 20 20 20 2a 2a 20 77 68 65 72  **.      ** wher
53e0: 65 20 48 41 53 48 20 69 73 20 61 20 72 61 6e 64  e HASH is a rand
53f0: 6f 6d 20 68 65 78 20 6e 75 6d 62 65 72 2c 20 50  om hex number, P
5400: 52 4f 4a 45 43 54 20 69 73 20 65 69 74 68 65 72  ROJECT is either
5410: 20 70 72 6f 6a 65 63 74 0a 20 20 20 20 20 20 2a   project.      *
5420: 2a 20 63 6f 64 65 20 70 72 65 66 69 78 2c 20 61  * code prefix, a
5430: 6e 64 20 4c 4f 47 49 4e 20 69 73 20 74 68 65 20  nd LOGIN is the 
5440: 75 73 65 72 20 6e 61 6d 65 2e 0a 20 20 20 20 20  user name..     
5450: 20 2a 2f 0a 20 20 20 20 20 20 6c 6f 67 69 6e 5f   */.      login_
5460: 73 65 74 5f 75 73 65 72 5f 63 6f 6f 6b 69 65 28  set_user_cookie(
5470: 7a 55 73 65 72 6e 61 6d 65 2c 20 75 69 64 2c 20  zUsername, uid, 
5480: 4e 55 4c 4c 29 3b 0a 20 20 20 20 20 20 72 65 64  NULL);.      red
5490: 69 72 65 63 74 5f 74 6f 5f 67 28 29 3b 0a 20 20  irect_to_g();.  
54a0: 20 20 7d 0a 20 20 7d 0a 20 20 73 74 79 6c 65 5f    }.  }.  style_
54b0: 68 65 61 64 65 72 28 22 4c 6f 67 69 6e 2f 4c 6f  header("Login/Lo
54c0: 67 6f 75 74 22 29 3b 0a 20 20 73 74 79 6c 65 5f  gout");.  style_
54d0: 61 64 75 6e 69 74 5f 63 6f 6e 66 69 67 28 41 44  adunit_config(AD
54e0: 55 4e 49 54 5f 4f 46 46 29 3b 0a 20 20 40 20 25  UNIT_OFF);.  @ %
54f0: 73 28 7a 45 72 72 4d 73 67 29 0a 20 20 69 66 28  s(zErrMsg).  if(
5500: 20 7a 47 6f 74 6f 20 26 26 20 21 6e 6f 41 6e 6f   zGoto && !noAno
5510: 6e 20 29 7b 0a 20 20 20 20 63 68 61 72 20 2a 7a  n ){.    char *z
5520: 41 62 62 72 65 76 20 3d 20 66 6f 73 73 69 6c 5f  Abbrev = fossil_
5530: 73 74 72 64 75 70 28 7a 47 6f 74 6f 29 3b 0a 20  strdup(zGoto);. 
5540: 20 20 20 69 6e 74 20 69 3b 0a 20 20 20 20 66 6f     int i;.    fo
5550: 72 28 69 3d 30 3b 20 7a 41 62 62 72 65 76 5b 69  r(i=0; zAbbrev[i
5560: 5d 20 26 26 20 7a 41 62 62 72 65 76 5b 69 5d 21  ] && zAbbrev[i]!
5570: 3d 27 3f 27 3b 20 69 2b 2b 29 7b 7d 0a 20 20 20  ='?'; i++){}.   
5580: 20 7a 41 62 62 72 65 76 5b 69 5d 20 3d 20 30 3b   zAbbrev[i] = 0;
5590: 0a 20 20 20 20 69 66 28 20 67 2e 7a 4c 6f 67 69  .    if( g.zLogi
55a0: 6e 20 29 7b 0a 20 20 20 20 20 20 40 20 3c 70 3e  n ){.      @ <p>
55b0: 55 73 65 20 61 20 64 69 66 66 65 72 65 6e 74 20  Use a different 
55c0: 6c 6f 67 69 6e 20 77 69 74 68 20 67 72 65 61 74  login with great
55d0: 65 72 20 70 72 69 76 69 6c 65 67 65 20 74 68 61  er privilege tha
55e0: 6e 20 3c 62 3e 25 68 28 67 2e 7a 4c 6f 67 69 6e  n <b>%h(g.zLogin
55f0: 29 3c 2f 62 3e 0a 20 20 20 20 20 20 40 20 74 6f  )</b>.      @ to
5600: 20 61 63 63 65 73 73 20 3c 62 3e 25 68 28 7a 41   access <b>%h(zA
5610: 62 62 72 65 76 29 3c 2f 62 3e 2e 0a 20 20 20 20  bbrev)</b>..    
5620: 7d 65 6c 73 65 20 69 66 28 20 61 6e 6f 6e 46 6c  }else if( anonFl
5630: 61 67 20 29 7b 0a 20 20 20 20 20 20 40 20 3c 70  ag ){.      @ <p
5640: 3e 4c 6f 67 69 6e 20 61 73 20 3c 62 3e 61 6e 6f  >Login as <b>ano
5650: 6e 79 6d 6f 75 73 3c 2f 62 3e 20 6f 72 20 61 6e  nymous</b> or an
5660: 79 20 6e 61 6d 65 64 20 75 73 65 72 0a 20 20 20  y named user.   
5670: 20 20 20 40 20 74 6f 20 61 63 63 65 73 73 20 70     @ to access p
5680: 61 67 65 20 3c 62 3e 25 68 28 7a 41 62 62 72 65  age <b>%h(zAbbre
5690: 76 29 3c 2f 62 3e 2e 0a 20 20 20 20 7d 65 6c 73  v)</b>..    }els
56a0: 65 7b 0a 20 20 20 20 20 20 40 20 3c 70 3e 4c 6f  e{.      @ <p>Lo
56b0: 67 69 6e 20 61 73 20 61 20 6e 61 6d 65 64 20 75  gin as a named u
56c0: 73 65 72 20 74 6f 20 61 63 63 65 73 73 20 70 61  ser to access pa
56d0: 67 65 20 3c 62 3e 25 68 28 7a 41 62 62 72 65 76  ge <b>%h(zAbbrev
56e0: 29 3c 2f 62 3e 2e 0a 20 20 20 20 7d 0a 20 20 7d  )</b>..    }.  }
56f0: 0a 20 20 69 66 28 20 67 2e 73 73 6c 4e 6f 74 41  .  if( g.sslNotA
5700: 76 61 69 6c 61 62 6c 65 3d 3d 30 0a 20 20 20 26  vailable==0.   &
5710: 26 20 73 74 72 6e 63 6d 70 28 67 2e 7a 42 61 73  & strncmp(g.zBas
5720: 65 55 52 4c 2c 22 68 74 74 70 73 3a 22 2c 36 29  eURL,"https:",6)
5730: 21 3d 30 0a 20 20 20 26 26 20 64 62 5f 67 65 74  !=0.   && db_get
5740: 5f 62 6f 6f 6c 65 61 6e 28 22 68 74 74 70 73 2d  _boolean("https-
5750: 6c 6f 67 69 6e 22 2c 30 29 0a 20 20 29 7b 0a 20  login",0).  ){. 
5760: 20 20 20 66 6f 72 6d 5f 62 65 67 69 6e 28 30 2c     form_begin(0,
5770: 20 22 68 74 74 70 73 3a 25 73 2f 6c 6f 67 69 6e   "https:%s/login
5780: 22 2c 20 67 2e 7a 42 61 73 65 55 52 4c 2b 35 29  ", g.zBaseURL+5)
5790: 3b 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 66  ;.  }else{.    f
57a0: 6f 72 6d 5f 62 65 67 69 6e 28 30 2c 20 22 25 52  orm_begin(0, "%R
57b0: 2f 6c 6f 67 69 6e 22 29 3b 0a 20 20 7d 0a 20 20  /login");.  }.  
57c0: 69 66 28 20 7a 47 6f 74 6f 20 29 7b 0a 20 20 20  if( zGoto ){.   
57d0: 20 40 20 3c 69 6e 70 75 74 20 74 79 70 65 3d 22   @ <input type="
57e0: 68 69 64 64 65 6e 22 20 6e 61 6d 65 3d 22 67 22  hidden" name="g"
57f0: 20 76 61 6c 75 65 3d 22 25 68 28 7a 47 6f 74 6f   value="%h(zGoto
5800: 29 22 20 2f 3e 0a 20 20 7d 65 6c 73 65 20 69 66  )" />.  }else if
5810: 28 20 7a 52 65 66 65 72 65 72 20 26 26 20 73 74  ( zReferer && st
5820: 72 6e 63 6d 70 28 67 2e 7a 42 61 73 65 55 52 4c  rncmp(g.zBaseURL
5830: 2c 20 7a 52 65 66 65 72 65 72 2c 20 73 74 72 6c  , zReferer, strl
5840: 65 6e 28 67 2e 7a 42 61 73 65 55 52 4c 29 29 3d  en(g.zBaseURL))=
5850: 3d 30 20 29 7b 0a 20 20 20 20 40 20 3c 69 6e 70  =0 ){.    @ <inp
5860: 75 74 20 74 79 70 65 3d 22 68 69 64 64 65 6e 22  ut type="hidden"
5870: 20 6e 61 6d 65 3d 22 67 22 20 76 61 6c 75 65 3d   name="g" value=
5880: 22 25 68 28 7a 52 65 66 65 72 65 72 29 22 20 2f  "%h(zReferer)" /
5890: 3e 0a 20 20 7d 0a 20 20 69 66 28 20 61 6e 6f 6e  >.  }.  if( anon
58a0: 46 6c 61 67 20 29 7b 0a 20 20 20 20 40 20 3c 69  Flag ){.    @ <i
58b0: 6e 70 75 74 20 74 79 70 65 3d 22 68 69 64 64 65  nput type="hidde
58c0: 6e 22 20 6e 61 6d 65 3d 22 61 6e 6f 6e 22 20 76  n" name="anon" v
58d0: 61 6c 75 65 3d 22 31 22 20 2f 3e 0a 20 20 7d 0a  alue="1" />.  }.
58e0: 20 20 69 66 28 20 67 2e 7a 4c 6f 67 69 6e 20 29    if( g.zLogin )
58f0: 7b 0a 20 20 20 20 40 20 3c 70 3e 43 75 72 72 65  {.    @ <p>Curre
5900: 6e 74 6c 79 20 6c 6f 67 67 65 64 20 69 6e 20 61  ntly logged in a
5910: 73 20 3c 62 3e 25 68 28 67 2e 7a 4c 6f 67 69 6e  s <b>%h(g.zLogin
5920: 29 3c 2f 62 3e 2e 0a 20 20 20 20 40 20 3c 69 6e  )</b>..    @ <in
5930: 70 75 74 20 74 79 70 65 3d 22 73 75 62 6d 69 74  put type="submit
5940: 22 20 6e 61 6d 65 3d 22 6f 75 74 22 20 76 61 6c  " name="out" val
5950: 75 65 3d 22 4c 6f 67 6f 75 74 22 3e 3c 2f 70 3e  ue="Logout"></p>
5960: 0a 20 20 20 20 40 20 3c 2f 66 6f 72 6d 3e 0a 20  .    @ </form>. 
5970: 20 7d 65 6c 73 65 7b 0a 20 20 20 20 40 20 3c 74   }else{.    @ <t
5980: 61 62 6c 65 20 63 6c 61 73 73 3d 22 6c 6f 67 69  able class="logi
5990: 6e 5f 6f 75 74 22 3e 0a 20 20 20 20 40 20 3c 74  n_out">.    @ <t
59a0: 72 3e 0a 20 20 20 20 40 20 20 20 3c 74 64 20 63  r>.    @   <td c
59b0: 6c 61 73 73 3d 22 66 6f 72 6d 5f 6c 61 62 65 6c  lass="form_label
59c0: 22 3e 55 73 65 72 20 49 44 3a 3c 2f 74 64 3e 0a  ">User ID:</td>.
59d0: 20 20 20 20 69 66 28 20 61 6e 6f 6e 46 6c 61 67      if( anonFlag
59e0: 20 29 7b 0a 20 20 20 20 20 20 40 20 3c 74 64 3e   ){.      @ <td>
59f0: 3c 69 6e 70 75 74 20 74 79 70 65 3d 22 74 65 78  <input type="tex
5a00: 74 22 20 69 64 3d 22 75 22 20 6e 61 6d 65 3d 22  t" id="u" name="
5a10: 75 22 20 76 61 6c 75 65 3d 22 61 6e 6f 6e 79 6d  u" value="anonym
5a20: 6f 75 73 22 20 73 69 7a 65 3d 22 33 30 22 3e 3c  ous" size="30"><
5a30: 2f 74 64 3e 0a 20 20 20 20 7d 65 6c 73 65 7b 0a  /td>.    }else{.
5a40: 20 20 20 20 20 20 40 20 3c 74 64 3e 3c 69 6e 70        @ <td><inp
5a50: 75 74 20 74 79 70 65 3d 22 74 65 78 74 22 20 69  ut type="text" i
5a60: 64 3d 22 75 22 20 6e 61 6d 65 3d 22 75 22 20 76  d="u" name="u" v
5a70: 61 6c 75 65 3d 22 22 20 73 69 7a 65 3d 22 33 30  alue="" size="30
5a80: 22 20 2f 3e 3c 2f 74 64 3e 0a 20 20 20 20 7d 0a  " /></td>.    }.
5a90: 20 20 20 20 40 20 3c 2f 74 72 3e 0a 20 20 20 20      @ </tr>.    
5aa0: 40 20 3c 74 72 3e 0a 20 20 20 20 40 20 20 3c 74  @ <tr>.    @  <t
5ab0: 64 20 63 6c 61 73 73 3d 22 66 6f 72 6d 5f 6c 61  d class="form_la
5ac0: 62 65 6c 22 3e 50 61 73 73 77 6f 72 64 3a 3c 2f  bel">Password:</
5ad0: 74 64 3e 0a 20 20 20 20 40 20 20 3c 74 64 3e 3c  td>.    @  <td><
5ae0: 69 6e 70 75 74 20 74 79 70 65 3d 22 70 61 73 73  input type="pass
5af0: 77 6f 72 64 22 20 69 64 3d 22 70 22 20 6e 61 6d  word" id="p" nam
5b00: 65 3d 22 70 22 20 76 61 6c 75 65 3d 22 22 20 73  e="p" value="" s
5b10: 69 7a 65 3d 22 33 30 22 20 2f 3e 3c 2f 74 64 3e  ize="30" /></td>
5b20: 0a 20 20 20 20 40 20 3c 2f 74 72 3e 0a 20 20 20  .    @ </tr>.   
5b30: 20 69 66 28 20 50 28 22 48 54 54 50 53 22 29 3d   if( P("HTTPS")=
5b40: 3d 30 20 29 7b 0a 20 20 20 20 20 20 40 20 3c 74  =0 ){.      @ <t
5b50: 72 3e 3c 74 64 20 63 6c 61 73 73 3d 22 66 6f 72  r><td class="for
5b60: 6d 5f 6c 61 62 65 6c 22 3e 57 61 72 6e 69 6e 67  m_label">Warning
5b70: 3a 3c 2f 74 64 3e 0a 20 20 20 20 20 20 40 20 3c  :</td>.      @ <
5b80: 74 64 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 27  td><span class='
5b90: 73 65 63 75 72 69 74 79 57 61 72 6e 69 6e 67 27  securityWarning'
5ba0: 3e 0a 20 20 20 20 20 20 40 20 59 6f 75 72 20 70  >.      @ Your p
5bb0: 61 73 73 77 6f 72 64 20 77 69 6c 6c 20 62 65 20  assword will be 
5bc0: 73 65 6e 74 20 69 6e 20 74 68 65 20 63 6c 65 61  sent in the clea
5bd0: 72 20 6f 76 65 72 20 61 6e 0a 20 20 20 20 20 20  r over an.      
5be0: 40 20 75 6e 65 6e 63 72 79 70 74 65 64 20 63 6f  @ unencrypted co
5bf0: 6e 6e 65 63 74 69 6f 6e 2e 0a 20 20 20 20 20 20  nnection..      
5c00: 69 66 28 20 67 2e 73 73 6c 4e 6f 74 41 76 61 69  if( g.sslNotAvai
5c10: 6c 61 62 6c 65 20 29 7b 0a 20 20 20 20 20 20 20  lable ){.       
5c20: 20 40 20 4e 6f 20 65 6e 63 72 79 70 74 65 64 20   @ No encrypted 
5c30: 63 6f 6e 6e 65 63 74 69 6f 6e 20 69 73 20 61 76  connection is av
5c40: 61 69 6c 61 62 6c 65 20 6f 6e 20 74 68 69 73 20  ailable on this 
5c50: 73 65 72 76 65 72 2e 0a 20 20 20 20 20 20 7d 65  server..      }e
5c60: 6c 73 65 7b 0a 20 20 20 20 20 20 20 20 40 20 43  lse{.        @ C
5c70: 6f 6e 73 69 64 65 72 20 6c 6f 67 67 69 6e 67 20  onsider logging 
5c80: 69 6e 20 61 74 0a 20 20 20 20 20 20 20 20 40 20  in at.        @ 
5c90: 3c 61 20 68 72 65 66 3d 27 25 73 28 67 2e 7a 48  <a href='%s(g.zH
5ca0: 74 74 70 73 55 52 4c 29 27 3e 25 68 28 67 2e 7a  ttpsURL)'>%h(g.z
5cb0: 48 74 74 70 73 55 52 4c 29 3c 2f 61 3e 20 69 6e  HttpsURL)</a> in
5cc0: 73 74 65 61 64 2e 0a 20 20 20 20 20 20 7d 0a 20  stead..      }. 
5cd0: 20 20 20 20 20 40 20 3c 2f 73 70 61 6e 3e 3c 2f       @ </span></
5ce0: 74 64 3e 3c 2f 74 72 3e 0a 20 20 20 20 7d 0a 20  td></tr>.    }. 
5cf0: 20 20 20 69 66 28 20 67 2e 7a 4c 6f 67 69 6e 3d     if( g.zLogin=
5d00: 3d 30 20 26 26 20 28 61 6e 6f 6e 46 6c 61 67 20  =0 && (anonFlag 
5d10: 7c 7c 20 7a 47 6f 74 6f 3d 3d 30 29 20 29 7b 0a  || zGoto==0) ){.
5d20: 20 20 20 20 20 20 7a 41 6e 6f 6e 50 77 20 3d 20        zAnonPw = 
5d30: 64 62 5f 74 65 78 74 28 30 2c 20 22 53 45 4c 45  db_text(0, "SELE
5d40: 43 54 20 70 77 20 46 52 4f 4d 20 75 73 65 72 22  CT pw FROM user"
5d50: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
5d60: 20 20 20 20 20 20 20 20 20 20 20 20 22 20 57 48              " WH
5d70: 45 52 45 20 6c 6f 67 69 6e 3d 27 61 6e 6f 6e 79  ERE login='anony
5d80: 6d 6f 75 73 27 22 0a 20 20 20 20 20 20 20 20 20  mous'".         
5d90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5da0: 20 20 22 20 20 20 41 4e 44 20 63 61 70 21 3d 27    "   AND cap!='
5db0: 27 22 29 3b 0a 20 20 20 20 7d 0a 20 20 20 20 40  '");.    }.    @
5dc0: 20 3c 74 72 3e 0a 20 20 20 20 40 20 20 20 3c 74   <tr>.    @   <t
5dd0: 64 3e 3c 2f 74 64 3e 0a 20 20 20 20 40 20 20 20  d></td>.    @   
5de0: 3c 74 64 3e 3c 69 6e 70 75 74 20 74 79 70 65 3d  <td><input type=
5df0: 22 73 75 62 6d 69 74 22 20 6e 61 6d 65 3d 22 69  "submit" name="i
5e00: 6e 22 20 76 61 6c 75 65 3d 22 4c 6f 67 69 6e 22  n" value="Login"
5e10: 3e 3c 2f 74 64 3e 0a 20 20 20 20 40 20 3c 2f 74  ></td>.    @ </t
5e20: 72 3e 0a 20 20 20 20 69 66 28 20 21 6e 6f 41 6e  r>.    if( !noAn
5e30: 6f 6e 20 26 26 20 6c 6f 67 69 6e 5f 73 65 6c 66  on && login_self
5e40: 5f 72 65 67 69 73 74 65 72 5f 61 76 61 69 6c 61  _register_availa
5e50: 62 6c 65 28 30 29 20 29 7b 0a 20 20 20 20 20 20  ble(0) ){.      
5e60: 40 20 3c 74 72 3e 0a 20 20 20 20 20 20 40 20 20  @ <tr>.      @  
5e70: 20 3c 74 64 3e 3c 2f 74 64 3e 0a 20 20 20 20 20   <td></td>.     
5e80: 20 40 20 20 20 3c 74 64 3e 3c 69 6e 70 75 74 20   @   <td><input 
5e90: 74 79 70 65 3d 22 73 75 62 6d 69 74 22 20 6e 61  type="submit" na
5ea0: 6d 65 3d 22 73 65 6c 66 22 20 76 61 6c 75 65 3d  me="self" value=
5eb0: 22 43 72 65 61 74 65 20 41 20 4e 65 77 20 41 63  "Create A New Ac
5ec0: 63 6f 75 6e 74 22 3e 0a 20 20 20 20 20 20 40 20  count">.      @ 
5ed0: 3c 2f 74 72 3e 0a 20 20 20 20 7d 0a 20 20 20 20  </tr>.    }.    
5ee0: 40 20 3c 2f 74 61 62 6c 65 3e 0a 20 20 20 20 69  @ </table>.    i
5ef0: 66 28 20 7a 41 6e 6f 6e 50 77 20 26 26 20 21 6e  f( zAnonPw && !n
5f00: 6f 41 6e 6f 6e 20 29 7b 0a 20 20 20 20 20 20 75  oAnon ){.      u
5f10: 6e 73 69 67 6e 65 64 20 69 6e 74 20 75 53 65 65  nsigned int uSee
5f20: 64 20 3d 20 63 61 70 74 63 68 61 5f 73 65 65 64  d = captcha_seed
5f30: 28 29 3b 0a 20 20 20 20 20 20 63 6f 6e 73 74 20  ();.      const 
5f40: 63 68 61 72 20 2a 7a 44 65 63 6f 64 65 64 20 3d  char *zDecoded =
5f50: 20 63 61 70 74 63 68 61 5f 64 65 63 6f 64 65 28   captcha_decode(
5f60: 75 53 65 65 64 29 3b 0a 20 20 20 20 20 20 69 6e  uSeed);.      in
5f70: 74 20 62 41 75 74 6f 43 61 70 74 63 68 61 20 3d  t bAutoCaptcha =
5f80: 20 64 62 5f 67 65 74 5f 62 6f 6f 6c 65 61 6e 28   db_get_boolean(
5f90: 22 61 75 74 6f 2d 63 61 70 74 63 68 61 22 2c 20  "auto-captcha", 
5fa0: 30 29 3b 0a 20 20 20 20 20 20 63 68 61 72 20 2a  0);.      char *
5fb0: 7a 43 61 70 74 63 68 61 20 3d 20 63 61 70 74 63  zCaptcha = captc
5fc0: 68 61 5f 72 65 6e 64 65 72 28 7a 44 65 63 6f 64  ha_render(zDecod
5fd0: 65 64 29 3b 0a 20 20 0a 20 20 20 20 20 20 40 20  ed);.  .      @ 
5fe0: 3c 70 3e 3c 69 6e 70 75 74 20 74 79 70 65 3d 22  <p><input type="
5ff0: 68 69 64 64 65 6e 22 20 6e 61 6d 65 3d 22 63 73  hidden" name="cs
6000: 22 20 76 61 6c 75 65 3d 22 25 75 28 75 53 65 65  " value="%u(uSee
6010: 64 29 22 20 2f 3e 0a 20 20 20 20 20 20 40 20 56  d)" />.      @ V
6020: 69 73 69 74 6f 72 73 20 6d 61 79 20 65 6e 74 65  isitors may ente
6030: 72 20 3c 62 3e 61 6e 6f 6e 79 6d 6f 75 73 3c 2f  r <b>anonymous</
6040: 62 3e 20 61 73 20 74 68 65 20 75 73 65 72 2d 49  b> as the user-I
6050: 44 20 77 69 74 68 0a 20 20 20 20 20 20 40 20 74  D with.      @ t
6060: 68 65 20 38 2d 63 68 61 72 61 63 74 65 72 20 68  he 8-character h
6070: 65 78 61 64 65 63 69 6d 61 6c 20 70 61 73 73 77  exadecimal passw
6080: 6f 72 64 20 73 68 6f 77 6e 20 62 65 6c 6f 77 3a  ord shown below:
6090: 3c 2f 70 3e 0a 20 20 20 20 20 20 40 20 3c 64 69  </p>.      @ <di
60a0: 76 20 63 6c 61 73 73 3d 22 63 61 70 74 63 68 61  v class="captcha
60b0: 22 3e 3c 74 61 62 6c 65 20 63 6c 61 73 73 3d 22  "><table class="
60c0: 63 61 70 74 63 68 61 22 3e 3c 74 72 3e 3c 74 64  captcha"><tr><td
60d0: 3e 5c 0a 20 20 20 20 20 20 40 20 3c 70 72 65 20  >\.      @ <pre 
60e0: 63 6c 61 73 73 3d 22 63 61 70 74 63 68 61 22 3e  class="captcha">
60f0: 0a 20 20 20 20 20 20 40 20 25 68 28 7a 43 61 70  .      @ %h(zCap
6100: 74 63 68 61 29 0a 20 20 20 20 20 20 40 20 3c 2f  tcha).      @ </
6110: 70 72 65 3e 3c 2f 74 64 3e 3c 2f 74 72 3e 3c 2f  pre></td></tr></
6120: 74 61 62 6c 65 3e 0a 20 20 20 20 20 20 69 66 28  table>.      if(
6130: 20 62 41 75 74 6f 43 61 70 74 63 68 61 20 29 20   bAutoCaptcha ) 
6140: 7b 0a 20 20 20 20 20 20 20 20 20 40 20 3c 69 6e  {.         @ <in
6150: 70 75 74 20 74 79 70 65 3d 22 62 75 74 74 6f 6e  put type="button
6160: 22 20 76 61 6c 75 65 3d 22 46 69 6c 6c 20 6f 75  " value="Fill ou
6170: 74 20 63 61 70 74 63 68 61 22 20 69 64 3d 27 61  t captcha" id='a
6180: 75 74 6f 66 69 6c 6c 42 75 74 74 6f 6e 27 20 5c  utofillButton' \
6190: 0a 20 20 20 20 20 20 20 20 20 40 20 64 61 74 61  .         @ data
61a0: 2d 61 66 3d 27 25 73 28 7a 44 65 63 6f 64 65 64  -af='%s(zDecoded
61b0: 29 27 20 2f 3e 0a 20 20 20 20 20 20 20 20 20 73  )' />.         s
61c0: 74 79 6c 65 5f 6c 6f 61 64 5f 6f 6e 65 5f 6a 73  tyle_load_one_js
61d0: 5f 66 69 6c 65 28 22 6c 6f 67 69 6e 2e 6a 73 22  _file("login.js"
61e0: 29 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 20  );.      }.     
61f0: 20 40 20 3c 2f 64 69 76 3e 0a 20 20 20 20 20 20   @ </div>.      
6200: 66 72 65 65 28 7a 43 61 70 74 63 68 61 29 3b 0a  free(zCaptcha);.
6210: 20 20 20 20 7d 0a 20 20 20 20 40 20 3c 2f 66 6f      }.    @ </fo
6220: 72 6d 3e 0a 20 20 7d 0a 20 20 69 66 28 20 6c 6f  rm>.  }.  if( lo
6230: 67 69 6e 5f 69 73 5f 69 6e 64 69 76 69 64 75 61  gin_is_individua
6240: 6c 28 29 20 29 7b 0a 20 20 20 20 69 66 28 20 67  l() ){.    if( g
6250: 2e 70 65 72 6d 2e 45 6d 61 69 6c 41 6c 65 72 74  .perm.EmailAlert
6260: 20 26 26 20 61 6c 65 72 74 5f 65 6e 61 62 6c 65   && alert_enable
6270: 64 28 29 20 29 7b 0a 20 20 20 20 20 20 40 20 3c  d() ){.      @ <
6280: 68 72 3e 0a 20 20 20 20 20 20 40 20 3c 70 3e 43  hr>.      @ <p>C
6290: 6f 6e 66 69 67 75 72 65 20 3c 61 20 68 72 65 66  onfigure <a href
62a0: 3d 22 25 52 2f 61 6c 65 72 74 73 22 3e 45 6d 61  ="%R/alerts">Ema
62b0: 69 6c 20 41 6c 65 72 74 73 3c 2f 61 3e 0a 20 20  il Alerts</a>.  
62c0: 20 20 20 20 40 20 66 6f 72 20 75 73 65 72 20 3c      @ for user <
62d0: 62 3e 25 68 28 67 2e 7a 4c 6f 67 69 6e 29 3c 2f  b>%h(g.zLogin)</
62e0: 62 3e 3c 2f 70 3e 0a 20 20 20 20 7d 0a 20 20 20  b></p>.    }.   
62f0: 20 69 66 28 20 67 2e 70 65 72 6d 2e 50 61 73 73   if( g.perm.Pass
6300: 77 6f 72 64 20 29 7b 0a 20 20 20 20 20 20 40 20  word ){.      @ 
6310: 3c 68 72 3e 0a 20 20 20 20 20 20 40 20 3c 70 3e  <hr>.      @ <p>
6320: 43 68 61 6e 67 65 20 50 61 73 73 77 6f 72 64 20  Change Password 
6330: 66 6f 72 20 75 73 65 72 20 3c 62 3e 25 68 28 67  for user <b>%h(g
6340: 2e 7a 4c 6f 67 69 6e 29 3c 2f 62 3e 3a 3c 2f 70  .zLogin)</b>:</p
6350: 3e 0a 20 20 20 20 20 20 66 6f 72 6d 5f 62 65 67  >.      form_beg
6360: 69 6e 28 30 2c 20 22 25 52 2f 6c 6f 67 69 6e 22  in(0, "%R/login"
6370: 29 3b 0a 20 20 20 20 20 20 40 20 3c 74 61 62 6c  );.      @ <tabl
6380: 65 3e 0a 20 20 20 20 20 20 40 20 3c 74 72 3e 3c  e>.      @ <tr><
6390: 74 64 20 63 6c 61 73 73 3d 22 66 6f 72 6d 5f 6c  td class="form_l
63a0: 61 62 65 6c 22 3e 4f 6c 64 20 50 61 73 73 77 6f  abel">Old Passwo
63b0: 72 64 3a 3c 2f 74 64 3e 0a 20 20 20 20 20 20 40  rd:</td>.      @
63c0: 20 3c 74 64 3e 3c 69 6e 70 75 74 20 74 79 70 65   <td><input type
63d0: 3d 22 70 61 73 73 77 6f 72 64 22 20 6e 61 6d 65  ="password" name
63e0: 3d 22 70 22 20 73 69 7a 65 3d 22 33 30 22 20 2f  ="p" size="30" /
63f0: 3e 3c 2f 74 64 3e 3c 2f 74 72 3e 0a 20 20 20 20  ></td></tr>.    
6400: 20 20 40 20 3c 74 72 3e 3c 74 64 20 63 6c 61 73    @ <tr><td clas
6410: 73 3d 22 66 6f 72 6d 5f 6c 61 62 65 6c 22 3e 4e  s="form_label">N
6420: 65 77 20 50 61 73 73 77 6f 72 64 3a 3c 2f 74 64  ew Password:</td
6430: 3e 0a 20 20 20 20 20 20 40 20 3c 74 64 3e 3c 69  >.      @ <td><i
6440: 6e 70 75 74 20 74 79 70 65 3d 22 70 61 73 73 77  nput type="passw
6450: 6f 72 64 22 20 6e 61 6d 65 3d 22 6e 31 22 20 73  ord" name="n1" s
6460: 69 7a 65 3d 22 33 30 22 20 2f 3e 3c 2f 74 64 3e  ize="30" /></td>
6470: 3c 2f 74 72 3e 0a 20 20 20 20 20 20 40 20 3c 74  </tr>.      @ <t
6480: 72 3e 3c 74 64 20 63 6c 61 73 73 3d 22 66 6f 72  r><td class="for
6490: 6d 5f 6c 61 62 65 6c 22 3e 52 65 70 65 61 74 20  m_label">Repeat 
64a0: 4e 65 77 20 50 61 73 73 77 6f 72 64 3a 3c 2f 74  New Password:</t
64b0: 64 3e 0a 20 20 20 20 20 20 40 20 3c 74 64 3e 3c  d>.      @ <td><
64c0: 69 6e 70 75 74 20 74 79 70 65 3d 22 70 61 73 73  input type="pass
64d0: 77 6f 72 64 22 20 6e 61 6d 65 3d 22 6e 32 22 20  word" name="n2" 
64e0: 73 69 7a 65 3d 22 33 30 22 20 2f 3e 3c 2f 74 64  size="30" /></td
64f0: 3e 3c 2f 74 72 3e 0a 20 20 20 20 20 20 40 20 3c  ></tr>.      @ <
6500: 74 72 3e 3c 74 64 3e 3c 2f 74 64 3e 0a 20 20 20  tr><td></td>.   
6510: 20 20 20 40 20 3c 74 64 3e 3c 69 6e 70 75 74 20     @ <td><input 
6520: 74 79 70 65 3d 22 73 75 62 6d 69 74 22 20 76 61  type="submit" va
6530: 6c 75 65 3d 22 43 68 61 6e 67 65 20 50 61 73 73  lue="Change Pass
6540: 77 6f 72 64 22 20 2f 3e 3c 2f 74 64 3e 3c 2f 74  word" /></td></t
6550: 72 3e 0a 20 20 20 20 20 20 40 20 3c 2f 74 61 62  r>.      @ </tab
6560: 6c 65 3e 0a 20 20 20 20 20 20 40 20 3c 2f 66 6f  le>.      @ </fo
6570: 72 6d 3e 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20  rm>.    }.  }.  
6580: 73 74 79 6c 65 5f 66 6f 6f 74 65 72 28 29 3b 0a  style_footer();.
6590: 7d 0a 0a 2f 2a 0a 2a 2a 20 41 74 74 65 6d 70 74  }../*.** Attempt
65a0: 20 74 6f 20 66 69 6e 64 20 6c 6f 67 69 6e 20 63   to find login c
65b0: 72 65 64 65 6e 74 69 61 6c 73 20 66 6f 72 20 75  redentials for u
65c0: 73 65 72 20 7a 4c 6f 67 69 6e 20 6f 6e 20 61 20  ser zLogin on a 
65d0: 70 65 65 72 20 72 65 70 6f 73 69 74 6f 72 79 0a  peer repository.
65e0: 2a 2a 20 77 69 74 68 20 70 72 6f 6a 65 63 74 20  ** with project 
65f0: 63 6f 64 65 20 7a 43 6f 64 65 2e 20 20 54 72 61  code zCode.  Tra
6600: 6e 73 66 65 72 20 74 68 6f 73 65 20 63 72 65 64  nsfer those cred
6610: 65 6e 74 69 61 6c 73 20 74 6f 20 74 68 65 20 6c  entials to the l
6620: 6f 63 61 6c 0a 2a 2a 20 72 65 70 6f 73 69 74 6f  ocal.** reposito
6630: 72 79 2e 0a 2a 2a 0a 2a 2a 20 52 65 74 75 72 6e  ry..**.** Return
6640: 20 74 72 75 65 20 69 66 20 61 20 74 72 61 6e 73   true if a trans
6650: 66 65 72 20 77 61 73 20 6d 61 64 65 20 61 6e 64  fer was made and
6660: 20 66 61 6c 73 65 20 69 66 20 6e 6f 74 2e 0a 2a   false if not..*
6670: 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 6c 6f 67  /.static int log
6680: 69 6e 5f 74 72 61 6e 73 66 65 72 5f 63 72 65 64  in_transfer_cred
6690: 65 6e 74 69 61 6c 73 28 0a 20 20 63 6f 6e 73 74  entials(.  const
66a0: 20 63 68 61 72 20 2a 7a 4c 6f 67 69 6e 2c 20 20   char *zLogin,  
66b0: 20 20 20 20 20 20 20 20 2f 2a 20 4c 6f 67 69 6e          /* Login
66c0: 20 77 65 20 61 72 65 20 6c 6f 6f 6b 69 6e 67 20   we are looking 
66d0: 66 6f 72 20 2a 2f 0a 20 20 63 6f 6e 73 74 20 63  for */.  const c
66e0: 68 61 72 20 2a 7a 43 6f 64 65 2c 20 20 20 20 20  har *zCode,     
66f0: 20 20 20 20 20 20 2f 2a 20 50 72 6f 6a 65 63 74        /* Project
6700: 20 63 6f 64 65 20 6f 66 20 70 65 65 72 20 72 65   code of peer re
6710: 70 6f 73 69 74 6f 72 79 20 2a 2f 0a 20 20 63 6f  pository */.  co
6720: 6e 73 74 20 63 68 61 72 20 2a 7a 48 61 73 68 2c  nst char *zHash,
6730: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 48 41             /* HA
6740: 53 48 20 66 72 6f 6d 20 6c 6f 67 69 6e 20 63 6f  SH from login co
6750: 6f 6b 69 65 20 48 41 53 48 2f 43 4f 44 45 2f 4c  okie HASH/CODE/L
6760: 4f 47 49 4e 20 2a 2f 0a 20 20 63 6f 6e 73 74 20  OGIN */.  const 
6770: 63 68 61 72 20 2a 7a 52 65 6d 6f 74 65 41 64 64  char *zRemoteAdd
6780: 72 20 20 20 20 20 20 2f 2a 20 52 65 71 75 65 73  r      /* Reques
6790: 74 20 63 6f 6d 65 73 20 66 72 6f 6d 20 68 65 72  t comes from her
67a0: 65 20 2a 2f 0a 29 7b 0a 20 20 73 71 6c 69 74 65  e */.){.  sqlite
67b0: 33 20 2a 70 4f 74 68 65 72 20 3d 20 30 3b 20 20  3 *pOther = 0;  
67c0: 20 20 20 20 20 20 20 2f 2a 20 54 68 65 20 6f 74         /* The ot
67d0: 68 65 72 20 72 65 70 6f 73 69 74 6f 72 79 20 2a  her repository *
67e0: 2f 0a 20 20 73 71 6c 69 74 65 33 5f 73 74 6d 74  /.  sqlite3_stmt
67f0: 20 2a 70 53 74 6d 74 3b 20 20 20 20 20 20 20 20   *pStmt;        
6800: 20 2f 2a 20 51 75 65 72 79 20 61 67 61 69 6e 73   /* Query agains
6810: 74 20 74 68 65 20 6f 74 68 65 72 20 72 65 70 6f  t the other repo
6820: 73 69 74 6f 72 79 20 2a 2f 0a 20 20 63 68 61 72  sitory */.  char
6830: 20 2a 7a 53 51 4c 3b 20 20 20 20 20 20 20 20 20   *zSQL;         
6840: 20 20 20 20 20 20 20 20 20 2f 2a 20 53 51 4c 20           /* SQL 
6850: 6f 66 20 74 68 65 20 71 75 65 72 79 20 61 67 61  of the query aga
6860: 69 6e 73 74 20 6f 74 68 65 72 20 72 65 70 6f 20  inst other repo 
6870: 2a 2f 0a 20 20 63 68 61 72 20 2a 7a 4f 74 68 65  */.  char *zOthe
6880: 72 52 65 70 6f 3b 20 20 20 20 20 20 20 20 20 20  rRepo;          
6890: 20 20 2f 2a 20 46 69 6c 65 6e 61 6d 65 20 6f 66    /* Filename of
68a0: 20 74 68 65 20 6f 74 68 65 72 20 72 65 70 6f 73   the other repos
68b0: 69 74 6f 72 79 20 2a 2f 0a 20 20 69 6e 74 20 72  itory */.  int r
68c0: 63 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  c;              
68d0: 20 20 20 20 20 20 20 20 2f 2a 20 52 65 73 75 6c          /* Resul
68e0: 74 20 63 6f 64 65 20 66 72 6f 6d 20 53 51 4c 69  t code from SQLi
68f0: 74 65 20 6c 69 62 72 61 72 79 20 66 75 6e 63 74  te library funct
6900: 69 6f 6e 73 20 2a 2f 0a 20 20 69 6e 74 20 6e 58  ions */.  int nX
6910: 66 65 72 20 3d 20 30 3b 20 20 20 20 20 20 20 20  fer = 0;        
6920: 20 20 20 20 20 20 20 2f 2a 20 4e 75 6d 62 65 72         /* Number
6930: 20 6f 66 20 63 72 65 64 65 6e 74 69 61 6c 73 20   of credentials 
6940: 74 72 61 6e 73 66 65 72 72 65 64 20 2a 2f 0a 0a  transferred */..
6950: 20 20 7a 4f 74 68 65 72 52 65 70 6f 20 3d 20 64    zOtherRepo = d
6960: 62 5f 74 65 78 74 28 30 2c 0a 20 20 20 20 20 20  b_text(0,.      
6970: 20 22 53 45 4c 45 43 54 20 76 61 6c 75 65 20 46   "SELECT value F
6980: 52 4f 4d 20 63 6f 6e 66 69 67 20 57 48 45 52 45  ROM config WHERE
6990: 20 6e 61 6d 65 3d 27 70 65 65 72 2d 72 65 70 6f   name='peer-repo
69a0: 2d 25 71 27 22 2c 0a 20 20 20 20 20 20 20 7a 43  -%q'",.       zC
69b0: 6f 64 65 0a 20 20 29 3b 0a 20 20 69 66 28 20 7a  ode.  );.  if( z
69c0: 4f 74 68 65 72 52 65 70 6f 3d 3d 30 20 29 20 72  OtherRepo==0 ) r
69d0: 65 74 75 72 6e 20 30 3b 20 20 2f 2a 20 4e 6f 20  eturn 0;  /* No 
69e0: 73 75 63 68 20 70 65 65 72 20 72 65 70 6f 73 69  such peer reposi
69f0: 74 6f 72 79 20 2a 2f 0a 0a 20 20 72 63 20 3d 20  tory */..  rc = 
6a00: 73 71 6c 69 74 65 33 5f 6f 70 65 6e 5f 76 32 28  sqlite3_open_v2(
6a10: 0a 20 20 20 20 20 20 20 7a 4f 74 68 65 72 52 65  .       zOtherRe
6a20: 70 6f 2c 20 26 70 4f 74 68 65 72 2c 0a 20 20 20  po, &pOther,.   
6a30: 20 20 20 20 53 51 4c 49 54 45 5f 4f 50 45 4e 5f      SQLITE_OPEN_
6a40: 52 45 41 44 57 52 49 54 45 20 7c 20 53 51 4c 49  READWRITE | SQLI
6a50: 54 45 5f 4f 50 45 4e 5f 43 52 45 41 54 45 2c 0a  TE_OPEN_CREATE,.
6a60: 20 20 20 20 20 20 20 67 2e 7a 56 66 73 4e 61 6d         g.zVfsNam
6a70: 65 0a 20 20 29 3b 0a 20 20 69 66 28 20 72 63 3d  e.  );.  if( rc=
6a80: 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20  =SQLITE_OK ){.  
6a90: 20 20 73 71 6c 69 74 65 33 5f 63 72 65 61 74 65    sqlite3_create
6aa0: 5f 66 75 6e 63 74 69 6f 6e 28 70 4f 74 68 65 72  _function(pOther
6ab0: 2c 22 6e 6f 77 22 2c 30 2c 53 51 4c 49 54 45 5f  ,"now",0,SQLITE_
6ac0: 55 54 46 38 2c 30 2c 64 62 5f 6e 6f 77 5f 66 75  UTF8,0,db_now_fu
6ad0: 6e 63 74 69 6f 6e 2c 30 2c 30 29 3b 0a 20 20 20  nction,0,0);.   
6ae0: 20 73 71 6c 69 74 65 33 5f 63 72 65 61 74 65 5f   sqlite3_create_
6af0: 66 75 6e 63 74 69 6f 6e 28 70 4f 74 68 65 72 2c  function(pOther,
6b00: 20 22 63 6f 6e 73 74 61 6e 74 5f 74 69 6d 65 5f   "constant_time_
6b10: 63 6d 70 22 2c 20 32 2c 20 53 51 4c 49 54 45 5f  cmp", 2, SQLITE_
6b20: 55 54 46 38 2c 20 30 2c 0a 20 20 20 20 20 20 20  UTF8, 0,.       
6b30: 20 20 20 20 20 20 20 20 20 20 20 63 6f 6e 73 74             const
6b40: 61 6e 74 5f 74 69 6d 65 5f 63 6d 70 5f 66 75 6e  ant_time_cmp_fun
6b50: 63 74 69 6f 6e 2c 20 30 2c 20 30 29 3b 0a 20 20  ction, 0, 0);.  
6b60: 20 20 73 71 6c 69 74 65 33 5f 62 75 73 79 5f 74    sqlite3_busy_t
6b70: 69 6d 65 6f 75 74 28 70 4f 74 68 65 72 2c 20 35  imeout(pOther, 5
6b80: 30 30 30 29 3b 0a 20 20 20 20 7a 53 51 4c 20 3d  000);.    zSQL =
6b90: 20 6d 70 72 69 6e 74 66 28 0a 20 20 20 20 20 20   mprintf(.      
6ba0: 22 53 45 4c 45 43 54 20 63 65 78 70 69 72 65 20  "SELECT cexpire 
6bb0: 46 52 4f 4d 20 75 73 65 72 22 0a 20 20 20 20 20  FROM user".     
6bc0: 20 22 20 57 48 45 52 45 20 6c 6f 67 69 6e 3d 25   " WHERE login=%
6bd0: 51 22 0a 20 20 20 20 20 20 22 20 20 20 41 4e 44  Q".      "   AND
6be0: 20 69 70 61 64 64 72 3d 25 51 22 0a 20 20 20 20   ipaddr=%Q".    
6bf0: 20 20 22 20 20 20 41 4e 44 20 6c 65 6e 67 74 68    "   AND length
6c00: 28 63 61 70 29 3e 30 22 0a 20 20 20 20 20 20 22  (cap)>0".      "
6c10: 20 20 20 41 4e 44 20 6c 65 6e 67 74 68 28 70 77     AND length(pw
6c20: 29 3e 30 22 0a 20 20 20 20 20 20 22 20 20 20 41  )>0".      "   A
6c30: 4e 44 20 63 65 78 70 69 72 65 3e 6a 75 6c 69 61  ND cexpire>julia
6c40: 6e 64 61 79 28 27 6e 6f 77 27 29 22 0a 20 20 20  nday('now')".   
6c50: 20 20 20 22 20 20 20 41 4e 44 20 63 6f 6e 73 74     "   AND const
6c60: 61 6e 74 5f 74 69 6d 65 5f 63 6d 70 28 63 6f 6f  ant_time_cmp(coo
6c70: 6b 69 65 2c 25 51 29 3d 30 22 2c 0a 20 20 20 20  kie,%Q)=0",.    
6c80: 20 20 7a 4c 6f 67 69 6e 2c 20 7a 52 65 6d 6f 74    zLogin, zRemot
6c90: 65 41 64 64 72 2c 20 7a 48 61 73 68 0a 20 20 20  eAddr, zHash.   
6ca0: 20 29 3b 0a 20 20 20 20 70 53 74 6d 74 20 3d 20   );.    pStmt = 
6cb0: 30 3b 0a 20 20 20 20 72 63 20 3d 20 73 71 6c 69  0;.    rc = sqli
6cc0: 74 65 33 5f 70 72 65 70 61 72 65 5f 76 32 28 70  te3_prepare_v2(p
6cd0: 4f 74 68 65 72 2c 20 7a 53 51 4c 2c 20 2d 31 2c  Other, zSQL, -1,
6ce0: 20 26 70 53 74 6d 74 2c 20 30 29 3b 0a 20 20 20   &pStmt, 0);.   
6cf0: 20 69 66 28 20 72 63 3d 3d 53 51 4c 49 54 45 5f   if( rc==SQLITE_
6d00: 4f 4b 20 26 26 20 73 71 6c 69 74 65 33 5f 73 74  OK && sqlite3_st
6d10: 65 70 28 70 53 74 6d 74 29 3d 3d 53 51 4c 49 54  ep(pStmt)==SQLIT
6d20: 45 5f 52 4f 57 20 29 7b 0a 20 20 20 20 20 20 64  E_ROW ){.      d
6d30: 62 5f 6d 75 6c 74 69 5f 65 78 65 63 28 0a 20 20  b_multi_exec(.  
6d40: 20 20 20 20 20 20 22 55 50 44 41 54 45 20 75 73        "UPDATE us
6d50: 65 72 20 53 45 54 20 63 6f 6f 6b 69 65 3d 25 51  er SET cookie=%Q
6d60: 2c 20 69 70 61 64 64 72 3d 25 51 2c 20 63 65 78  , ipaddr=%Q, cex
6d70: 70 69 72 65 3d 25 2e 31 37 67 22 0a 20 20 20 20  pire=%.17g".    
6d80: 20 20 20 20 22 20 57 48 45 52 45 20 6c 6f 67 69      " WHERE logi
6d90: 6e 3d 25 51 22 2c 0a 20 20 20 20 20 20 20 20 7a  n=%Q",.        z
6da0: 48 61 73 68 2c 20 7a 52 65 6d 6f 74 65 41 64 64  Hash, zRemoteAdd
6db0: 72 2c 0a 20 20 20 20 20 20 20 20 73 71 6c 69 74  r,.        sqlit
6dc0: 65 33 5f 63 6f 6c 75 6d 6e 5f 64 6f 75 62 6c 65  e3_column_double
6dd0: 28 70 53 74 6d 74 2c 20 30 29 2c 20 7a 4c 6f 67  (pStmt, 0), zLog
6de0: 69 6e 0a 20 20 20 20 20 20 29 3b 0a 20 20 20 20  in.      );.    
6df0: 20 20 6e 58 66 65 72 2b 2b 3b 0a 20 20 20 20 7d    nXfer++;.    }
6e00: 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 66 69 6e  .    sqlite3_fin
6e10: 61 6c 69 7a 65 28 70 53 74 6d 74 29 3b 0a 20 20  alize(pStmt);.  
6e20: 7d 0a 20 20 73 71 6c 69 74 65 33 5f 63 6c 6f 73  }.  sqlite3_clos
6e30: 65 28 70 4f 74 68 65 72 29 3b 0a 20 20 66 6f 73  e(pOther);.  fos
6e40: 73 69 6c 5f 66 72 65 65 28 7a 4f 74 68 65 72 52  sil_free(zOtherR
6e50: 65 70 6f 29 3b 0a 20 20 72 65 74 75 72 6e 20 6e  epo);.  return n
6e60: 58 66 65 72 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 52  Xfer;.}../*.** R
6e70: 65 74 75 72 6e 20 54 52 55 45 20 69 66 20 7a 4c  eturn TRUE if zL
6e80: 6f 67 69 6e 20 69 73 20 6f 6e 65 20 6f 66 20 74  ogin is one of t
6e90: 68 65 20 73 70 65 63 69 61 6c 20 75 73 65 72 6e  he special usern
6ea0: 61 6d 65 73 0a 2a 2f 0a 69 6e 74 20 6c 6f 67 69  ames.*/.int logi
6eb0: 6e 5f 69 73 5f 73 70 65 63 69 61 6c 28 63 6f 6e  n_is_special(con
6ec0: 73 74 20 63 68 61 72 20 2a 7a 4c 6f 67 69 6e 29  st char *zLogin)
6ed0: 7b 0a 20 20 69 66 28 20 66 6f 73 73 69 6c 5f 73  {.  if( fossil_s
6ee0: 74 72 63 6d 70 28 7a 4c 6f 67 69 6e 2c 20 22 61  trcmp(zLogin, "a
6ef0: 6e 6f 6e 79 6d 6f 75 73 22 29 3d 3d 30 20 29 20  nonymous")==0 ) 
6f00: 72 65 74 75 72 6e 20 31 3b 0a 20 20 69 66 28 20  return 1;.  if( 
6f10: 66 6f 73 73 69 6c 5f 73 74 72 63 6d 70 28 7a 4c  fossil_strcmp(zL
6f20: 6f 67 69 6e 2c 20 22 6e 6f 62 6f 64 79 22 29 3d  ogin, "nobody")=
6f30: 3d 30 20 29 20 72 65 74 75 72 6e 20 31 3b 0a 20  =0 ) return 1;. 
6f40: 20 69 66 28 20 66 6f 73 73 69 6c 5f 73 74 72 63   if( fossil_strc
6f50: 6d 70 28 7a 4c 6f 67 69 6e 2c 20 22 64 65 76 65  mp(zLogin, "deve
6f60: 6c 6f 70 65 72 22 29 3d 3d 30 20 29 20 72 65 74  loper")==0 ) ret
6f70: 75 72 6e 20 31 3b 0a 20 20 69 66 28 20 66 6f 73  urn 1;.  if( fos
6f80: 73 69 6c 5f 73 74 72 63 6d 70 28 7a 4c 6f 67 69  sil_strcmp(zLogi
6f90: 6e 2c 20 22 72 65 61 64 65 72 22 29 3d 3d 30 20  n, "reader")==0 
6fa0: 29 20 72 65 74 75 72 6e 20 31 3b 0a 20 20 72 65  ) return 1;.  re
6fb0: 74 75 72 6e 20 30 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a  turn 0;.}../*.**
6fc0: 20 4c 6f 6f 6b 75 70 20 74 68 65 20 75 69 64 20   Lookup the uid 
6fd0: 66 6f 72 20 61 20 6e 6f 6e 2d 62 75 69 6c 74 2d  for a non-built-
6fe0: 69 6e 20 75 73 65 72 20 77 69 74 68 20 7a 4c 6f  in user with zLo
6ff0: 67 69 6e 20 61 6e 64 20 7a 43 6f 6f 6b 69 65 20  gin and zCookie 
7000: 61 6e 64 0a 2a 2a 20 7a 52 65 6d 6f 74 65 41 64  and.** zRemoteAd
7010: 64 72 2e 20 20 52 65 74 75 72 6e 20 30 20 69 66  dr.  Return 0 if
7020: 20 6e 6f 74 20 66 6f 75 6e 64 2e 0a 2a 2a 0a 2a   not found..**.*
7030: 2a 20 4e 6f 74 65 20 74 68 61 74 20 74 68 69 73  * Note that this
7040: 20 6f 6e 6c 79 20 73 65 61 72 63 68 65 73 20 66   only searches f
7050: 6f 72 20 6c 6f 67 67 65 64 2d 69 6e 20 65 6e 74  or logged-in ent
7060: 72 69 65 73 20 77 69 74 68 20 6d 61 74 63 68 69  ries with matchi
7070: 6e 67 0a 2a 2a 20 7a 43 6f 6f 6b 69 65 20 28 64  ng.** zCookie (d
7080: 62 3a 20 75 73 65 72 2e 63 6f 6f 6b 69 65 29 20  b: user.cookie) 
7090: 61 6e 64 20 7a 52 65 6d 6f 74 65 41 64 64 72 20  and zRemoteAddr 
70a0: 28 64 62 3a 20 75 73 65 72 2e 69 70 61 64 64 72  (db: user.ipaddr
70b0: 29 0a 2a 2a 20 65 6e 74 72 69 65 73 2e 0a 2a 2f  ).** entries..*/
70c0: 0a 73 74 61 74 69 63 20 69 6e 74 20 6c 6f 67 69  .static int logi
70d0: 6e 5f 66 69 6e 64 5f 75 73 65 72 28 0a 20 20 63  n_find_user(.  c
70e0: 6f 6e 73 74 20 63 68 61 72 20 2a 7a 4c 6f 67 69  onst char *zLogi
70f0: 6e 2c 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a  n,            /*
7100: 20 55 73 65 72 20 6e 61 6d 65 20 2a 2f 0a 20 20   User name */.  
7110: 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 43 6f 6f  const char *zCoo
7120: 6b 69 65 2c 20 20 20 20 20 20 20 20 20 20 20 2f  kie,           /
7130: 2a 20 4c 6f 67 69 6e 20 63 6f 6f 6b 69 65 20 76  * Login cookie v
7140: 61 6c 75 65 20 2a 2f 0a 20 20 63 6f 6e 73 74 20  alue */.  const 
7150: 63 68 61 72 20 2a 7a 52 65 6d 6f 74 65 41 64 64  char *zRemoteAdd
7160: 72 20 20 20 20 20 20 20 20 2f 2a 20 41 62 62 72  r        /* Abbr
7170: 65 76 69 61 74 65 64 20 49 50 20 61 64 64 72 65  eviated IP addre
7180: 73 73 20 66 6f 72 20 76 61 6c 69 64 20 6c 6f 67  ss for valid log
7190: 69 6e 20 2a 2f 0a 29 7b 0a 20 20 69 6e 74 20 75  in */.){.  int u
71a0: 69 64 3b 0a 20 20 69 66 28 20 6c 6f 67 69 6e 5f  id;.  if( login_
71b0: 69 73 5f 73 70 65 63 69 61 6c 28 7a 4c 6f 67 69  is_special(zLogi
71c0: 6e 29 20 29 20 72 65 74 75 72 6e 20 30 3b 0a 20  n) ) return 0;. 
71d0: 20 75 69 64 20 3d 20 64 62 5f 69 6e 74 28 30 2c   uid = db_int(0,
71e0: 0a 20 20 20 20 22 53 45 4c 45 43 54 20 75 69 64  .    "SELECT uid
71f0: 20 46 52 4f 4d 20 75 73 65 72 22 0a 20 20 20 20   FROM user".    
7200: 22 20 57 48 45 52 45 20 6c 6f 67 69 6e 3d 25 51  " WHERE login=%Q
7210: 22 0a 20 20 20 20 22 20 20 20 41 4e 44 20 69 70  ".    "   AND ip
7220: 61 64 64 72 3d 25 51 22 0a 20 20 20 20 22 20 20  addr=%Q".    "  
7230: 20 41 4e 44 20 63 65 78 70 69 72 65 3e 6a 75 6c   AND cexpire>jul
7240: 69 61 6e 64 61 79 28 27 6e 6f 77 27 29 22 0a 20  ianday('now')". 
7250: 20 20 20 22 20 20 20 41 4e 44 20 6c 65 6e 67 74     "   AND lengt
7260: 68 28 63 61 70 29 3e 30 22 0a 20 20 20 20 22 20  h(cap)>0".    " 
7270: 20 20 41 4e 44 20 6c 65 6e 67 74 68 28 70 77 29    AND length(pw)
7280: 3e 30 22 0a 20 20 20 20 22 20 20 20 41 4e 44 20  >0".    "   AND 
7290: 63 6f 6e 73 74 61 6e 74 5f 74 69 6d 65 5f 63 6d  constant_time_cm
72a0: 70 28 63 6f 6f 6b 69 65 2c 25 51 29 3d 30 22 2c  p(cookie,%Q)=0",
72b0: 0a 20 20 20 20 7a 4c 6f 67 69 6e 2c 20 7a 52 65  .    zLogin, zRe
72c0: 6d 6f 74 65 41 64 64 72 2c 20 7a 43 6f 6f 6b 69  moteAddr, zCooki
72d0: 65 0a 20 20 29 3b 0a 20 20 72 65 74 75 72 6e 20  e.  );.  return 
72e0: 75 69 64 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 41 74  uid;.}../*.** At
72f0: 74 65 6d 70 74 20 74 6f 20 75 73 65 20 42 61 73  tempt to use Bas
7300: 69 63 20 41 75 74 68 65 6e 74 69 63 61 74 69 6f  ic Authenticatio
7310: 6e 20 74 6f 20 65 73 74 61 62 6c 69 73 68 20 74  n to establish t
7320: 68 65 20 75 73 65 72 2e 20 20 52 65 74 75 72 6e  he user.  Return
7330: 20 74 68 65 0a 2a 2a 20 28 6e 6f 6e 2d 7a 65 72   the.** (non-zer
7340: 6f 29 20 75 69 64 20 69 66 20 73 75 63 63 65 73  o) uid if succes
7350: 73 66 75 6c 2e 20 20 52 65 74 75 72 6e 20 30 20  sful.  Return 0 
7360: 69 66 20 69 74 20 64 6f 65 73 20 6e 6f 74 20 77  if it does not w
7370: 6f 72 6b 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69  ork..*/.static i
7380: 6e 74 20 6c 6f 67 69 6e 5f 62 61 73 69 63 5f 61  nt login_basic_a
7390: 75 74 68 65 6e 74 69 63 61 74 69 6f 6e 28 63 6f  uthentication(co
73a0: 6e 73 74 20 63 68 61 72 20 2a 7a 49 70 41 64 64  nst char *zIpAdd
73b0: 72 29 7b 0a 20 20 63 6f 6e 73 74 20 63 68 61 72  r){.  const char
73c0: 20 2a 7a 41 75 74 68 20 3d 20 50 44 28 22 48 54   *zAuth = PD("HT
73d0: 54 50 5f 41 55 54 48 4f 52 49 5a 41 54 49 4f 4e  TP_AUTHORIZATION
73e0: 22 2c 20 30 29 3b 0a 20 20 69 6e 74 20 69 3b 0a  ", 0);.  int i;.
73f0: 20 20 69 6e 74 20 75 69 64 20 3d 20 30 3b 0a 20    int uid = 0;. 
7400: 20 69 6e 74 20 6e 44 65 63 6f 64 65 20 3d 20 30   int nDecode = 0
7410: 3b 0a 20 20 63 68 61 72 20 2a 7a 44 65 63 6f 64  ;.  char *zDecod
7420: 65 20 3d 20 30 3b 0a 20 20 63 6f 6e 73 74 20 63  e = 0;.  const c
7430: 68 61 72 20 2a 7a 55 73 65 72 6e 61 6d 65 20 3d  har *zUsername =
7440: 20 30 3b 0a 20 20 63 6f 6e 73 74 20 63 68 61 72   0;.  const char
7450: 20 2a 7a 50 61 73 73 77 64 20 3d 20 30 3b 0a 0a   *zPasswd = 0;..
7460: 20 20 69 66 28 20 7a 41 75 74 68 3d 3d 30 20 29    if( zAuth==0 )
7470: 20 72 65 74 75 72 6e 20 30 3b 20 20 20 20 20 20   return 0;      
7480: 20 20 20 20 20 20 20 2f 2a 20 46 61 69 6c 3a 20         /* Fail: 
7490: 4e 6f 20 41 75 74 68 65 6e 74 69 63 61 74 69 6f  No Authenticatio
74a0: 6e 3a 20 68 65 61 64 65 72 20 2a 2f 0a 20 20 77  n: header */.  w
74b0: 68 69 6c 65 28 20 66 6f 73 73 69 6c 5f 69 73 73  hile( fossil_iss
74c0: 70 61 63 65 28 7a 41 75 74 68 5b 30 5d 29 20 29  pace(zAuth[0]) )
74d0: 20 7a 41 75 74 68 2b 2b 3b 20 20 2f 2a 20 53 6b   zAuth++;  /* Sk
74e0: 69 70 20 6c 65 61 64 69 6e 67 20 77 68 69 74 65  ip leading white
74f0: 73 70 61 63 65 20 2a 2f 0a 20 20 69 66 28 20 73  space */.  if( s
7500: 74 72 6e 63 6d 70 28 7a 41 75 74 68 2c 20 22 42  trncmp(zAuth, "B
7510: 61 73 69 63 20 22 2c 20 36 29 21 3d 30 20 29 7b  asic ", 6)!=0 ){
7520: 0a 20 20 20 20 72 65 74 75 72 6e 20 30 3b 20 20  .    return 0;  
7530: 2f 2a 20 46 61 69 6c 3a 20 4e 6f 74 20 42 61 73  /* Fail: Not Bas
7540: 69 63 20 41 75 74 68 65 6e 74 69 63 61 74 69 6f  ic Authenticatio
7550: 6e 20 2a 2f 0a 20 20 7d 0a 0a 20 20 2f 2a 20 50  n */.  }..  /* P
7560: 61 72 73 65 20 6f 75 74 20 74 68 65 20 75 73 65  arse out the use
7570: 72 6e 61 6d 65 20 61 6e 64 20 70 61 73 73 77 6f  rname and passwo
7580: 72 64 2c 20 73 65 70 61 72 61 74 65 64 20 62 79  rd, separated by
7590: 20 61 20 22 3a 22 20 2a 2f 0a 20 20 7a 41 75 74   a ":" */.  zAut
75a0: 68 20 2b 3d 20 36 3b 0a 20 20 77 68 69 6c 65 28  h += 6;.  while(
75b0: 20 66 6f 73 73 69 6c 5f 69 73 73 70 61 63 65 28   fossil_isspace(
75c0: 7a 41 75 74 68 5b 30 5d 29 20 29 20 7a 41 75 74  zAuth[0]) ) zAut
75d0: 68 2b 2b 3b 0a 20 20 7a 44 65 63 6f 64 65 20 3d  h++;.  zDecode =
75e0: 20 64 65 63 6f 64 65 36 34 28 7a 41 75 74 68 2c   decode64(zAuth,
75f0: 20 26 6e 44 65 63 6f 64 65 29 3b 0a 0a 20 20 66   &nDecode);..  f
7600: 6f 72 28 69 3d 30 3b 20 7a 44 65 63 6f 64 65 5b  or(i=0; zDecode[
7610: 69 5d 20 26 26 20 7a 44 65 63 6f 64 65 5b 69 5d  i] && zDecode[i]
7620: 21 3d 27 3a 27 3b 20 69 2b 2b 29 7b 7d 0a 20 20  !=':'; i++){}.  
7630: 69 66 28 20 7a 44 65 63 6f 64 65 5b 69 5d 20 29  if( zDecode[i] )
7640: 7b 0a 20 20 20 20 7a 44 65 63 6f 64 65 5b 69 5d  {.    zDecode[i]
7650: 20 3d 20 30 3b 0a 20 20 20 20 7a 55 73 65 72 6e   = 0;.    zUsern
7660: 61 6d 65 20 3d 20 7a 44 65 63 6f 64 65 3b 0a 20  ame = zDecode;. 
7670: 20 20 20 7a 50 61 73 73 77 64 20 3d 20 26 7a 44     zPasswd = &zD
7680: 65 63 6f 64 65 5b 69 2b 31 5d 3b 0a 0a 20 20 20  ecode[i+1];..   
7690: 20 2f 2a 20 41 74 74 65 6d 70 74 69 6e 67 20 74   /* Attempting t
76a0: 6f 20 6c 6f 67 20 69 6e 20 61 73 20 74 68 65 20  o log in as the 
76b0: 75 73 65 72 20 70 72 6f 76 69 64 65 64 20 62 79  user provided by
76c0: 20 48 54 54 50 0a 20 20 20 20 2a 2a 20 62 61 73   HTTP.    ** bas
76d0: 69 63 20 61 75 74 68 0a 20 20 20 20 2a 2f 0a 20  ic auth.    */. 
76e0: 20 20 20 75 69 64 20 3d 20 6c 6f 67 69 6e 5f 73     uid = login_s
76f0: 65 61 72 63 68 5f 75 69 64 28 26 7a 55 73 65 72  earch_uid(&zUser
7700: 6e 61 6d 65 2c 20 7a 50 61 73 73 77 64 29 3b 0a  name, zPasswd);.
7710: 20 20 20 20 69 66 28 20 75 69 64 3e 30 20 29 7b      if( uid>0 ){
7720: 0a 20 20 20 20 20 20 72 65 63 6f 72 64 5f 6c 6f  .      record_lo
7730: 67 69 6e 5f 61 74 74 65 6d 70 74 28 7a 55 73 65  gin_attempt(zUse
7740: 72 6e 61 6d 65 2c 20 7a 49 70 41 64 64 72 2c 20  rname, zIpAddr, 
7750: 31 29 3b 0a 20 20 20 20 7d 65 6c 73 65 7b 0a 20  1);.    }else{. 
7760: 20 20 20 20 20 72 65 63 6f 72 64 5f 6c 6f 67 69       record_logi
7770: 6e 5f 61 74 74 65 6d 70 74 28 7a 55 73 65 72 6e  n_attempt(zUsern
7780: 61 6d 65 2c 20 7a 49 70 41 64 64 72 2c 20 30 29  ame, zIpAddr, 0)
7790: 3b 0a 0a 20 20 20 20 20 20 2f 2a 20 54 68 65 20  ;..      /* The 
77a0: 75 73 65 72 20 61 74 74 65 6d 70 74 65 64 20 74  user attempted t
77b0: 6f 20 6c 6f 67 69 6e 20 73 70 65 63 69 66 69 63  o login specific
77c0: 61 6c 6c 79 20 77 69 74 68 20 48 54 54 50 20 62  ally with HTTP b
77d0: 61 73 69 63 0a 20 20 20 20 20 20 2a 2a 20 61 75  asic.      ** au
77e0: 74 68 2c 20 62 75 74 20 70 72 6f 76 69 64 65 64  th, but provided
77f0: 20 69 6e 76 61 6c 69 64 20 63 72 65 64 65 6e 74   invalid credent
7800: 69 61 6c 73 2e 20 49 6e 66 6f 72 6d 20 74 68 65  ials. Inform the
7810: 6d 20 6f 66 0a 20 20 20 20 20 20 2a 2a 20 74 68  m of.      ** th
7820: 65 20 66 61 69 6c 65 64 20 6c 6f 67 69 6e 20 61  e failed login a
7830: 74 74 65 6d 70 74 20 76 69 61 20 34 30 31 2e 0a  ttempt via 401..
7840: 20 20 20 20 20 20 2a 2f 0a 20 20 20 20 20 20 63        */.      c
7850: 67 69 5f 73 65 74 5f 73 74 61 74 75 73 28 34 30  gi_set_status(40
7860: 31 2c 20 22 55 6e 61 75 74 68 6f 72 69 7a 65 64  1, "Unauthorized
7870: 22 29 3b 0a 20 20 20 20 20 20 63 67 69 5f 72 65  ");.      cgi_re
7880: 70 6c 79 28 29 3b 0a 20 20 20 20 20 20 66 6f 73  ply();.      fos
7890: 73 69 6c 5f 65 78 69 74 28 30 29 3b 0a 20 20 20  sil_exit(0);.   
78a0: 20 7d 0a 20 20 7d 0a 20 20 66 6f 73 73 69 6c 5f   }.  }.  fossil_
78b0: 66 72 65 65 28 7a 44 65 63 6f 64 65 29 3b 0a 20  free(zDecode);. 
78c0: 20 72 65 74 75 72 6e 20 75 69 64 3b 0a 7d 0a 0a   return uid;.}..
78d0: 2f 2a 0a 2a 2a 20 54 68 69 73 20 72 6f 75 74 69  /*.** This routi
78e0: 6e 65 20 65 78 61 6d 69 6e 65 73 20 74 68 65 20  ne examines the 
78f0: 6c 6f 67 69 6e 20 63 6f 6f 6b 69 65 20 74 6f 20  login cookie to 
7900: 73 65 65 20 69 66 20 69 74 20 65 78 69 73 74 73  see if it exists
7910: 20 61 6e 64 0a 2a 2a 20 69 73 20 76 61 6c 69 64   and.** is valid
7920: 2e 20 20 49 66 20 74 68 65 20 6c 6f 67 69 6e 20  .  If the login 
7930: 63 6f 6f 6b 69 65 20 63 68 65 63 6b 73 20 6f 75  cookie checks ou
7940: 74 2c 20 69 74 20 74 68 65 6e 20 73 65 74 73 20  t, it then sets 
7950: 67 6c 6f 62 61 6c 0a 2a 2a 20 76 61 72 69 61 62  global.** variab
7960: 6c 65 73 20 61 70 70 72 6f 70 72 69 61 74 65 6c  les appropriatel
7970: 79 2e 0a 2a 2a 0a 2a 2a 20 20 20 20 67 2e 75 73  y..**.**    g.us
7980: 65 72 55 69 64 20 20 20 20 20 20 44 61 74 61 62  erUid      Datab
7990: 61 73 65 20 55 53 45 52 2e 55 49 44 20 76 61 6c  ase USER.UID val
79a0: 75 65 2e 20 20 4d 69 67 68 74 20 62 65 20 2d 31  ue.  Might be -1
79b0: 20 66 6f 72 20 22 6e 6f 62 6f 64 79 22 0a 2a 2a   for "nobody".**
79c0: 20 20 20 20 67 2e 7a 4c 6f 67 69 6e 20 20 20 20      g.zLogin    
79d0: 20 20 20 44 61 74 61 62 61 73 65 20 55 53 45 52     Database USER
79e0: 2e 4c 4f 47 49 4e 20 76 61 6c 75 65 2e 20 20 4e  .LOGIN value.  N
79f0: 55 4c 4c 20 66 6f 72 20 75 73 65 72 20 22 6e 6f  ULL for user "no
7a00: 62 6f 64 79 22 0a 2a 2a 20 20 20 20 67 2e 70 65  body".**    g.pe
7a10: 72 6d 20 20 20 20 20 20 20 20 20 50 65 72 6d 69  rm         Permi
7a20: 73 73 69 6f 6e 73 20 67 72 61 6e 74 65 64 20 74  ssions granted t
7a30: 6f 20 74 68 69 73 20 75 73 65 72 0a 2a 2a 20 20  o this user.**  
7a40: 20 20 67 2e 61 6e 6f 6e 20 20 20 20 20 20 20 20    g.anon        
7a50: 20 50 65 72 6d 69 73 73 69 6f 6e 73 20 74 68 61   Permissions tha
7a60: 74 20 77 6f 75 6c 64 20 62 65 20 61 76 61 69 6c  t would be avail
7a70: 61 62 6c 65 20 74 6f 20 61 6e 6f 6e 79 6d 6f 75  able to anonymou
7a80: 73 0a 2a 2a 20 20 20 20 67 2e 69 73 48 75 6d 61  s.**    g.isHuma
7a90: 6e 20 20 20 20 20 20 54 72 75 65 20 69 66 20 74  n      True if t
7aa0: 68 65 20 75 73 65 72 20 69 73 20 68 75 6d 61 6e  he user is human
7ab0: 2c 20 6e 6f 74 20 61 20 73 70 69 64 65 72 20 6f  , not a spider o
7ac0: 72 20 72 6f 62 6f 74 0a 2a 2a 0a 2a 2f 0a 76 6f  r robot.**.*/.vo
7ad0: 69 64 20 6c 6f 67 69 6e 5f 63 68 65 63 6b 5f 63  id login_check_c
7ae0: 72 65 64 65 6e 74 69 61 6c 73 28 76 6f 69 64 29  redentials(void)
7af0: 7b 0a 20 20 69 6e 74 20 75 69 64 20 3d 20 30 3b  {.  int uid = 0;
7b00: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7b10: 20 20 2f 2a 20 55 73 65 72 20 69 64 20 2a 2f 0a    /* User id */.
7b20: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 43    const char *zC
7b30: 6f 6f 6b 69 65 3b 20 20 20 20 20 20 20 20 20 20  ookie;          
7b40: 2f 2a 20 54 65 78 74 20 6f 66 20 74 68 65 20 6c  /* Text of the l
7b50: 6f 67 69 6e 20 63 6f 6f 6b 69 65 20 2a 2f 0a 20  ogin cookie */. 
7b60: 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 49 70   const char *zIp
7b70: 41 64 64 72 3b 20 20 20 20 20 20 20 20 20 20 2f  Addr;          /
7b80: 2a 20 52 61 77 20 49 50 20 61 64 64 72 65 73 73  * Raw IP address
7b90: 20 6f 66 20 74 68 65 20 72 65 71 75 65 73 74 6f   of the requesto
7ba0: 72 20 2a 2f 0a 20 20 63 68 61 72 20 2a 7a 52 65  r */.  char *zRe
7bb0: 6d 6f 74 65 41 64 64 72 3b 20 20 20 20 20 20 20  moteAddr;       
7bc0: 20 20 20 20 20 2f 2a 20 41 62 62 72 65 76 69 61       /* Abbrevia
7bd0: 74 65 64 20 49 50 20 61 64 64 72 65 73 73 20 6f  ted IP address o
7be0: 66 20 74 68 65 20 72 65 71 75 65 73 74 6f 72 20  f the requestor 
7bf0: 2a 2f 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20  */.  const char 
7c00: 2a 7a 43 61 70 20 3d 20 30 3b 20 20 20 20 20 20  *zCap = 0;      
7c10: 20 20 20 2f 2a 20 43 61 70 61 62 69 6c 69 74 79     /* Capability
7c20: 20 73 74 72 69 6e 67 20 2a 2f 0a 20 20 63 6f 6e   string */.  con
7c30: 73 74 20 63 68 61 72 20 2a 7a 50 75 62 6c 69 63  st char *zPublic
7c40: 50 61 67 65 73 20 3d 20 30 3b 20 2f 2a 20 47 4c  Pages = 0; /* GL
7c50: 4f 42 20 70 61 74 74 65 72 6e 73 20 6f 66 20 70  OB patterns of p
7c60: 75 62 6c 69 63 20 70 61 67 65 73 20 2a 2f 0a 20  ublic pages */. 
7c70: 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 4c 6f   const char *zLo
7c80: 67 69 6e 20 3d 20 30 3b 20 20 20 20 20 20 20 2f  gin = 0;       /
7c90: 2a 20 4c 6f 67 69 6e 20 75 73 65 72 20 66 6f 72  * Login user for
7ca0: 20 63 72 65 64 65 6e 74 69 61 6c 73 20 2a 2f 0a   credentials */.
7cb0: 0a 20 20 2f 2a 20 4f 6e 6c 79 20 72 75 6e 20 74  .  /* Only run t
7cc0: 68 69 73 20 63 68 65 63 6b 20 6f 6e 63 65 2e 20  his check once. 
7cd0: 20 2a 2f 0a 20 20 69 66 28 20 67 2e 75 73 65 72   */.  if( g.user
7ce0: 55 69 64 21 3d 30 20 29 20 72 65 74 75 72 6e 3b  Uid!=0 ) return;
7cf0: 0a 0a 20 20 73 71 6c 69 74 65 33 5f 63 72 65 61  ..  sqlite3_crea
7d00: 74 65 5f 66 75 6e 63 74 69 6f 6e 28 67 2e 64 62  te_function(g.db
7d10: 2c 20 22 63 6f 6e 73 74 61 6e 74 5f 74 69 6d 65  , "constant_time
7d20: 5f 63 6d 70 22 2c 20 32 2c 20 53 51 4c 49 54 45  _cmp", 2, SQLITE
7d30: 5f 55 54 46 38 2c 20 30 2c 0a 20 20 20 20 20 20  _UTF8, 0,.      
7d40: 20 20 20 20 20 20 20 20 20 20 20 20 63 6f 6e 73              cons
7d50: 74 61 6e 74 5f 74 69 6d 65 5f 63 6d 70 5f 66 75  tant_time_cmp_fu
7d60: 6e 63 74 69 6f 6e 2c 20 30 2c 20 30 29 3b 0a 0a  nction, 0, 0);..
7d70: 20 20 2f 2a 20 49 66 20 74 68 65 20 48 54 54 50    /* If the HTTP
7d80: 20 63 6f 6e 6e 65 63 74 69 6f 6e 20 69 73 20 63   connection is c
7d90: 6f 6d 69 6e 67 20 6f 76 65 72 20 31 32 37 2e 30  oming over 127.0
7da0: 2e 30 2e 31 20 61 6e 64 20 69 66 0a 20 20 2a 2a  .0.1 and if.  **
7db0: 20 6c 6f 63 61 6c 20 6c 6f 67 69 6e 20 69 73 20   local login is 
7dc0: 64 69 73 61 62 6c 65 64 20 61 6e 64 20 69 66 20  disabled and if 
7dd0: 77 65 20 61 72 65 20 75 73 69 6e 67 20 48 54 54  we are using HTT
7de0: 50 20 61 6e 64 20 6e 6f 74 20 48 54 54 50 53 2c  P and not HTTPS,
7df0: 0a 20 20 2a 2a 20 74 68 65 6e 20 74 68 65 72 65  .  ** then there
7e00: 20 69 73 20 6e 6f 20 6e 65 65 64 20 74 6f 20 63   is no need to c
7e10: 68 65 63 6b 20 75 73 65 72 20 63 72 65 64 65 6e  heck user creden
7e20: 74 69 61 6c 73 2e 0a 20 20 2a 2a 0a 20 20 2a 2a  tials..  **.  **
7e30: 20 54 68 69 73 20 66 65 61 74 75 72 65 20 61 6c   This feature al
7e40: 6c 6f 77 73 20 74 68 65 20 22 66 6f 73 73 69 6c  lows the "fossil
7e50: 20 75 69 22 20 63 6f 6d 6d 61 6e 64 20 74 6f 20   ui" command to 
7e60: 67 69 76 65 20 74 68 65 20 75 73 65 72 0a 20 20  give the user.  
7e70: 2a 2a 20 66 75 6c 6c 20 61 63 63 65 73 73 20 72  ** full access r
7e80: 69 67 68 74 73 20 77 69 74 68 6f 75 74 20 68 61  ights without ha
7e90: 76 69 6e 67 20 74 6f 20 6c 6f 67 20 69 6e 2e 0a  ving to log in..
7ea0: 20 20 2a 2f 0a 20 20 7a 52 65 6d 6f 74 65 41 64    */.  zRemoteAd
7eb0: 64 72 20 3d 20 69 70 50 72 65 66 69 78 28 7a 49  dr = ipPrefix(zI
7ec0: 70 41 64 64 72 20 3d 20 50 44 28 22 52 45 4d 4f  pAddr = PD("REMO
7ed0: 54 45 5f 41 44 44 52 22 2c 22 6e 69 6c 22 29 29  TE_ADDR","nil"))
7ee0: 3b 0a 20 20 69 66 28 20 28 20 63 67 69 5f 69 73  ;.  if( ( cgi_is
7ef0: 5f 6c 6f 6f 70 62 61 63 6b 28 7a 49 70 41 64 64  _loopback(zIpAdd
7f00: 72 29 0a 20 20 20 20 20 20 20 7c 7c 20 28 67 2e  r).       || (g.
7f10: 66 53 73 68 43 6c 69 65 6e 74 20 26 20 43 47 49  fSshClient & CGI
7f20: 5f 53 53 48 5f 43 4c 49 45 4e 54 29 21 3d 30 20  _SSH_CLIENT)!=0 
7f30: 29 0a 20 20 20 26 26 20 67 2e 75 73 65 4c 6f 63  ).   && g.useLoc
7f40: 61 6c 61 75 74 68 0a 20 20 20 26 26 20 64 62 5f  alauth.   && db_
7f50: 67 65 74 5f 69 6e 74 28 22 6c 6f 63 61 6c 61 75  get_int("localau
7f60: 74 68 22 2c 30 29 3d 3d 30 0a 20 20 20 26 26 20  th",0)==0.   && 
7f70: 50 28 22 48 54 54 50 53 22 29 3d 3d 30 0a 20 20  P("HTTPS")==0.  
7f80: 29 7b 0a 20 20 20 20 69 66 28 20 67 2e 6c 6f 63  ){.    if( g.loc
7f90: 61 6c 4f 70 65 6e 20 29 20 7a 4c 6f 67 69 6e 20  alOpen ) zLogin 
7fa0: 3d 20 64 62 5f 6c 67 65 74 28 22 64 65 66 61 75  = db_lget("defau
7fb0: 6c 74 2d 75 73 65 72 22 2c 30 29 3b 0a 20 20 20  lt-user",0);.   
7fc0: 20 69 66 28 20 7a 4c 6f 67 69 6e 21 3d 30 20 29   if( zLogin!=0 )
7fd0: 7b 0a 20 20 20 20 20 20 75 69 64 20 3d 20 64 62  {.      uid = db
7fe0: 5f 69 6e 74 28 30 2c 20 22 53 45 4c 45 43 54 20  _int(0, "SELECT 
7ff0: 75 69 64 20 46 52 4f 4d 20 75 73 65 72 20 57 48  uid FROM user WH
8000: 45 52 45 20 6c 6f 67 69 6e 3d 25 51 22 2c 20 7a  ERE login=%Q", z
8010: 4c 6f 67 69 6e 29 3b 0a 20 20 20 20 7d 65 6c 73  Login);.    }els
8020: 65 7b 0a 20 20 20 20 20 20 75 69 64 20 3d 20 64  e{.      uid = d
8030: 62 5f 69 6e 74 28 30 2c 20 22 53 45 4c 45 43 54  b_int(0, "SELECT
8040: 20 75 69 64 20 46 52 4f 4d 20 75 73 65 72 20 57   uid FROM user W
8050: 48 45 52 45 20 63 61 70 20 4c 49 4b 45 20 27 25  HERE cap LIKE '%
8060: 25 73 25 25 27 22 29 3b 0a 20 20 20 20 7d 0a 20  %s%%'");.    }. 
8070: 20 20 20 67 2e 7a 4c 6f 67 69 6e 20 3d 20 64 62     g.zLogin = db
8080: 5f 74 65 78 74 28 22 3f 22 2c 20 22 53 45 4c 45  _text("?", "SELE
8090: 43 54 20 6c 6f 67 69 6e 20 46 52 4f 4d 20 75 73  CT login FROM us
80a0: 65 72 20 57 48 45 52 45 20 75 69 64 3d 25 64 22  er WHERE uid=%d"
80b0: 2c 20 75 69 64 29 3b 0a 20 20 20 20 7a 43 61 70  , uid);.    zCap
80c0: 20 3d 20 22 73 78 22 3b 0a 20 20 20 20 67 2e 6e   = "sx";.    g.n
80d0: 6f 50 73 77 64 20 3d 20 31 3b 0a 20 20 20 20 67  oPswd = 1;.    g
80e0: 2e 69 73 48 75 6d 61 6e 20 3d 20 31 3b 0a 20 20  .isHuman = 1;.  
80f0: 20 20 73 71 6c 69 74 65 33 5f 73 6e 70 72 69 6e    sqlite3_snprin
8100: 74 66 28 73 69 7a 65 6f 66 28 67 2e 7a 43 73 72  tf(sizeof(g.zCsr
8110: 66 54 6f 6b 65 6e 29 2c 20 67 2e 7a 43 73 72 66  fToken), g.zCsrf
8120: 54 6f 6b 65 6e 2c 20 22 6c 6f 63 61 6c 68 6f 73  Token, "localhos
8130: 74 22 29 3b 0a 20 20 7d 0a 0a 20 20 2f 2a 20 43  t");.  }..  /* C
8140: 68 65 63 6b 20 74 68 65 20 6c 6f 67 69 6e 20 63  heck the login c
8150: 6f 6f 6b 69 65 20 74 6f 20 73 65 65 20 69 66 20  ookie to see if 
8160: 69 74 20 6d 61 74 63 68 65 73 20 61 20 6b 6e 6f  it matches a kno
8170: 77 6e 20 76 61 6c 69 64 20 75 73 65 72 2e 0a 20  wn valid user.. 
8180: 20 2a 2f 0a 20 20 69 66 28 20 75 69 64 3d 3d 30   */.  if( uid==0
8190: 20 26 26 20 28 7a 43 6f 6f 6b 69 65 20 3d 20 50   && (zCookie = P
81a0: 28 6c 6f 67 69 6e 5f 63 6f 6f 6b 69 65 5f 6e 61  (login_cookie_na
81b0: 6d 65 28 29 29 29 21 3d 30 20 29 7b 0a 20 20 20  me()))!=0 ){.   
81c0: 20 2f 2a 20 50 61 72 73 65 20 74 68 65 20 63 6f   /* Parse the co
81d0: 6f 6b 69 65 20 76 61 6c 75 65 20 75 70 20 69 6e  okie value up in
81e0: 74 6f 20 48 41 53 48 2f 41 52 47 2f 55 53 45 52  to HASH/ARG/USER
81f0: 20 2a 2f 0a 20 20 20 20 63 68 61 72 20 2a 7a 48   */.    char *zH
8200: 61 73 68 20 3d 20 66 6f 73 73 69 6c 5f 73 74 72  ash = fossil_str
8210: 64 75 70 28 7a 43 6f 6f 6b 69 65 29 3b 0a 20 20  dup(zCookie);.  
8220: 20 20 63 68 61 72 20 2a 7a 41 72 67 20 3d 20 30    char *zArg = 0
8230: 3b 0a 20 20 20 20 63 68 61 72 20 2a 7a 55 73 65  ;.    char *zUse
8240: 72 20 3d 20 30 3b 0a 20 20 20 20 69 6e 74 20 69  r = 0;.    int i
8250: 2c 20 63 3b 0a 20 20 20 20 66 6f 72 28 69 3d 30  , c;.    for(i=0
8260: 3b 20 28 63 20 3d 20 7a 48 61 73 68 5b 69 5d 29  ; (c = zHash[i])
8270: 21 3d 30 3b 20 69 2b 2b 29 7b 0a 20 20 20 20 20  !=0; i++){.     
8280: 20 69 66 28 20 63 3d 3d 27 2f 27 20 29 7b 0a 20   if( c=='/' ){. 
8290: 20 20 20 20 20 20 20 7a 48 61 73 68 5b 69 2b 2b         zHash[i++
82a0: 5d 20 3d 20 30 3b 0a 20 20 20 20 20 20 20 20 69  ] = 0;.        i
82b0: 66 28 20 7a 41 72 67 3d 3d 30 20 29 7b 0a 20 20  f( zArg==0 ){.  
82c0: 20 20 20 20 20 20 20 20 7a 41 72 67 20 3d 20 26          zArg = &
82d0: 7a 48 61 73 68 5b 69 5d 3b 0a 20 20 20 20 20 20  zHash[i];.      
82e0: 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 20    }else{.       
82f0: 20 20 20 7a 55 73 65 72 20 3d 20 26 7a 48 61 73     zUser = &zHas
8300: 68 5b 69 5d 3b 0a 20 20 20 20 20 20 20 20 20 20  h[i];.          
8310: 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 20 20 7d  break;.        }
8320: 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a 20  .      }.    }. 
8330: 20 20 20 69 66 28 20 7a 55 73 65 72 3d 3d 30 20     if( zUser==0 
8340: 29 7b 0a 20 20 20 20 20 20 2f 2a 20 49 6e 76 61  ){.      /* Inva
8350: 6c 69 64 20 63 6f 6f 6b 69 65 20 2a 2f 0a 20 20  lid cookie */.  
8360: 20 20 7d 65 6c 73 65 20 69 66 28 20 66 6f 73 73    }else if( foss
8370: 69 6c 5f 73 74 72 63 6d 70 28 7a 55 73 65 72 2c  il_strcmp(zUser,
8380: 20 22 61 6e 6f 6e 79 6d 6f 75 73 22 29 3d 3d 30   "anonymous")==0
8390: 20 29 7b 0a 20 20 20 20 20 20 2f 2a 20 43 6f 6f   ){.      /* Coo
83a0: 6b 69 65 73 20 6f 66 20 74 68 65 20 66 6f 72 6d  kies of the form
83b0: 20 22 48 41 53 48 2f 54 49 4d 45 2f 61 6e 6f 6e   "HASH/TIME/anon
83c0: 79 6d 6f 75 73 22 2e 20 20 54 68 65 20 54 49 4d  ymous".  The TIM
83d0: 45 20 6d 75 73 74 20 6e 6f 74 20 62 65 0a 20 20  E must not be.  
83e0: 20 20 20 20 2a 2a 20 74 6f 6f 20 6f 6c 64 20 61      ** too old a
83f0: 6e 64 20 74 68 65 20 73 68 61 31 20 68 61 73 68  nd the sha1 hash
8400: 20 6f 66 20 54 49 4d 45 2f 49 50 41 44 44 52 2f   of TIME/IPADDR/
8410: 53 45 43 52 45 54 20 6d 75 73 74 20 6d 61 74 63  SECRET must matc
8420: 68 20 48 41 53 48 2e 0a 20 20 20 20 20 20 2a 2a  h HASH..      **
8430: 20 53 45 43 52 45 54 20 69 73 20 74 68 65 20 22   SECRET is the "
8440: 63 61 70 74 63 68 61 2d 73 65 63 72 65 74 22 20  captcha-secret" 
8450: 76 61 6c 75 65 20 69 6e 20 74 68 65 20 72 65 70  value in the rep
8460: 6f 73 69 74 6f 72 79 2e 0a 20 20 20 20 20 20 2a  ository..      *
8470: 2f 0a 20 20 20 20 20 20 64 6f 75 62 6c 65 20 72  /.      double r
8480: 54 69 6d 65 20 3d 20 61 74 6f 66 28 7a 41 72 67  Time = atof(zArg
8490: 29 3b 0a 20 20 20 20 20 20 42 6c 6f 62 20 62 3b  );.      Blob b;
84a0: 0a 20 20 20 20 20 20 62 6c 6f 62 5f 7a 65 72 6f  .      blob_zero
84b0: 28 26 62 29 3b 0a 20 20 20 20 20 20 62 6c 6f 62  (&b);.      blob
84c0: 5f 61 70 70 65 6e 64 66 28 26 62 2c 20 22 25 73  _appendf(&b, "%s
84d0: 2f 25 73 2f 25 73 22 2c 0a 20 20 20 20 20 20 20  /%s/%s",.       
84e0: 20 20 20 20 20 20 20 20 20 20 20 20 7a 41 72 67              zArg
84f0: 2c 20 7a 52 65 6d 6f 74 65 41 64 64 72 2c 20 64  , zRemoteAddr, d
8500: 62 5f 67 65 74 28 22 63 61 70 74 63 68 61 2d 73  b_get("captcha-s
8510: 65 63 72 65 74 22 2c 22 22 29 29 3b 0a 20 20 20  ecret",""));.   
8520: 20 20 20 73 68 61 31 73 75 6d 5f 62 6c 6f 62 28     sha1sum_blob(
8530: 26 62 2c 20 26 62 29 3b 0a 20 20 20 20 20 20 69  &b, &b);.      i
8540: 66 28 20 66 6f 73 73 69 6c 5f 73 74 72 63 6d 70  f( fossil_strcmp
8550: 28 7a 48 61 73 68 2c 20 62 6c 6f 62 5f 73 74 72  (zHash, blob_str
8560: 28 26 62 29 29 3d 3d 30 20 29 7b 0a 20 20 20 20  (&b))==0 ){.    
8570: 20 20 20 20 75 69 64 20 3d 20 64 62 5f 69 6e 74      uid = db_int
8580: 28 30 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20  (0,.            
8590: 22 53 45 4c 45 43 54 20 75 69 64 20 46 52 4f 4d  "SELECT uid FROM
85a0: 20 75 73 65 72 20 57 48 45 52 45 20 6c 6f 67 69   user WHERE logi
85b0: 6e 3d 27 61 6e 6f 6e 79 6d 6f 75 73 27 22 0a 20  n='anonymous'". 
85c0: 20 20 20 20 20 20 20 20 20 20 20 22 20 41 4e 44             " AND
85d0: 20 6c 65 6e 67 74 68 28 63 61 70 29 3e 30 22 0a   length(cap)>0".
85e0: 20 20 20 20 20 20 20 20 20 20 20 20 22 20 41 4e              " AN
85f0: 44 20 6c 65 6e 67 74 68 28 70 77 29 3e 30 22 0a  D length(pw)>0".
8600: 20 20 20 20 20 20 20 20 20 20 20 20 22 20 41 4e              " AN
8610: 44 20 25 2e 31 37 67 2b 30 2e 32 35 3e 6a 75 6c  D %.17g+0.25>jul
8620: 69 61 6e 64 61 79 28 27 6e 6f 77 27 29 22 2c 0a  ianday('now')",.
8630: 20 20 20 20 20 20 20 20 20 20 20 20 72 54 69 6d              rTim
8640: 65 0a 20 20 20 20 20 20 20 20 29 3b 0a 20 20 20  e.        );.   
8650: 20 20 20 7d 0a 20 20 20 20 20 20 62 6c 6f 62 5f     }.      blob_
8660: 72 65 73 65 74 28 26 62 29 3b 0a 20 20 20 20 7d  reset(&b);.    }
8670: 65 6c 73 65 7b 0a 20 20 20 20 20 20 2f 2a 20 43  else{.      /* C
8680: 6f 6f 6b 69 65 73 20 6f 66 20 74 68 65 20 66 6f  ookies of the fo
8690: 72 6d 20 22 48 41 53 48 2f 43 4f 44 45 2f 55 53  rm "HASH/CODE/US
86a0: 45 52 22 2e 20 20 53 65 61 72 63 68 20 66 69 72  ER".  Search fir
86b0: 73 74 20 69 6e 20 74 68 65 0a 20 20 20 20 20 20  st in the.      
86c0: 2a 2a 20 6c 6f 63 61 6c 20 75 73 65 72 20 74 61  ** local user ta
86d0: 62 6c 65 2c 20 74 68 65 6e 20 74 68 65 20 75 73  ble, then the us
86e0: 65 72 20 74 61 62 6c 65 20 66 6f 72 20 70 72 6f  er table for pro
86f0: 6a 65 63 74 20 43 4f 44 45 20 69 66 20 77 65 0a  ject CODE if we.
8700: 20 20 20 20 20 20 2a 2a 20 61 72 65 20 70 61 72        ** are par
8710: 74 20 6f 66 20 61 20 6c 6f 67 69 6e 2d 67 72 6f  t of a login-gro
8720: 75 70 2e 0a 20 20 20 20 20 20 2a 2f 0a 20 20 20  up..      */.   
8730: 20 20 20 75 69 64 20 3d 20 6c 6f 67 69 6e 5f 66     uid = login_f
8740: 69 6e 64 5f 75 73 65 72 28 7a 55 73 65 72 2c 20  ind_user(zUser, 
8750: 7a 48 61 73 68 2c 20 7a 52 65 6d 6f 74 65 41 64  zHash, zRemoteAd
8760: 64 72 29 3b 0a 20 20 20 20 20 20 69 66 28 20 75  dr);.      if( u
8770: 69 64 3d 3d 30 20 26 26 20 6c 6f 67 69 6e 5f 74  id==0 && login_t
8780: 72 61 6e 73 66 65 72 5f 63 72 65 64 65 6e 74 69  ransfer_credenti
8790: 61 6c 73 28 7a 55 73 65 72 2c 7a 41 72 67 2c 7a  als(zUser,zArg,z
87a0: 48 61 73 68 2c 7a 52 65 6d 6f 74 65 41 64 64 72  Hash,zRemoteAddr
87b0: 29 20 29 7b 0a 20 20 20 20 20 20 20 20 75 69 64  ) ){.        uid
87c0: 20 3d 20 6c 6f 67 69 6e 5f 66 69 6e 64 5f 75 73   = login_find_us
87d0: 65 72 28 7a 55 73 65 72 2c 20 7a 48 61 73 68 2c  er(zUser, zHash,
87e0: 20 7a 52 65 6d 6f 74 65 41 64 64 72 29 3b 0a 20   zRemoteAddr);. 
87f0: 20 20 20 20 20 20 20 69 66 28 20 75 69 64 20 29         if( uid )
8800: 20 72 65 63 6f 72 64 5f 6c 6f 67 69 6e 5f 61 74   record_login_at
8810: 74 65 6d 70 74 28 7a 55 73 65 72 2c 20 7a 49 70  tempt(zUser, zIp
8820: 41 64 64 72 2c 20 31 29 3b 0a 20 20 20 20 20 20  Addr, 1);.      
8830: 7d 0a 20 20 20 20 7d 0a 20 20 20 20 73 71 6c 69  }.    }.    sqli
8840: 74 65 33 5f 73 6e 70 72 69 6e 74 66 28 73 69 7a  te3_snprintf(siz
8850: 65 6f 66 28 67 2e 7a 43 73 72 66 54 6f 6b 65 6e  eof(g.zCsrfToken
8860: 29 2c 20 67 2e 7a 43 73 72 66 54 6f 6b 65 6e 2c  ), g.zCsrfToken,
8870: 20 22 25 2e 31 30 73 22 2c 20 7a 48 61 73 68 29   "%.10s", zHash)
8880: 3b 0a 20 20 7d 0a 0a 20 20 2f 2a 20 49 66 20 6e  ;.  }..  /* If n
8890: 6f 20 75 73 65 72 20 66 6f 75 6e 64 20 61 6e 64  o user found and
88a0: 20 74 68 65 20 52 45 4d 4f 54 45 5f 55 53 45 52   the REMOTE_USER
88b0: 20 65 6e 76 69 72 6f 6e 6d 65 6e 74 20 76 61 72   environment var
88c0: 69 61 62 6c 65 20 69 73 20 73 65 74 2c 0a 20 20  iable is set,.  
88d0: 2a 2a 20 74 68 65 6e 20 61 63 63 65 70 74 20 74  ** then accept t
88e0: 68 65 20 76 61 6c 75 65 20 6f 66 20 52 45 4d 4f  he value of REMO
88f0: 54 45 5f 55 53 45 52 20 61 73 20 74 68 65 20 75  TE_USER as the u
8900: 73 65 72 2e 0a 20 20 2a 2f 0a 20 20 69 66 28 20  ser..  */.  if( 
8910: 75 69 64 3d 3d 30 20 29 7b 0a 20 20 20 20 63 6f  uid==0 ){.    co
8920: 6e 73 74 20 63 68 61 72 20 2a 7a 52 65 6d 6f 74  nst char *zRemot
8930: 65 55 73 65 72 20 3d 20 50 28 22 52 45 4d 4f 54  eUser = P("REMOT
8940: 45 5f 55 53 45 52 22 29 3b 0a 20 20 20 20 69 66  E_USER");.    if
8950: 28 20 7a 52 65 6d 6f 74 65 55 73 65 72 20 26 26  ( zRemoteUser &&
8960: 20 64 62 5f 67 65 74 5f 62 6f 6f 6c 65 61 6e 28   db_get_boolean(
8970: 22 72 65 6d 6f 74 65 5f 75 73 65 72 5f 6f 6b 22  "remote_user_ok"
8980: 2c 30 29 20 29 7b 0a 20 20 20 20 20 20 75 69 64  ,0) ){.      uid
8990: 20 3d 20 64 62 5f 69 6e 74 28 30 2c 20 22 53 45   = db_int(0, "SE
89a0: 4c 45 43 54 20 75 69 64 20 46 52 4f 4d 20 75 73  LECT uid FROM us
89b0: 65 72 20 57 48 45 52 45 20 6c 6f 67 69 6e 3d 25  er WHERE login=%
89c0: 51 22 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  Q".             
89d0: 20 20 20 20 20 20 20 20 20 22 20 41 4e 44 20 6c           " AND l
89e0: 65 6e 67 74 68 28 63 61 70 29 3e 30 20 41 4e 44  ength(cap)>0 AND
89f0: 20 6c 65 6e 67 74 68 28 70 77 29 3e 30 22 2c 20   length(pw)>0", 
8a00: 7a 52 65 6d 6f 74 65 55 73 65 72 29 3b 0a 20 20  zRemoteUser);.  
8a10: 20 20 7d 0a 20 20 7d 0a 0a 20 20 2f 2a 20 49 66    }.  }..  /* If
8a20: 20 74 68 65 20 72 65 71 75 65 73 74 20 64 69 64   the request did
8a30: 6e 27 74 20 70 72 6f 76 69 64 65 20 61 20 6c 6f  n't provide a lo
8a40: 67 69 6e 20 63 6f 6f 6b 69 65 20 6f 72 20 74 68  gin cookie or th
8a50: 65 20 6c 6f 67 69 6e 20 63 6f 6f 6b 69 65 20 64  e login cookie d
8a60: 69 64 6e 27 74 0a 20 20 2a 2a 20 6d 61 74 63 68  idn't.  ** match
8a70: 20 61 20 6b 6e 6f 77 6e 20 76 61 6c 69 64 20 75   a known valid u
8a80: 73 65 72 2c 20 63 68 65 63 6b 20 74 68 65 20 48  ser, check the H
8a90: 54 54 50 20 22 41 75 74 68 6f 72 69 7a 61 74 69  TTP "Authorizati
8aa0: 6f 6e 22 20 68 65 61 64 65 72 20 61 6e 64 0a 20  on" header and. 
8ab0: 20 2a 2a 20 73 65 65 20 69 66 20 74 68 6f 73 65   ** see if those
8ac0: 20 63 72 65 64 65 6e 74 69 61 6c 73 20 61 72 65   credentials are
8ad0: 20 76 61 6c 69 64 20 66 6f 72 20 61 20 6b 6e 6f   valid for a kno
8ae0: 77 6e 20 75 73 65 72 2e 0a 20 20 2a 2f 0a 20 20  wn user..  */.  
8af0: 69 66 28 20 75 69 64 3d 3d 30 20 26 26 20 64 62  if( uid==0 && db
8b00: 5f 67 65 74 5f 62 6f 6f 6c 65 61 6e 28 22 68 74  _get_boolean("ht
8b10: 74 70 5f 61 75 74 68 65 6e 74 69 63 61 74 69 6f  tp_authenticatio
8b20: 6e 5f 6f 6b 22 2c 30 29 20 29 7b 0a 20 20 20 20  n_ok",0) ){.    
8b30: 75 69 64 20 3d 20 6c 6f 67 69 6e 5f 62 61 73 69  uid = login_basi
8b40: 63 5f 61 75 74 68 65 6e 74 69 63 61 74 69 6f 6e  c_authentication
8b50: 28 7a 49 70 41 64 64 72 29 3b 0a 20 20 7d 0a 0a  (zIpAddr);.  }..
8b60: 20 20 2f 2a 20 49 66 20 6e 6f 20 75 73 65 72 20    /* If no user 
8b70: 66 6f 75 6e 64 20 79 65 74 2c 20 74 72 79 20 74  found yet, try t
8b80: 6f 20 6c 6f 67 20 69 6e 20 61 73 20 22 6e 6f 62  o log in as "nob
8b90: 6f 64 79 22 20 2a 2f 0a 20 20 69 66 28 20 75 69  ody" */.  if( ui
8ba0: 64 3d 3d 30 20 29 7b 0a 20 20 20 20 75 69 64 20  d==0 ){.    uid 
8bb0: 3d 20 64 62 5f 69 6e 74 28 30 2c 20 22 53 45 4c  = db_int(0, "SEL
8bc0: 45 43 54 20 75 69 64 20 46 52 4f 4d 20 75 73 65  ECT uid FROM use
8bd0: 72 20 57 48 45 52 45 20 6c 6f 67 69 6e 3d 27 6e  r WHERE login='n
8be0: 6f 62 6f 64 79 27 22 29 3b 0a 20 20 20 20 69 66  obody'");.    if
8bf0: 28 20 75 69 64 3d 3d 30 20 29 7b 0a 20 20 20 20  ( uid==0 ){.    
8c00: 20 20 2f 2a 20 49 66 20 74 68 65 72 65 20 69 73    /* If there is
8c10: 20 6e 6f 20 75 73 65 72 20 22 6e 6f 62 6f 64 79   no user "nobody
8c20: 22 2c 20 74 68 65 6e 20 6d 61 6b 65 20 6f 6e 65  ", then make one
8c30: 20 75 70 20 2d 20 77 69 74 68 20 6e 6f 20 70 72   up - with no pr
8c40: 69 76 69 6c 65 67 65 73 20 2a 2f 0a 20 20 20 20  ivileges */.    
8c50: 20 20 75 69 64 20 3d 20 2d 31 3b 0a 20 20 20 20    uid = -1;.    
8c60: 20 20 7a 43 61 70 20 3d 20 22 22 3b 0a 20 20 20    zCap = "";.   
8c70: 20 7d 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 73   }.    sqlite3_s
8c80: 6e 70 72 69 6e 74 66 28 73 69 7a 65 6f 66 28 67  nprintf(sizeof(g
8c90: 2e 7a 43 73 72 66 54 6f 6b 65 6e 29 2c 20 67 2e  .zCsrfToken), g.
8ca0: 7a 43 73 72 66 54 6f 6b 65 6e 2c 20 22 6e 6f 6e  zCsrfToken, "non
8cb0: 65 22 29 3b 0a 20 20 7d 0a 0a 20 20 2f 2a 20 41  e");.  }..  /* A
8cc0: 74 20 74 68 69 73 20 70 6f 69 6e 74 2c 20 77 65  t this point, we
8cd0: 20 6b 6e 6f 77 20 74 68 61 74 20 75 69 64 21 3d   know that uid!=
8ce0: 30 2e 20 20 46 69 6e 64 20 74 68 65 20 70 72 69  0.  Find the pri
8cf0: 76 69 6c 65 67 65 73 20 61 73 73 6f 63 69 61 74  vileges associat
8d00: 65 64 0a 20 20 2a 2a 20 77 69 74 68 20 75 73 65  ed.  ** with use
8d10: 72 20 75 69 64 2e 0a 20 20 2a 2f 0a 20 20 61 73  r uid..  */.  as
8d20: 73 65 72 74 28 20 75 69 64 21 3d 30 20 29 3b 0a  sert( uid!=0 );.
8d30: 20 20 69 66 28 20 7a 43 61 70 3d 3d 30 20 29 7b    if( zCap==0 ){
8d40: 0a 20 20 20 20 53 74 6d 74 20 73 3b 0a 20 20 20  .    Stmt s;.   
8d50: 20 64 62 5f 70 72 65 70 61 72 65 28 26 73 2c 20   db_prepare(&s, 
8d60: 22 53 45 4c 45 43 54 20 6c 6f 67 69 6e 2c 20 63  "SELECT login, c
8d70: 61 70 20 46 52 4f 4d 20 75 73 65 72 20 57 48 45  ap FROM user WHE
8d80: 52 45 20 75 69 64 3d 25 64 22 2c 20 75 69 64 29  RE uid=%d", uid)
8d90: 3b 0a 20 20 20 20 69 66 28 20 64 62 5f 73 74 65  ;.    if( db_ste
8da0: 70 28 26 73 29 3d 3d 53 51 4c 49 54 45 5f 52 4f  p(&s)==SQLITE_RO
8db0: 57 20 29 7b 0a 20 20 20 20 20 20 67 2e 7a 4c 6f  W ){.      g.zLo
8dc0: 67 69 6e 20 3d 20 64 62 5f 63 6f 6c 75 6d 6e 5f  gin = db_column_
8dd0: 6d 61 6c 6c 6f 63 28 26 73 2c 20 30 29 3b 0a 20  malloc(&s, 0);. 
8de0: 20 20 20 20 20 7a 43 61 70 20 3d 20 64 62 5f 63       zCap = db_c
8df0: 6f 6c 75 6d 6e 5f 6d 61 6c 6c 6f 63 28 26 73 2c  olumn_malloc(&s,
8e00: 20 31 29 3b 0a 20 20 20 20 7d 0a 20 20 20 20 64   1);.    }.    d
8e10: 62 5f 66 69 6e 61 6c 69 7a 65 28 26 73 29 3b 0a  b_finalize(&s);.
8e20: 20 20 20 20 69 66 28 20 7a 43 61 70 3d 3d 30 20      if( zCap==0 
8e30: 29 7b 0a 20 20 20 20 20 20 7a 43 61 70 20 3d 20  ){.      zCap = 
8e40: 22 22 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20  "";.    }.  }.  
8e50: 69 66 28 20 67 2e 66 48 74 74 70 54 72 61 63 65  if( g.fHttpTrace
8e60: 20 26 26 20 67 2e 7a 4c 6f 67 69 6e 20 29 7b 0a   && g.zLogin ){.
8e70: 20 20 20 20 66 70 72 69 6e 74 66 28 73 74 64 65      fprintf(stde
8e80: 72 72 2c 20 22 23 20 6c 6f 67 69 6e 3a 20 5b 25  rr, "# login: [%
8e90: 73 5d 20 77 69 74 68 20 63 61 70 61 62 69 6c 69  s] with capabili
8ea0: 74 69 65 73 20 5b 25 73 5d 5c 6e 22 2c 20 67 2e  ties [%s]\n", g.
8eb0: 7a 4c 6f 67 69 6e 2c 20 7a 43 61 70 29 3b 0a 20  zLogin, zCap);. 
8ec0: 20 7d 0a 0a 20 20 2f 2a 20 53 65 74 20 74 68 65   }..  /* Set the
8ed0: 20 67 6c 6f 62 61 6c 20 76 61 72 69 61 62 6c 65   global variable
8ee0: 73 20 72 65 63 6f 72 64 69 6e 67 20 74 68 65 20  s recording the 
8ef0: 75 73 65 72 69 64 20 61 6e 64 20 6c 6f 67 69 6e  userid and login
8f00: 2e 20 20 54 68 65 0a 20 20 2a 2a 20 22 6e 6f 62  .  The.  ** "nob
8f10: 6f 64 79 22 20 75 73 65 72 20 69 73 20 61 20 73  ody" user is a s
8f20: 70 65 63 69 61 6c 20 63 61 73 65 20 69 6e 20 74  pecial case in t
8f30: 68 61 74 20 67 2e 7a 4c 6f 67 69 6e 3d 3d 30 2e  hat g.zLogin==0.
8f40: 0a 20 20 2a 2f 0a 20 20 67 2e 75 73 65 72 55 69  .  */.  g.userUi
8f50: 64 20 3d 20 75 69 64 3b 0a 20 20 69 66 28 20 66  d = uid;.  if( f
8f60: 6f 73 73 69 6c 5f 73 74 72 63 6d 70 28 67 2e 7a  ossil_strcmp(g.z
8f70: 4c 6f 67 69 6e 2c 22 6e 6f 62 6f 64 79 22 29 3d  Login,"nobody")=
8f80: 3d 30 20 29 7b 0a 20 20 20 20 67 2e 7a 4c 6f 67  =0 ){.    g.zLog
8f90: 69 6e 20 3d 20 30 3b 0a 20 20 7d 0a 20 20 69 66  in = 0;.  }.  if
8fa0: 28 20 50 42 28 22 69 73 72 6f 62 6f 74 22 29 20  ( PB("isrobot") 
8fb0: 29 7b 0a 20 20 20 20 67 2e 69 73 48 75 6d 61 6e  ){.    g.isHuman
8fc0: 20 3d 20 30 3b 0a 20 20 7d 65 6c 73 65 20 69 66   = 0;.  }else if
8fd0: 28 20 67 2e 7a 4c 6f 67 69 6e 3d 3d 30 20 29 7b  ( g.zLogin==0 ){
8fe0: 0a 20 20 20 20 67 2e 69 73 48 75 6d 61 6e 20 3d  .    g.isHuman =
8ff0: 20 69 73 48 75 6d 61 6e 28 50 28 22 48 54 54 50   isHuman(P("HTTP
9000: 5f 55 53 45 52 5f 41 47 45 4e 54 22 29 29 3b 0a  _USER_AGENT"));.
9010: 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 67 2e 69    }else{.    g.i
9020: 73 48 75 6d 61 6e 20 3d 20 31 3b 0a 20 20 7d 0a  sHuman = 1;.  }.
9030: 0a 20 20 2f 2a 20 53 65 74 20 74 68 65 20 63 61  .  /* Set the ca
9040: 70 61 62 69 6c 69 74 69 65 73 20 2a 2f 0a 20 20  pabilities */.  
9050: 6c 6f 67 69 6e 5f 72 65 70 6c 61 63 65 5f 63 61  login_replace_ca
9060: 70 61 62 69 6c 69 74 69 65 73 28 7a 43 61 70 2c  pabilities(zCap,
9070: 20 30 29 3b 0a 0a 20 20 2f 2a 20 54 68 65 20 61   0);..  /* The a
9080: 75 74 6f 2d 68 79 70 65 72 6c 69 6e 6b 20 73 65  uto-hyperlink se
9090: 74 74 69 6e 67 20 61 6c 6c 6f 77 73 20 68 79 70  tting allows hyp
90a0: 65 72 6c 69 6e 6b 73 20 74 6f 20 62 65 20 64 69  erlinks to be di
90b0: 73 70 6c 61 79 65 64 20 66 6f 72 20 75 73 65 72  splayed for user
90c0: 73 0a 20 20 2a 2a 20 77 68 6f 20 64 6f 20 6e 6f  s.  ** who do no
90d0: 74 20 68 61 76 65 20 74 68 65 20 22 68 22 20 70  t have the "h" p
90e0: 65 72 6d 69 73 73 69 6f 6e 20 61 73 20 6c 6f 6e  ermission as lon
90f0: 67 20 61 73 20 74 68 65 69 72 20 55 73 65 72 41  g as their UserA
9100: 67 65 6e 74 20 73 74 72 69 6e 67 0a 20 20 2a 2a  gent string.  **
9110: 20 6d 61 6b 65 73 20 69 74 20 61 70 70 65 61 72   makes it appear
9120: 20 74 68 61 74 20 74 68 65 79 20 61 72 65 20 68   that they are h
9130: 75 6d 61 6e 2e 20 20 43 68 65 63 6b 20 74 6f 20  uman.  Check to 
9140: 73 65 65 20 69 66 20 61 75 74 6f 2d 68 79 70 65  see if auto-hype
9150: 72 6c 69 6e 6b 20 69 73 0a 20 20 2a 2a 20 65 6e  rlink is.  ** en
9160: 61 62 6c 65 64 20 66 6f 72 20 74 68 69 73 20 72  abled for this r
9170: 65 70 6f 73 69 74 6f 72 79 20 61 6e 64 20 6d 61  epository and ma
9180: 6b 65 20 61 70 70 72 6f 70 72 69 61 74 65 20 61  ke appropriate a
9190: 64 6a 75 73 74 6d 65 6e 74 73 20 74 6f 20 74 68  djustments to th
91a0: 65 0a 20 20 2a 2a 20 70 65 72 6d 69 73 73 69 6f  e.  ** permissio
91b0: 6e 20 66 6c 61 67 73 20 69 66 20 69 74 20 69 73  n flags if it is
91c0: 2e 20 20 54 68 69 73 20 73 68 6f 75 6c 64 20 62  .  This should b
91d0: 65 20 64 6f 6e 65 20 62 65 66 6f 72 65 20 74 68  e done before th
91e0: 65 20 70 65 72 6d 69 73 73 69 6f 6e 73 0a 20 20  e permissions.  
91f0: 2a 2a 20 61 72 65 20 28 70 6f 74 65 6e 74 69 61  ** are (potentia
9200: 6c 6c 79 29 20 63 6f 70 69 65 64 20 74 6f 20 74  lly) copied to t
9210: 68 65 20 61 6e 6f 6e 79 6d 6f 75 73 20 70 65 72  he anonymous per
9220: 6d 69 73 73 69 6f 6e 20 73 65 74 3b 20 6f 74 68  mission set; oth
9230: 65 72 77 69 73 65 2c 0a 20 20 2a 2a 20 74 68 6f  erwise,.  ** tho
9240: 73 65 20 77 69 6c 6c 20 62 65 20 6f 75 74 2d 6f  se will be out-o
9250: 66 2d 73 79 6e 63 2e 0a 20 20 2a 2f 0a 20 20 69  f-sync..  */.  i
9260: 66 28 20 7a 43 61 70 5b 30 5d 0a 20 20 20 26 26  f( zCap[0].   &&
9270: 20 21 67 2e 70 65 72 6d 2e 48 79 70 65 72 6c 69   !g.perm.Hyperli
9280: 6e 6b 0a 20 20 20 26 26 20 67 2e 69 73 48 75 6d  nk.   && g.isHum
9290: 61 6e 0a 20 20 20 26 26 20 64 62 5f 67 65 74 5f  an.   && db_get_
92a0: 62 6f 6f 6c 65 61 6e 28 22 61 75 74 6f 2d 68 79  boolean("auto-hy
92b0: 70 65 72 6c 69 6e 6b 22 2c 31 29 0a 20 20 29 7b  perlink",1).  ){
92c0: 0a 20 20 20 20 67 2e 70 65 72 6d 2e 48 79 70 65  .    g.perm.Hype
92d0: 72 6c 69 6e 6b 20 3d 20 31 3b 0a 20 20 20 20 67  rlink = 1;.    g
92e0: 2e 6a 61 76 61 73 63 72 69 70 74 48 79 70 65 72  .javascriptHyper
92f0: 6c 69 6e 6b 20 3d 20 31 3b 0a 20 20 7d 0a 0a 20  link = 1;.  }.. 
9300: 20 2f 2a 0a 20 20 2a 2a 20 41 74 20 74 68 69 73   /*.  ** At this
9310: 20 70 6f 69 6e 74 2c 20 74 68 65 20 63 61 70 61   point, the capa
9320: 62 69 6c 69 74 69 65 73 20 66 6f 72 20 74 68 65  bilities for the
9330: 20 6c 6f 67 67 65 64 20 69 6e 20 75 73 65 72 20   logged in user 
9340: 61 72 65 20 6e 6f 74 20 67 6f 69 6e 67 0a 20 20  are not going.  
9350: 2a 2a 20 74 6f 20 62 65 20 6d 6f 64 69 66 69 65  ** to be modifie
9360: 64 20 61 6e 79 6d 6f 72 65 3b 20 74 68 65 72 65  d anymore; there
9370: 66 6f 72 65 2c 20 77 65 20 63 61 6e 20 63 6f 70  fore, we can cop
9380: 79 20 74 68 65 6d 20 6f 76 65 72 20 74 6f 20 74  y them over to t
9390: 68 65 20 6f 6e 65 73 0a 20 20 2a 2a 20 66 6f 72  he ones.  ** for
93a0: 20 74 68 65 20 61 6e 6f 6e 79 6d 6f 75 73 20 75   the anonymous u
93b0: 73 65 72 2e 0a 20 20 2a 2a 0a 20 20 2a 2a 20 57  ser..  **.  ** W
93c0: 41 52 4e 49 4e 47 3a 20 49 6e 20 74 68 65 20 66  ARNING: In the f
93d0: 75 74 75 72 65 2c 20 70 6c 65 61 73 65 20 64 6f  uture, please do
93e0: 20 6e 6f 74 20 61 64 64 20 63 6f 64 65 20 61 66   not add code af
93f0: 74 65 72 20 74 68 69 73 20 70 6f 69 6e 74 20 74  ter this point t
9400: 68 61 74 0a 20 20 2a 2a 20 20 20 20 20 20 20 20  hat.  **        
9410: 20 20 6d 6f 64 69 66 69 65 73 20 74 68 65 20 63    modifies the c
9420: 61 70 61 62 69 6c 69 74 69 65 73 20 66 6f 72 20  apabilities for 
9430: 74 68 65 20 6c 6f 67 67 65 64 20 69 6e 20 75 73  the logged in us
9440: 65 72 2e 0a 20 20 2a 2f 0a 20 20 6c 6f 67 69 6e  er..  */.  login
9450: 5f 73 65 74 5f 61 6e 6f 6e 5f 6e 6f 62 6f 64 79  _set_anon_nobody
9460: 5f 63 61 70 61 62 69 6c 69 74 69 65 73 28 29 3b  _capabilities();
9470: 0a 0a 20 20 2f 2a 20 49 66 20 74 68 65 20 70 75  ..  /* If the pu
9480: 62 6c 69 63 2d 70 61 67 65 73 20 67 6c 6f 62 20  blic-pages glob 
9490: 70 61 74 74 65 72 6e 20 69 73 20 64 65 66 69 6e  pattern is defin
94a0: 65 64 20 61 6e 64 20 52 45 51 55 45 53 54 5f 55  ed and REQUEST_U
94b0: 52 49 20 6d 61 74 63 68 65 73 0a 20 20 2a 2a 20  RI matches.  ** 
94c0: 6f 6e 65 20 6f 66 20 74 68 65 20 67 6c 6f 62 73  one of the globs
94d0: 20 69 6e 20 70 75 62 6c 69 63 2d 70 61 67 65 73   in public-pages
94e0: 2c 20 74 68 65 6e 20 61 6c 73 6f 20 61 64 64 20  , then also add 
94f0: 69 6e 20 61 6c 6c 20 64 65 66 61 75 6c 74 2d 70  in all default-p
9500: 65 72 6d 73 0a 20 20 2a 2a 20 70 65 72 6d 69 73  erms.  ** permis
9510: 73 69 6f 6e 73 2e 0a 20 20 2a 2f 0a 20 20 7a 50  sions..  */.  zP
9520: 75 62 6c 69 63 50 61 67 65 73 20 3d 20 64 62 5f  ublicPages = db_
9530: 67 65 74 28 22 70 75 62 6c 69 63 2d 70 61 67 65  get("public-page
9540: 73 22 2c 30 29 3b 0a 20 20 69 66 28 20 7a 50 75  s",0);.  if( zPu
9550: 62 6c 69 63 50 61 67 65 73 21 3d 30 20 29 7b 0a  blicPages!=0 ){.
9560: 20 20 20 20 47 6c 6f 62 20 2a 70 47 6c 6f 62 20      Glob *pGlob 
9570: 3d 20 67 6c 6f 62 5f 63 72 65 61 74 65 28 7a 50  = glob_create(zP
9580: 75 62 6c 69 63 50 61 67 65 73 29 3b 0a 20 20 20  ublicPages);.   
9590: 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 55 72   const char *zUr
95a0: 69 20 3d 20 50 44 28 22 52 45 51 55 45 53 54 5f  i = PD("REQUEST_
95b0: 55 52 49 22 2c 22 22 29 3b 0a 20 20 20 20 7a 55  URI","");.    zU
95c0: 72 69 20 2b 3d 20 28 69 6e 74 29 73 74 72 6c 65  ri += (int)strle
95d0: 6e 28 67 2e 7a 54 6f 70 29 3b 0a 20 20 20 20 69  n(g.zTop);.    i
95e0: 66 28 20 67 6c 6f 62 5f 6d 61 74 63 68 28 70 47  f( glob_match(pG
95f0: 6c 6f 62 2c 20 7a 55 72 69 29 20 29 7b 0a 20 20  lob, zUri) ){.  
9600: 20 20 20 20 6c 6f 67 69 6e 5f 73 65 74 5f 63 61      login_set_ca
9610: 70 61 62 69 6c 69 74 69 65 73 28 64 62 5f 67 65  pabilities(db_ge
9620: 74 28 22 64 65 66 61 75 6c 74 2d 70 65 72 6d 73  t("default-perms
9630: 22 2c 22 75 22 29 2c 20 30 29 3b 0a 20 20 20 20  ","u"), 0);.    
9640: 7d 0a 20 20 20 20 67 6c 6f 62 5f 66 72 65 65 28  }.    glob_free(
9650: 70 47 6c 6f 62 29 3b 0a 20 20 7d 0a 7d 0a 0a 2f  pGlob);.  }.}../
9660: 2a 0a 2a 2a 20 4d 65 6d 6f 72 79 20 6f 66 20 73  *.** Memory of s
9670: 65 74 74 69 6e 67 73 0a 2a 2f 0a 73 74 61 74 69  ettings.*/.stati
9680: 63 20 69 6e 74 20 6c 6f 67 69 6e 5f 61 6e 6f 6e  c int login_anon
9690: 5f 6f 6e 63 65 20 3d 20 31 3b 0a 0a 2f 2a 0a 2a  _once = 1;../*.*
96a0: 2a 20 41 64 64 20 74 6f 20 67 2e 70 65 72 6d 20  * Add to g.perm 
96b0: 74 68 65 20 64 65 66 61 75 6c 74 20 70 72 69 76  the default priv
96c0: 69 6c 65 67 65 73 20 6f 66 20 75 73 65 72 73 20  ileges of users 
96d0: 22 6e 6f 62 6f 64 79 22 20 61 6e 64 2f 6f 72 20  "nobody" and/or 
96e0: 22 61 6e 6f 6e 79 6d 6f 75 73 22 0a 2a 2a 20 61  "anonymous".** a
96f0: 73 20 61 70 70 72 6f 70 72 69 61 74 65 20 66 6f  s appropriate fo
9700: 72 20 74 68 65 20 75 73 65 72 20 67 2e 7a 4c 6f  r the user g.zLo
9710: 67 69 6e 2e 0a 2a 2a 0a 2a 2a 20 54 68 69 73 20  gin..**.** This 
9720: 72 6f 75 74 69 6e 65 20 61 6c 73 6f 20 73 65 74  routine also set
9730: 73 20 75 70 20 67 2e 61 6e 6f 6e 20 74 6f 20 62  s up g.anon to b
9740: 65 20 65 69 74 68 65 72 20 61 20 63 6f 70 79 20  e either a copy 
9750: 6f 66 20 67 2e 70 65 72 6d 20 66 6f 72 0a 2a 2a  of g.perm for.**
9760: 20 61 6c 6c 20 6c 6f 67 67 65 64 20 69 6e 20 75   all logged in u
9770: 73 65 73 2c 20 6f 72 20 74 68 65 20 70 72 69 76  ses, or the priv
9780: 69 6c 65 67 65 73 20 74 68 61 74 20 77 6f 75 6c  ileges that woul
9790: 64 20 62 65 20 61 76 61 69 6c 61 62 6c 65 20 74  d be available t
97a0: 6f 20 22 61 6e 6f 6e 79 6d 6f 75 73 22 0a 2a 2a  o "anonymous".**
97b0: 20 69 66 20 67 2e 7a 4c 6f 67 69 6e 3d 3d 30 20   if g.zLogin==0 
97c0: 28 6d 65 61 6e 69 6e 67 20 74 68 61 74 20 74 68  (meaning that th
97d0: 65 20 75 73 65 72 20 69 73 20 22 6e 6f 62 6f 64  e user is "nobod
97e0: 79 22 29 2e 0a 2a 2f 0a 76 6f 69 64 20 6c 6f 67  y")..*/.void log
97f0: 69 6e 5f 73 65 74 5f 61 6e 6f 6e 5f 6e 6f 62 6f  in_set_anon_nobo
9800: 64 79 5f 63 61 70 61 62 69 6c 69 74 69 65 73 28  dy_capabilities(
9810: 76 6f 69 64 29 7b 0a 20 20 69 66 28 20 6c 6f 67  void){.  if( log
9820: 69 6e 5f 61 6e 6f 6e 5f 6f 6e 63 65 20 29 7b 0a  in_anon_once ){.
9830: 20 20 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a      const char *
9840: 7a 43 61 70 3b 0a 20 20 20 20 2f 2a 20 41 6c 6c  zCap;.    /* All
9850: 20 75 73 65 72 73 20 67 65 74 20 70 72 69 76 69   users get privi
9860: 6c 65 67 65 73 20 66 72 6f 6d 20 22 6e 6f 62 6f  leges from "nobo
9870: 64 79 22 20 2a 2f 0a 20 20 20 20 7a 43 61 70 20  dy" */.    zCap 
9880: 3d 20 64 62 5f 74 65 78 74 28 22 22 2c 20 22 53  = db_text("", "S
9890: 45 4c 45 43 54 20 63 61 70 20 46 52 4f 4d 20 75  ELECT cap FROM u
98a0: 73 65 72 20 57 48 45 52 45 20 6c 6f 67 69 6e 20  ser WHERE login 
98b0: 3d 20 27 6e 6f 62 6f 64 79 27 22 29 3b 0a 20 20  = 'nobody'");.  
98c0: 20 20 6c 6f 67 69 6e 5f 73 65 74 5f 63 61 70 61    login_set_capa
98d0: 62 69 6c 69 74 69 65 73 28 7a 43 61 70 2c 20 30  bilities(zCap, 0
98e0: 29 3b 0a 20 20 20 20 7a 43 61 70 20 3d 20 64 62  );.    zCap = db
98f0: 5f 74 65 78 74 28 22 22 2c 20 22 53 45 4c 45 43  _text("", "SELEC
9900: 54 20 63 61 70 20 46 52 4f 4d 20 75 73 65 72 20  T cap FROM user 
9910: 57 48 45 52 45 20 6c 6f 67 69 6e 20 3d 20 27 61  WHERE login = 'a
9920: 6e 6f 6e 79 6d 6f 75 73 27 22 29 3b 0a 20 20 20  nonymous'");.   
9930: 20 69 66 28 20 67 2e 7a 4c 6f 67 69 6e 20 26 26   if( g.zLogin &&
9940: 20 66 6f 73 73 69 6c 5f 73 74 72 63 6d 70 28 67   fossil_strcmp(g
9950: 2e 7a 4c 6f 67 69 6e 2c 20 22 6e 6f 62 6f 64 79  .zLogin, "nobody
9960: 22 29 21 3d 30 20 29 7b 0a 20 20 20 20 20 20 2f  ")!=0 ){.      /
9970: 2a 20 41 6c 6c 20 6c 6f 67 67 65 64 2d 69 6e 20  * All logged-in 
9980: 75 73 65 72 73 20 69 6e 68 65 72 69 74 20 70 72  users inherit pr
9990: 69 76 69 6c 65 67 65 73 20 66 72 6f 6d 20 22 61  ivileges from "a
99a0: 6e 6f 6e 79 6d 6f 75 73 22 20 2a 2f 0a 20 20 20  nonymous" */.   
99b0: 20 20 20 6c 6f 67 69 6e 5f 73 65 74 5f 63 61 70     login_set_cap
99c0: 61 62 69 6c 69 74 69 65 73 28 7a 43 61 70 2c 20  abilities(zCap, 
99d0: 30 29 3b 0a 20 20 20 20 20 20 67 2e 61 6e 6f 6e  0);.      g.anon
99e0: 20 3d 20 67 2e 70 65 72 6d 3b 0a 20 20 20 20 7d   = g.perm;.    }
99f0: 65 6c 73 65 7b 0a 20 20 20 20 20 20 2f 2a 20 52  else{.      /* R
9a00: 65 63 6f 72 64 20 74 68 65 20 70 72 69 76 69 6c  ecord the privil
9a10: 65 67 65 73 20 6f 66 20 61 6e 6f 6e 79 6d 6f 75  eges of anonymou
9a20: 73 20 69 6e 20 67 2e 61 6e 6f 6e 20 2a 2f 0a 20  s in g.anon */. 
9a30: 20 20 20 20 20 67 2e 61 6e 6f 6e 20 3d 20 67 2e       g.anon = g.
9a40: 70 65 72 6d 3b 0a 20 20 20 20 20 20 6c 6f 67 69  perm;.      logi
9a50: 6e 5f 73 65 74 5f 63 61 70 61 62 69 6c 69 74 69  n_set_capabiliti
9a60: 65 73 28 7a 43 61 70 2c 20 4c 4f 47 49 4e 5f 41  es(zCap, LOGIN_A
9a70: 4e 4f 4e 29 3b 0a 20 20 20 20 7d 0a 20 20 20 20  NON);.    }.    
9a80: 6c 6f 67 69 6e 5f 61 6e 6f 6e 5f 6f 6e 63 65 20  login_anon_once 
9a90: 3d 20 30 3b 0a 20 20 7d 0a 7d 0a 0a 2f 2a 0a 2a  = 0;.  }.}../*.*
9aa0: 2a 20 46 6c 61 67 73 20 70 61 73 73 65 64 20 69  * Flags passed i
9ab0: 6e 74 6f 20 74 68 65 20 32 6e 64 20 61 72 67 75  nto the 2nd argu
9ac0: 6d 65 6e 74 20 6f 66 20 6c 6f 67 69 6e 5f 73 65  ment of login_se
9ad0: 74 2f 72 65 70 6c 61 63 65 5f 63 61 70 61 62 69  t/replace_capabi
9ae0: 6c 69 74 69 65 73 28 29 2e 0a 2a 2f 0a 23 69 66  lities()..*/.#if
9af0: 20 49 4e 54 45 52 46 41 43 45 0a 23 64 65 66 69   INTERFACE.#defi
9b00: 6e 65 20 4c 4f 47 49 4e 5f 49 47 4e 4f 52 45 5f  ne LOGIN_IGNORE_
9b10: 55 56 20 20 30 78 30 31 20 20 20 20 20 20 20 20  UV  0x01        
9b20: 20 2f 2a 20 49 67 6e 6f 72 65 20 22 75 22 20 61   /* Ignore "u" a
9b30: 6e 64 20 22 76 22 20 2a 2f 0a 23 64 65 66 69 6e  nd "v" */.#defin
9b40: 65 20 4c 4f 47 49 4e 5f 41 4e 4f 4e 20 20 20 20  e LOGIN_ANON    
9b50: 20 20 20 30 78 30 32 20 20 20 20 20 20 20 20 20     0x02         
9b60: 2f 2a 20 55 73 65 20 67 2e 61 6e 6f 6e 20 69 6e  /* Use g.anon in
9b70: 73 74 65 61 64 20 6f 66 20 67 2e 70 65 72 6d 20  stead of g.perm 
9b80: 2a 2f 0a 23 65 6e 64 69 66 0a 0a 2f 2a 0a 2a 2a  */.#endif../*.**
9b90: 20 41 64 64 73 20 61 6c 6c 20 63 61 70 61 62 69   Adds all capabi
9ba0: 6c 69 74 79 20 66 6c 61 67 73 20 69 6e 20 7a 43  lity flags in zC
9bb0: 61 70 20 74 6f 20 67 2e 70 65 72 6d 20 6f 72 20  ap to g.perm or 
9bc0: 67 2e 61 6e 6f 6e 2e 0a 2a 2f 0a 76 6f 69 64 20  g.anon..*/.void 
9bd0: 6c 6f 67 69 6e 5f 73 65 74 5f 63 61 70 61 62 69  login_set_capabi
9be0: 6c 69 74 69 65 73 28 63 6f 6e 73 74 20 63 68 61  lities(const cha
9bf0: 72 20 2a 7a 43 61 70 2c 20 75 6e 73 69 67 6e 65  r *zCap, unsigne
9c00: 64 20 66 6c 61 67 73 29 7b 0a 20 20 69 6e 74 20  d flags){.  int 
9c10: 69 3b 0a 20 20 46 6f 73 73 69 6c 55 73 65 72 50  i;.  FossilUserP
9c20: 65 72 6d 73 20 2a 70 20 3d 20 28 66 6c 61 67 73  erms *p = (flags
9c30: 20 26 20 4c 4f 47 49 4e 5f 41 4e 4f 4e 29 20 3f   & LOGIN_ANON) ?
9c40: 20 26 67 2e 61 6e 6f 6e 20 3a 20 26 67 2e 70 65   &g.anon : &g.pe
9c50: 72 6d 3b 0a 20 20 69 66 28 4e 55 4c 4c 3d 3d 7a  rm;.  if(NULL==z
9c60: 43 61 70 29 7b 0a 20 20 20 20 72 65 74 75 72 6e  Cap){.    return
9c70: 3b 0a 20 20 7d 0a 20 20 66 6f 72 28 69 3d 30 3b  ;.  }.  for(i=0;
9c80: 20 7a 43 61 70 5b 69 5d 3b 20 69 2b 2b 29 7b 0a   zCap[i]; i++){.
9c90: 20 20 20 20 73 77 69 74 63 68 28 20 7a 43 61 70      switch( zCap
9ca0: 5b 69 5d 20 29 7b 0a 20 20 20 20 20 20 63 61 73  [i] ){.      cas
9cb0: 65 20 27 73 27 3a 20 20 20 70 2d 3e 53 65 74 75  e 's':   p->Setu
9cc0: 70 20 3d 20 31 3b 20 2f 2a 20 46 61 6c 6c 20 74  p = 1; /* Fall t
9cd0: 68 72 75 20 69 6e 74 6f 20 41 64 6d 69 6e 20 2a  hru into Admin *
9ce0: 2f 0a 20 20 20 20 20 20 63 61 73 65 20 27 61 27  /.      case 'a'
9cf0: 3a 20 20 20 70 2d 3e 41 64 6d 69 6e 20 3d 20 70  :   p->Admin = p
9d00: 2d 3e 52 64 54 6b 74 20 3d 20 70 2d 3e 57 72 54  ->RdTkt = p->WrT
9d10: 6b 74 20 3d 20 70 2d 3e 5a 69 70 20 3d 0a 20 20  kt = p->Zip =.  
9d20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9d30: 20 20 20 20 20 20 20 20 20 20 20 70 2d 3e 52 64             p->Rd
9d40: 57 69 6b 69 20 3d 20 70 2d 3e 57 72 57 69 6b 69  Wiki = p->WrWiki
9d50: 20 3d 20 70 2d 3e 4e 65 77 57 69 6b 69 20 3d 0a   = p->NewWiki =.
9d60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9d70: 20 20 20 20 20 20 20 20 20 20 20 20 20 70 2d 3e               p->
9d80: 41 70 6e 64 57 69 6b 69 20 3d 20 70 2d 3e 48 79  ApndWiki = p->Hy
9d90: 70 65 72 6c 69 6e 6b 20 3d 20 70 2d 3e 43 6c 6f  perlink = p->Clo
9da0: 6e 65 20 3d 0a 20 20 20 20 20 20 20 20 20 20 20  ne =.           
9db0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9dc0: 20 20 70 2d 3e 4e 65 77 54 6b 74 20 3d 20 70 2d    p->NewTkt = p-
9dd0: 3e 50 61 73 73 77 6f 72 64 20 3d 20 70 2d 3e 52  >Password = p->R
9de0: 64 41 64 64 72 20 3d 0a 20 20 20 20 20 20 20 20  dAddr =.        
9df0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9e00: 20 20 20 20 20 70 2d 3e 54 6b 74 46 6d 74 20 3d       p->TktFmt =
9e10: 20 70 2d 3e 41 74 74 61 63 68 20 3d 20 70 2d 3e   p->Attach = p->
9e20: 41 70 6e 64 54 6b 74 20 3d 0a 20 20 20 20 20 20  ApndTkt =.      
9e30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9e40: 20 20 20 20 20 20 20 70 2d 3e 4d 6f 64 57 69 6b         p->ModWik
9e50: 69 20 3d 20 70 2d 3e 4d 6f 64 54 6b 74 20 3d 20  i = p->ModTkt = 
9e60: 70 2d 3e 44 65 6c 65 74 65 20 3d 0a 20 20 20 20  p->Delete =.    
9e70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9e80: 20 20 20 20 20 20 20 20 20 70 2d 3e 52 64 46 6f           p->RdFo
9e90: 72 75 6d 20 3d 20 70 2d 3e 57 72 46 6f 72 75 6d  rum = p->WrForum
9ea0: 20 3d 20 70 2d 3e 4d 6f 64 46 6f 72 75 6d 20 3d   = p->ModForum =
9eb0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
9ec0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 70 2d                p-
9ed0: 3e 57 72 54 46 6f 72 75 6d 20 3d 20 70 2d 3e 41  >WrTForum = p->A
9ee0: 64 6d 69 6e 46 6f 72 75 6d 20 3d 0a 20 20 20 20  dminForum =.    
9ef0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9f00: 20 20 20 20 20 20 20 20 20 70 2d 3e 45 6d 61 69           p->Emai
9f10: 6c 41 6c 65 72 74 20 3d 20 70 2d 3e 41 6e 6e 6f  lAlert = p->Anno
9f20: 75 6e 63 65 20 3d 20 70 2d 3e 44 65 62 75 67 20  unce = p->Debug 
9f30: 3d 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  =.              
9f40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 70                 p
9f50: 2d 3e 50 72 69 76 61 74 65 20 3d 20 31 3b 0a 20  ->Private = 1;. 
9f60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9f70: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 46              /* F
9f80: 61 6c 6c 20 74 68 72 75 20 69 6e 74 6f 20 52 65  all thru into Re
9f90: 61 64 2f 57 72 69 74 65 20 2a 2f 0a 20 20 20 20  ad/Write */.    
9fa0: 20 20 63 61 73 65 20 27 69 27 3a 20 20 20 70 2d    case 'i':   p-
9fb0: 3e 52 65 61 64 20 3d 20 70 2d 3e 57 72 69 74 65  >Read = p->Write
9fc0: 20 3d 20 31 3b 20 20 20 20 20 20 20 20 20 20 20   = 1;           
9fd0: 20 20 20 20 20 20 20 20 20 20 20 62 72 65 61 6b             break
9fe0: 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27 6f 27  ;.      case 'o'
9ff0: 3a 20 20 20 70 2d 3e 52 65 61 64 20 3d 20 31 3b  :   p->Read = 1;
a000: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a010: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a020: 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 63 61   break;.      ca
a030: 73 65 20 27 7a 27 3a 20 20 20 70 2d 3e 5a 69 70  se 'z':   p->Zip
a040: 20 3d 20 31 3b 20 20 20 20 20 20 20 20 20 20 20   = 1;           
a050: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a060: 20 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 0a 20         break;.. 
a070: 20 20 20 20 20 63 61 73 65 20 27 64 27 3a 20 20       case 'd':  
a080: 20 70 2d 3e 44 65 6c 65 74 65 20 3d 20 31 3b 20   p->Delete = 1; 
a090: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a0a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 62 72                br
a0b0: 65 61 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20  eak;.      case 
a0c0: 27 68 27 3a 20 20 20 70 2d 3e 48 79 70 65 72 6c  'h':   p->Hyperl
a0d0: 69 6e 6b 20 3d 20 31 3b 20 20 20 20 20 20 20 20  ink = 1;        
a0e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a0f0: 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20      break;.     
a100: 20 63 61 73 65 20 27 67 27 3a 20 20 20 70 2d 3e   case 'g':   p->
a110: 43 6c 6f 6e 65 20 3d 20 31 3b 20 20 20 20 20 20  Clone = 1;      
a120: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a130: 20 20 20 20 20 20 20 20 20 20 62 72 65 61 6b 3b            break;
a140: 0a 20 20 20 20 20 20 63 61 73 65 20 27 70 27 3a  .      case 'p':
a150: 20 20 20 70 2d 3e 50 61 73 73 77 6f 72 64 20 3d     p->Password =
a160: 20 31 3b 20 20 20 20 20 20 20 20 20 20 20 20 20   1;             
a170: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a180: 62 72 65 61 6b 3b 0a 0a 20 20 20 20 20 20 63 61  break;..      ca
a190: 73 65 20 27 6a 27 3a 20 20 20 70 2d 3e 52 64 57  se 'j':   p->RdW
a1a0: 69 6b 69 20 3d 20 31 3b 20 20 20 20 20 20 20 20  iki = 1;        
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 62 72 65 61 6b 3b 0a 20 20         break;.  
a1d0: 20 20 20 20 63 61 73 65 20 27 6b 27 3a 20 20 20      case 'k':   
a1e0: 70 2d 3e 57 72 57 69 6b 69 20 3d 20 70 2d 3e 52  p->WrWiki = p->R
a1f0: 64 57 69 6b 69 20 3d 20 70 2d 3e 41 70 6e 64 57  dWiki = p->ApndW
a200: 69 6b 69 20 3d 31 3b 20 20 20 20 20 20 62 72 65  iki =1;      bre
a210: 61 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27  ak;.      case '
a220: 6d 27 3a 20 20 20 70 2d 3e 41 70 6e 64 57 69 6b  m':   p->ApndWik
a230: 69 20 3d 20 31 3b 20 20 20 20 20 20 20 20 20 20  i = 1;          
a240: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a250: 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20     break;.      
a260: 63 61 73 65 20 27 66 27 3a 20 20 20 70 2d 3e 4e  case 'f':   p->N
a270: 65 77 57 69 6b 69 20 3d 20 31 3b 20 20 20 20 20  ewWiki = 1;     
a280: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a290: 20 20 20 20 20 20 20 20 20 62 72 65 61 6b 3b 0a           break;.
a2a0: 20 20 20 20 20 20 63 61 73 65 20 27 6c 27 3a 20        case 'l': 
a2b0: 20 20 70 2d 3e 4d 6f 64 57 69 6b 69 20 3d 20 31    p->ModWiki = 1
a2c0: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ;               
a2d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 62                 b
a2e0: 72 65 61 6b 3b 0a 0a 20 20 20 20 20 20 63 61 73  reak;..      cas
a2f0: 65 20 27 65 27 3a 20 20 20 70 2d 3e 52 64 41 64  e 'e':   p->RdAd
a300: 64 72 20 3d 20 31 3b 20 20 20 20 20 20 20 20 20  dr = 1;         
a310: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a320: 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20        break;.   
a330: 20 20 20 63 61 73 65 20 27 72 27 3a 20 20 20 70     case 'r':   p
a340: 2d 3e 52 64 54 6b 74 20 3d 20 31 3b 20 20 20 20  ->RdTkt = 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 20 20 20 20 20 62 72 65 61              brea
a370: 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27 6e  k;.      case 'n
a380: 27 3a 20 20 20 70 2d 3e 4e 65 77 54 6b 74 20 3d  ':   p->NewTkt =
a390: 20 31 3b 20 20 20 20 20 20 20 20 20 20 20 20 20   1;             
a3a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a3b0: 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 63    break;.      c
a3c0: 61 73 65 20 27 77 27 3a 20 20 20 70 2d 3e 57 72  ase 'w':   p->Wr
a3d0: 54 6b 74 20 3d 20 70 2d 3e 52 64 54 6b 74 20 3d  Tkt = p->RdTkt =
a3e0: 20 70 2d 3e 4e 65 77 54 6b 74 20 3d 0a 20 20 20   p->NewTkt =.   
a3f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 70                 p
a400: 2d 3e 41 70 6e 64 54 6b 74 20 3d 20 31 3b 20 20  ->ApndTkt = 1;  
a410: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a420: 20 20 20 20 20 20 20 20 20 20 20 20 62 72 65 61              brea
a430: 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27 63  k;.      case 'c
a440: 27 3a 20 20 20 70 2d 3e 41 70 6e 64 54 6b 74 20  ':   p->ApndTkt 
a450: 3d 20 31 3b 20 20 20 20 20 20 20 20 20 20 20 20  = 1;            
a460: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a470: 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 63    break;.      c
a480: 61 73 65 20 27 71 27 3a 20 20 20 70 2d 3e 4d 6f  ase 'q':   p->Mo
a490: 64 54 6b 74 20 3d 20 31 3b 20 20 20 20 20 20 20  dTkt = 1;       
a4a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a4b0: 20 20 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20          break;. 
a4c0: 20 20 20 20 20 63 61 73 65 20 27 74 27 3a 20 20       case 't':  
a4d0: 20 70 2d 3e 54 6b 74 46 6d 74 20 3d 20 31 3b 20   p->TktFmt = 1; 
a4e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a4f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 62 72                br
a500: 65 61 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20  eak;.      case 
a510: 27 62 27 3a 20 20 20 70 2d 3e 41 74 74 61 63 68  'b':   p->Attach
a520: 20 3d 20 31 3b 20 20 20 20 20 20 20 20 20 20 20   = 1;           
a530: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a540: 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20      break;.     
a550: 20 63 61 73 65 20 27 78 27 3a 20 20 20 70 2d 3e   case 'x':   p->
a560: 50 72 69 76 61 74 65 20 3d 20 31 3b 20 20 20 20  Private = 1;    
a570: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a580: 20 20 20 20 20 20 20 20 20 20 62 72 65 61 6b 3b            break;
a590: 0a 20 20 20 20 20 20 63 61 73 65 20 27 79 27 3a  .      case 'y':
a5a0: 20 20 20 70 2d 3e 57 72 55 6e 76 65 72 20 3d 20     p->WrUnver = 
a5b0: 31 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20  1;              
a5c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a5d0: 62 72 65 61 6b 3b 0a 0a 20 20 20 20 20 20 63 61  break;..      ca
a5e0: 73 65 20 27 36 27 3a 20 20 20 70 2d 3e 41 64 6d  se '6':   p->Adm
a5f0: 69 6e 46 6f 72 75 6d 20 3d 20 31 3b 0a 20 20 20  inForum = 1;.   
a600: 20 20 20 63 61 73 65 20 27 35 27 3a 20 20 20 70     case '5':   p
a610: 2d 3e 4d 6f 64 46 6f 72 75 6d 20 3d 20 31 3b 0a  ->ModForum = 1;.
a620: 20 20 20 20 20 20 63 61 73 65 20 27 34 27 3a 20        case '4': 
a630: 20 20 70 2d 3e 57 72 54 46 6f 72 75 6d 20 3d 20    p->WrTForum = 
a640: 31 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27 33  1;.      case '3
a650: 27 3a 20 20 20 70 2d 3e 57 72 46 6f 72 75 6d 20  ':   p->WrForum 
a660: 3d 20 31 3b 0a 20 20 20 20 20 20 63 61 73 65 20  = 1;.      case 
a670: 27 32 27 3a 20 20 20 70 2d 3e 52 64 46 6f 72 75  '2':   p->RdForu
a680: 6d 20 3d 20 31 3b 20 20 20 20 20 20 20 20 20 20  m = 1;          
a690: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a6a0: 20 20 20 20 62 72 65 61 6b 3b 0a 0a 20 20 20 20      break;..    
a6b0: 20 20 63 61 73 65 20 27 37 27 3a 20 20 20 70 2d    case '7':   p-
a6c0: 3e 45 6d 61 69 6c 41 6c 65 72 74 20 3d 20 31 3b  >EmailAlert = 1;
a6d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a6e0: 20 20 20 20 20 20 20 20 20 20 20 62 72 65 61 6b             break
a6f0: 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27 41 27  ;.      case 'A'
a700: 3a 20 20 20 70 2d 3e 41 6e 6e 6f 75 6e 63 65 20  :   p->Announce 
a710: 3d 20 31 3b 20 20 20 20 20 20 20 20 20 20 20 20  = 1;            
a720: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a730: 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 63 61   break;.      ca
a740: 73 65 20 27 44 27 3a 20 20 20 70 2d 3e 44 65 62  se 'D':   p->Deb
a750: 75 67 20 3d 20 31 3b 20 20 20 20 20 20 20 20 20  ug = 1;         
a760: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a770: 20 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 0a 20         break;.. 
a780: 20 20 20 20 20 2f 2a 20 54 68 65 20 22 75 22 20       /* The "u" 
a790: 70 72 69 76 69 6c 65 67 65 20 72 65 63 75 72 73  privilege recurs
a7a0: 69 76 65 6c 79 0a 20 20 20 20 20 20 2a 2a 20 69  ively.      ** i
a7b0: 6e 68 65 72 69 74 73 20 61 6c 6c 20 70 72 69 76  nherits all priv
a7c0: 69 6c 65 67 65 73 20 6f 66 20 74 68 65 20 75 73  ileges of the us
a7d0: 65 72 20 6e 61 6d 65 64 20 22 72 65 61 64 65 72  er named "reader
a7e0: 22 20 2a 2f 0a 20 20 20 20 20 20 63 61 73 65 20  " */.      case 
a7f0: 27 75 27 3a 20 7b 0a 20 20 20 20 20 20 20 20 69  'u': {.        i
a800: 66 28 20 70 2d 3e 58 52 65 61 64 65 72 3d 3d 30  f( p->XReader==0
a810: 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20 63 6f   ){.          co
a820: 6e 73 74 20 63 68 61 72 20 2a 7a 55 73 65 72 3b  nst char *zUser;
a830: 0a 20 20 20 20 20 20 20 20 20 20 70 2d 3e 58 52  .          p->XR
a840: 65 61 64 65 72 20 3d 20 31 3b 0a 20 20 20 20 20  eader = 1;.     
a850: 20 20 20 20 20 7a 55 73 65 72 20 3d 20 64 62 5f       zUser = db_
a860: 74 65 78 74 28 22 22 2c 20 22 53 45 4c 45 43 54  text("", "SELECT
a870: 20 63 61 70 20 46 52 4f 4d 20 75 73 65 72 20 57   cap FROM user W
a880: 48 45 52 45 20 6c 6f 67 69 6e 3d 27 72 65 61 64  HERE login='read
a890: 65 72 27 22 29 3b 0a 20 20 20 20 20 20 20 20 20  er'");.         
a8a0: 20 6c 6f 67 69 6e 5f 73 65 74 5f 63 61 70 61 62   login_set_capab
a8b0: 69 6c 69 74 69 65 73 28 7a 55 73 65 72 2c 20 66  ilities(zUser, f
a8c0: 6c 61 67 73 29 3b 0a 20 20 20 20 20 20 20 20 7d  lags);.        }
a8d0: 0a 20 20 20 20 20 20 20 20 62 72 65 61 6b 3b 0a  .        break;.
a8e0: 20 20 20 20 20 20 7d 0a 0a 20 20 20 20 20 20 2f        }..      /
a8f0: 2a 20 54 68 65 20 22 76 22 20 70 72 69 76 69 6c  * The "v" privil
a900: 65 67 65 20 72 65 63 75 72 73 69 76 65 6c 79 0a  ege recursively.
a910: 20 20 20 20 20 20 2a 2a 20 69 6e 68 65 72 69 74        ** inherit
a920: 73 20 61 6c 6c 20 70 72 69 76 69 6c 65 67 65 73  s all privileges
a930: 20 6f 66 20 74 68 65 20 75 73 65 72 20 6e 61 6d   of the user nam
a940: 65 64 20 22 64 65 76 65 6c 6f 70 65 72 22 20 2a  ed "developer" *
a950: 2f 0a 20 20 20 20 20 20 63 61 73 65 20 27 76 27  /.      case 'v'
a960: 3a 20 7b 0a 20 20 20 20 20 20 20 20 69 66 28 20  : {.        if( 
a970: 70 2d 3e 58 44 65 76 65 6c 6f 70 65 72 3d 3d 30  p->XDeveloper==0
a980: 20 29 7b 0a 20 20 20 20 20 20 20 20 20 20 63 6f   ){.          co
a990: 6e 73 74 20 63 68 61 72 20 2a 7a 44 65 76 3b 0a  nst char *zDev;.
a9a0: 20 20 20 20 20 20 20 20 20 20 70 2d 3e 58 44 65            p->XDe
a9b0: 76 65 6c 6f 70 65 72 20 3d 20 31 3b 0a 20 20 20  veloper = 1;.   
a9c0: 20 20 20 20 20 20 20 7a 44 65 76 20 3d 20 64 62         zDev = db
a9d0: 5f 74 65 78 74 28 22 22 2c 20 22 53 45 4c 45 43  _text("", "SELEC
a9e0: 54 20 63 61 70 20 46 52 4f 4d 20 75 73 65 72 20  T cap FROM user 
a9f0: 57 48 45 52 45 20 6c 6f 67 69 6e 3d 27 64 65 76  WHERE login='dev
aa00: 65 6c 6f 70 65 72 27 22 29 3b 0a 20 20 20 20 20  eloper'");.     
aa10: 20 20 20 20 20 6c 6f 67 69 6e 5f 73 65 74 5f 63       login_set_c
aa20: 61 70 61 62 69 6c 69 74 69 65 73 28 7a 44 65 76  apabilities(zDev
aa30: 2c 20 66 6c 61 67 73 29 3b 0a 20 20 20 20 20 20  , flags);.      
aa40: 20 20 7d 0a 20 20 20 20 20 20 20 20 62 72 65 61    }.        brea
aa50: 6b 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 7d  k;.      }.    }
aa60: 0a 20 20 7d 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 5a 65  .  }.}../*.** Ze
aa70: 72 6f 65 73 20 6f 75 74 20 67 2e 70 65 72 6d 20  roes out g.perm 
aa80: 61 6e 64 20 63 61 6c 6c 73 20 6c 6f 67 69 6e 5f  and calls login_
aa90: 73 65 74 5f 63 61 70 61 62 69 6c 69 74 69 65 73  set_capabilities
aaa0: 28 7a 43 61 70 2c 66 6c 61 67 73 29 2e 0a 2a 2f  (zCap,flags)..*/
aab0: 0a 76 6f 69 64 20 6c 6f 67 69 6e 5f 72 65 70 6c  .void login_repl
aac0: 61 63 65 5f 63 61 70 61 62 69 6c 69 74 69 65 73  ace_capabilities
aad0: 28 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 43 61  (const char *zCa
aae0: 70 2c 20 75 6e 73 69 67 6e 65 64 20 66 6c 61 67  p, unsigned flag
aaf0: 73 29 7b 0a 20 20 6d 65 6d 73 65 74 28 26 67 2e  s){.  memset(&g.
ab00: 70 65 72 6d 2c 20 30 2c 20 73 69 7a 65 6f 66 28  perm, 0, sizeof(
ab10: 67 2e 70 65 72 6d 29 29 3b 0a 20 20 6c 6f 67 69  g.perm));.  logi
ab20: 6e 5f 73 65 74 5f 63 61 70 61 62 69 6c 69 74 69  n_set_capabiliti
ab30: 65 73 28 7a 43 61 70 2c 20 66 6c 61 67 73 29 3b  es(zCap, flags);
ab40: 0a 20 20 6c 6f 67 69 6e 5f 61 6e 6f 6e 5f 6f 6e  .  login_anon_on
ab50: 63 65 20 3d 20 31 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a  ce = 1;.}../*.**
ab60: 20 49 66 20 74 68 65 20 63 75 72 72 65 6e 74 20   If the current 
ab70: 6c 6f 67 69 6e 20 6c 61 63 6b 73 20 61 6e 79 20  login lacks any 
ab80: 6f 66 20 74 68 65 20 63 61 70 61 62 69 6c 69 74  of the capabilit
ab90: 69 65 73 20 6c 69 73 74 65 64 20 69 6e 0a 2a 2a  ies listed in.**
aba0: 20 74 68 65 20 69 6e 70 75 74 2c 20 74 68 65 6e   the input, then
abb0: 20 72 65 74 75 72 6e 20 30 2e 20 20 49 66 20 61   return 0.  If a
abc0: 6c 6c 20 63 61 70 61 62 69 6c 69 74 69 65 73 20  ll capabilities 
abd0: 61 72 65 20 70 72 65 73 65 6e 74 2c 20 74 68 65  are present, the
abe0: 6e 0a 2a 2a 20 72 65 74 75 72 6e 20 31 2e 0a 2a  n.** return 1..*
abf0: 2f 0a 69 6e 74 20 6c 6f 67 69 6e 5f 68 61 73 5f  /.int login_has_
ac00: 63 61 70 61 62 69 6c 69 74 79 28 63 6f 6e 73 74  capability(const
ac10: 20 63 68 61 72 20 2a 7a 43 61 70 2c 20 69 6e 74   char *zCap, int
ac20: 20 6e 43 61 70 2c 20 75 33 32 20 66 6c 67 73 29   nCap, u32 flgs)
ac30: 7b 0a 20 20 69 6e 74 20 69 3b 0a 20 20 69 6e 74  {.  int i;.  int
ac40: 20 72 63 20 3d 20 31 3b 0a 20 20 46 6f 73 73 69   rc = 1;.  Fossi
ac50: 6c 55 73 65 72 50 65 72 6d 73 20 2a 70 20 3d 20  lUserPerms *p = 
ac60: 28 66 6c 67 73 20 26 20 4c 4f 47 49 4e 5f 41 4e  (flgs & LOGIN_AN
ac70: 4f 4e 29 20 3f 20 26 67 2e 61 6e 6f 6e 20 3a 20  ON) ? &g.anon : 
ac80: 26 67 2e 70 65 72 6d 3b 0a 20 20 69 66 28 20 6e  &g.perm;.  if( n
ac90: 43 61 70 3c 30 20 29 20 6e 43 61 70 20 3d 20 73  Cap<0 ) nCap = s
aca0: 74 72 6c 65 6e 28 7a 43 61 70 29 3b 0a 20 20 66  trlen(zCap);.  f
acb0: 6f 72 28 69 3d 30 3b 20 69 3c 6e 43 61 70 20 26  or(i=0; i<nCap &
acc0: 26 20 72 63 20 26 26 20 7a 43 61 70 5b 69 5d 3b  & rc && zCap[i];
acd0: 20 69 2b 2b 29 7b 0a 20 20 20 20 73 77 69 74 63   i++){.    switc
ace0: 68 28 20 7a 43 61 70 5b 69 5d 20 29 7b 0a 20 20  h( zCap[i] ){.  
acf0: 20 20 20 20 63 61 73 65 20 27 61 27 3a 20 20 72      case 'a':  r
ad00: 63 20 3d 20 70 2d 3e 41 64 6d 69 6e 3b 20 20 20  c = p->Admin;   
ad10: 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 63    break;.      c
ad20: 61 73 65 20 27 62 27 3a 20 20 72 63 20 3d 20 70  ase 'b':  rc = p
ad30: 2d 3e 41 74 74 61 63 68 3b 20 20 20 20 62 72 65  ->Attach;    bre
ad40: 61 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27  ak;.      case '
ad50: 63 27 3a 20 20 72 63 20 3d 20 70 2d 3e 41 70 6e  c':  rc = p->Apn
ad60: 64 54 6b 74 3b 20 20 20 62 72 65 61 6b 3b 0a 20  dTkt;   break;. 
ad70: 20 20 20 20 20 63 61 73 65 20 27 64 27 3a 20 20       case 'd':  
ad80: 72 63 20 3d 20 70 2d 3e 44 65 6c 65 74 65 3b 20  rc = p->Delete; 
ad90: 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20     break;.      
ada0: 63 61 73 65 20 27 65 27 3a 20 20 72 63 20 3d 20  case 'e':  rc = 
adb0: 70 2d 3e 52 64 41 64 64 72 3b 20 20 20 20 62 72  p->RdAddr;    br
adc0: 65 61 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20  eak;.      case 
add0: 27 66 27 3a 20 20 72 63 20 3d 20 70 2d 3e 4e 65  'f':  rc = p->Ne
ade0: 77 57 69 6b 69 3b 20 20 20 62 72 65 61 6b 3b 0a  wWiki;   break;.
adf0: 20 20 20 20 20 20 63 61 73 65 20 27 67 27 3a 20        case 'g': 
ae00: 20 72 63 20 3d 20 70 2d 3e 43 6c 6f 6e 65 3b 20   rc = p->Clone; 
ae10: 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20      break;.     
ae20: 20 63 61 73 65 20 27 68 27 3a 20 20 72 63 20 3d   case 'h':  rc =
ae30: 20 70 2d 3e 48 79 70 65 72 6c 69 6e 6b 3b 20 62   p->Hyperlink; b
ae40: 72 65 61 6b 3b 0a 20 20 20 20 20 20 63 61 73 65  reak;.      case
ae50: 20 27 69 27 3a 20 20 72 63 20 3d 20 70 2d 3e 57   'i':  rc = p->W
ae60: 72 69 74 65 3b 20 20 20 20 20 62 72 65 61 6b 3b  rite;     break;
ae70: 0a 20 20 20 20 20 20 63 61 73 65 20 27 6a 27 3a  .      case 'j':
ae80: 20 20 72 63 20 3d 20 70 2d 3e 52 64 57 69 6b 69    rc = p->RdWiki
ae90: 3b 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20  ;    break;.    
aea0: 20 20 63 61 73 65 20 27 6b 27 3a 20 20 72 63 20    case 'k':  rc 
aeb0: 3d 20 70 2d 3e 57 72 57 69 6b 69 3b 20 20 20 20  = p->WrWiki;    
aec0: 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 63 61 73  break;.      cas
aed0: 65 20 27 6c 27 3a 20 20 72 63 20 3d 20 70 2d 3e  e 'l':  rc = p->
aee0: 4d 6f 64 57 69 6b 69 3b 20 20 20 62 72 65 61 6b  ModWiki;   break
aef0: 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27 6d 27  ;.      case 'm'
af00: 3a 20 20 72 63 20 3d 20 70 2d 3e 41 70 6e 64 57  :  rc = p->ApndW
af10: 69 6b 69 3b 20 20 62 72 65 61 6b 3b 0a 20 20 20  iki;  break;.   
af20: 20 20 20 63 61 73 65 20 27 6e 27 3a 20 20 72 63     case 'n':  rc
af30: 20 3d 20 70 2d 3e 4e 65 77 54 6b 74 3b 20 20 20   = p->NewTkt;   
af40: 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 63 61   break;.      ca
af50: 73 65 20 27 6f 27 3a 20 20 72 63 20 3d 20 70 2d  se 'o':  rc = p-
af60: 3e 52 65 61 64 3b 20 20 20 20 20 20 62 72 65 61  >Read;      brea
af70: 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27 70  k;.      case 'p
af80: 27 3a 20 20 72 63 20 3d 20 70 2d 3e 50 61 73 73  ':  rc = p->Pass
af90: 77 6f 72 64 3b 20 20 62 72 65 61 6b 3b 0a 20 20  word;  break;.  
afa0: 20 20 20 20 63 61 73 65 20 27 71 27 3a 20 20 72      case 'q':  r
afb0: 63 20 3d 20 70 2d 3e 4d 6f 64 54 6b 74 3b 20 20  c = p->ModTkt;  
afc0: 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 63    break;.      c
afd0: 61 73 65 20 27 72 27 3a 20 20 72 63 20 3d 20 70  ase 'r':  rc = p
afe0: 2d 3e 52 64 54 6b 74 3b 20 20 20 20 20 62 72 65  ->RdTkt;     bre
aff0: 61 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27  ak;.      case '
b000: 73 27 3a 20 20 72 63 20 3d 20 70 2d 3e 53 65 74  s':  rc = p->Set
b010: 75 70 3b 20 20 20 20 20 62 72 65 61 6b 3b 0a 20  up;     break;. 
b020: 20 20 20 20 20 63 61 73 65 20 27 74 27 3a 20 20       case 't':  
b030: 72 63 20 3d 20 70 2d 3e 54 6b 74 46 6d 74 3b 20  rc = p->TktFmt; 
b040: 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20     break;.      
b050: 2f 2a 20 63 61 73 65 20 27 75 27 3a 20 52 45 41  /* case 'u': REA
b060: 44 45 52 20 20 20 20 2a 2f 0a 20 20 20 20 20 20  DER    */.      
b070: 2f 2a 20 63 61 73 65 20 27 76 27 3a 20 44 45 56  /* case 'v': DEV
b080: 45 4c 4f 50 45 52 20 2a 2f 0a 20 20 20 20 20 20  ELOPER */.      
b090: 63 61 73 65 20 27 77 27 3a 20 20 72 63 20 3d 20  case 'w':  rc = 
b0a0: 70 2d 3e 57 72 54 6b 74 3b 20 20 20 20 20 62 72  p->WrTkt;     br
b0b0: 65 61 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20  eak;.      case 
b0c0: 27 78 27 3a 20 20 72 63 20 3d 20 70 2d 3e 50 72  'x':  rc = p->Pr
b0d0: 69 76 61 74 65 3b 20 20 20 62 72 65 61 6b 3b 0a  ivate;   break;.
b0e0: 20 20 20 20 20 20 63 61 73 65 20 27 79 27 3a 20        case 'y': 
b0f0: 20 72 63 20 3d 20 70 2d 3e 57 72 55 6e 76 65 72   rc = p->WrUnver
b100: 3b 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20  ;   break;.     
b110: 20 63 61 73 65 20 27 7a 27 3a 20 20 72 63 20 3d   case 'z':  rc =
b120: 20 70 2d 3e 5a 69 70 3b 20 20 20 20 20 20 20 62   p->Zip;       b
b130: 72 65 61 6b 3b 0a 20 20 20 20 20 20 63 61 73 65  reak;.      case
b140: 20 27 32 27 3a 20 20 72 63 20 3d 20 70 2d 3e 52   '2':  rc = p->R
b150: 64 46 6f 72 75 6d 3b 20 20 20 62 72 65 61 6b 3b  dForum;   break;
b160: 0a 20 20 20 20 20 20 63 61 73 65 20 27 33 27 3a  .      case '3':
b170: 20 20 72 63 20 3d 20 70 2d 3e 57 72 46 6f 72 75    rc = p->WrForu
b180: 6d 3b 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20  m;   break;.    
b190: 20 20 63 61 73 65 20 27 34 27 3a 20 20 72 63 20    case '4':  rc 
b1a0: 3d 20 70 2d 3e 57 72 54 46 6f 72 75 6d 3b 20 20  = p->WrTForum;  
b1b0: 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 63 61 73  break;.      cas
b1c0: 65 20 27 35 27 3a 20 20 72 63 20 3d 20 70 2d 3e  e '5':  rc = p->
b1d0: 4d 6f 64 46 6f 72 75 6d 3b 20 20 62 72 65 61 6b  ModForum;  break
b1e0: 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27 36 27  ;.      case '6'
b1f0: 3a 20 20 72 63 20 3d 20 70 2d 3e 41 64 6d 69 6e  :  rc = p->Admin
b200: 46 6f 72 75 6d 3b 62 72 65 61 6b 3b 0a 20 20 20  Forum;break;.   
b210: 20 20 20 63 61 73 65 20 27 37 27 3a 20 20 72 63     case '7':  rc
b220: 20 3d 20 70 2d 3e 45 6d 61 69 6c 41 6c 65 72 74   = p->EmailAlert
b230: 3b 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 63 61  ;break;.      ca
b240: 73 65 20 27 41 27 3a 20 20 72 63 20 3d 20 70 2d  se 'A':  rc = p-
b250: 3e 41 6e 6e 6f 75 6e 63 65 3b 20 20 62 72 65 61  >Announce;  brea
b260: 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27 44  k;.      case 'D
b270: 27 3a 20 20 72 63 20 3d 20 70 2d 3e 44 65 62 75  ':  rc = p->Debu
b280: 67 3b 20 20 20 20 20 62 72 65 61 6b 3b 0a 20 20  g;     break;.  
b290: 20 20 20 20 64 65 66 61 75 6c 74 3a 20 20 20 72      default:   r
b2a0: 63 20 3d 20 30 3b 20 20 20 20 20 20 20 20 20 20  c = 0;          
b2b0: 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 7d 0a 20    break;.    }. 
b2c0: 20 7d 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a   }.  return rc;.
b2d0: 7d 0a 0a 2f 2a 0a 2a 2a 20 43 68 61 6e 67 65 20  }../*.** Change 
b2e0: 74 68 65 20 6c 6f 67 69 6e 20 74 6f 20 7a 55 73  the login to zUs
b2f0: 65 72 2e 0a 2a 2f 0a 76 6f 69 64 20 6c 6f 67 69  er..*/.void logi
b300: 6e 5f 61 73 5f 75 73 65 72 28 63 6f 6e 73 74 20  n_as_user(const 
b310: 63 68 61 72 20 2a 7a 55 73 65 72 29 7b 0a 20 20  char *zUser){.  
b320: 63 68 61 72 20 2a 7a 43 61 70 20 3d 20 22 22 3b  char *zCap = "";
b330: 20 20 20 2f 2a 20 4e 65 77 20 63 61 70 61 62 69     /* New capabi
b340: 6c 69 74 69 65 73 20 2a 2f 0a 0a 20 20 2f 2a 20  lities */..  /* 
b350: 54 75 72 6e 20 6f 66 66 20 61 6c 6c 20 63 61 70  Turn off all cap
b360: 61 62 69 6c 69 74 69 65 73 20 66 72 6f 6d 20 70  abilities from p
b370: 72 69 6f 72 20 6c 6f 67 69 6e 73 20 2a 2f 0a 20  rior logins */. 
b380: 20 6d 65 6d 73 65 74 28 20 26 67 2e 70 65 72 6d   memset( &g.perm
b390: 2c 20 30 2c 20 73 69 7a 65 6f 66 28 67 2e 70 65  , 0, sizeof(g.pe
b3a0: 72 6d 29 20 29 3b 0a 0a 20 20 2f 2a 20 53 65 74  rm) );..  /* Set
b3b0: 20 74 68 65 20 67 6c 6f 62 61 6c 20 76 61 72 69   the global vari
b3c0: 61 62 6c 65 73 20 72 65 63 6f 72 64 69 6e 67 20  ables recording 
b3d0: 74 68 65 20 75 73 65 72 69 64 20 61 6e 64 20 6c  the userid and l
b3e0: 6f 67 69 6e 2e 20 20 54 68 65 0a 20 20 2a 2a 20  ogin.  The.  ** 
b3f0: 22 6e 6f 62 6f 64 79 22 20 75 73 65 72 20 69 73  "nobody" user is
b400: 20 61 20 73 70 65 63 69 61 6c 20 63 61 73 65 20   a special case 
b410: 69 6e 20 74 68 61 74 20 67 2e 7a 4c 6f 67 69 6e  in that g.zLogin
b420: 3d 3d 30 2e 0a 20 20 2a 2f 0a 20 20 67 2e 75 73  ==0..  */.  g.us
b430: 65 72 55 69 64 20 3d 20 64 62 5f 69 6e 74 28 30  erUid = db_int(0
b440: 2c 20 22 53 45 4c 45 43 54 20 75 69 64 20 46 52  , "SELECT uid FR
b450: 4f 4d 20 75 73 65 72 20 57 48 45 52 45 20 6c 6f  OM user WHERE lo
b460: 67 69 6e 3d 25 51 22 2c 20 7a 55 73 65 72 29 3b  gin=%Q", zUser);
b470: 0a 20 20 69 66 28 20 67 2e 75 73 65 72 55 69 64  .  if( g.userUid
b480: 3d 3d 30 20 29 7b 0a 20 20 20 20 7a 55 73 65 72  ==0 ){.    zUser
b490: 20 3d 20 30 3b 0a 20 20 20 20 67 2e 75 73 65 72   = 0;.    g.user
b4a0: 55 69 64 20 3d 20 64 62 5f 69 6e 74 28 30 2c 20  Uid = db_int(0, 
b4b0: 22 53 45 4c 45 43 54 20 75 69 64 20 46 52 4f 4d  "SELECT uid FROM
b4c0: 20 75 73 65 72 20 57 48 45 52 45 20 6c 6f 67 69   user WHERE logi
b4d0: 6e 3d 27 6e 6f 62 6f 64 79 27 22 29 3b 0a 20 20  n='nobody'");.  
b4e0: 7d 0a 20 20 69 66 28 20 67 2e 75 73 65 72 55 69  }.  if( g.userUi
b4f0: 64 20 29 7b 0a 20 20 20 20 7a 43 61 70 20 3d 20  d ){.    zCap = 
b500: 64 62 5f 74 65 78 74 28 22 22 2c 20 22 53 45 4c  db_text("", "SEL
b510: 45 43 54 20 63 61 70 20 46 52 4f 4d 20 75 73 65  ECT cap FROM use
b520: 72 20 57 48 45 52 45 20 75 69 64 3d 25 64 22 2c  r WHERE uid=%d",
b530: 20 67 2e 75 73 65 72 55 69 64 29 3b 0a 20 20 7d   g.userUid);.  }
b540: 0a 20 20 69 66 28 20 66 6f 73 73 69 6c 5f 73 74  .  if( fossil_st
b550: 72 63 6d 70 28 7a 55 73 65 72 2c 22 6e 6f 62 6f  rcmp(zUser,"nobo
b560: 64 79 22 29 3d 3d 30 20 29 20 7a 55 73 65 72 20  dy")==0 ) zUser 
b570: 3d 20 30 3b 0a 20 20 67 2e 7a 4c 6f 67 69 6e 20  = 0;.  g.zLogin 
b580: 3d 20 66 6f 73 73 69 6c 5f 73 74 72 64 75 70 28  = fossil_strdup(
b590: 7a 55 73 65 72 29 3b 0a 0a 20 20 2f 2a 20 53 65  zUser);..  /* Se
b5a0: 74 20 74 68 65 20 63 61 70 61 62 69 6c 69 74 69  t the capabiliti
b5b0: 65 73 20 2a 2f 0a 20 20 6c 6f 67 69 6e 5f 73 65  es */.  login_se
b5c0: 74 5f 63 61 70 61 62 69 6c 69 74 69 65 73 28 7a  t_capabilities(z
b5d0: 43 61 70 2c 20 30 29 3b 0a 20 20 6c 6f 67 69 6e  Cap, 0);.  login
b5e0: 5f 61 6e 6f 6e 5f 6f 6e 63 65 20 3d 20 31 3b 0a  _anon_once = 1;.
b5f0: 20 20 6c 6f 67 69 6e 5f 73 65 74 5f 61 6e 6f 6e    login_set_anon
b600: 5f 6e 6f 62 6f 64 79 5f 63 61 70 61 62 69 6c 69  _nobody_capabili
b610: 74 69 65 73 28 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a  ties();.}../*.**
b620: 20 52 65 74 75 72 6e 20 74 72 75 65 20 69 66 20   Return true if 
b630: 74 68 65 20 75 73 65 72 20 69 73 20 22 6e 6f 62  the user is "nob
b640: 6f 64 79 22 0a 2a 2f 0a 69 6e 74 20 6c 6f 67 69  ody".*/.int logi
b650: 6e 5f 69 73 5f 6e 6f 62 6f 64 79 28 76 6f 69 64  n_is_nobody(void
b660: 29 7b 0a 20 20 72 65 74 75 72 6e 20 67 2e 7a 4c  ){.  return g.zL
b670: 6f 67 69 6e 3d 3d 30 20 7c 7c 20 67 2e 7a 4c 6f  ogin==0 || g.zLo
b680: 67 69 6e 5b 30 5d 3d 3d 30 20 7c 7c 20 66 6f 73  gin[0]==0 || fos
b690: 73 69 6c 5f 73 74 72 63 6d 70 28 67 2e 7a 4c 6f  sil_strcmp(g.zLo
b6a0: 67 69 6e 2c 22 6e 6f 62 6f 64 79 22 29 3d 3d 30  gin,"nobody")==0
b6b0: 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 52 65 74 75 72  ;.}../*.** Retur
b6c0: 6e 20 74 72 75 65 20 69 66 20 74 68 65 20 75 73  n true if the us
b6d0: 65 72 20 69 73 20 61 20 73 70 65 63 69 66 69 63  er is a specific
b6e0: 20 69 6e 64 69 76 69 64 75 61 6c 2c 20 6e 6f 74   individual, not
b6f0: 20 22 6e 6f 62 6f 64 79 22 20 6f 72 0a 2a 2a 20   "nobody" or.** 
b700: 22 61 6e 6f 6e 79 6d 6f 75 73 22 2e 0a 2a 2f 0a  "anonymous"..*/.
b710: 69 6e 74 20 6c 6f 67 69 6e 5f 69 73 5f 69 6e 64  int login_is_ind
b720: 69 76 69 64 75 61 6c 28 76 6f 69 64 29 7b 0a 20  ividual(void){. 
b730: 20 72 65 74 75 72 6e 20 67 2e 7a 4c 6f 67 69 6e   return g.zLogin
b740: 21 3d 30 20 26 26 20 67 2e 7a 4c 6f 67 69 6e 5b  !=0 && g.zLogin[
b750: 30 5d 21 3d 30 20 26 26 20 66 6f 73 73 69 6c 5f  0]!=0 && fossil_
b760: 73 74 72 63 6d 70 28 67 2e 7a 4c 6f 67 69 6e 2c  strcmp(g.zLogin,
b770: 22 6e 6f 62 6f 64 79 22 29 21 3d 30 0a 20 20 20  "nobody")!=0.   
b780: 20 20 20 20 20 20 20 20 26 26 20 66 6f 73 73 69          && fossi
b790: 6c 5f 73 74 72 63 6d 70 28 67 2e 7a 4c 6f 67 69  l_strcmp(g.zLogi
b7a0: 6e 2c 22 61 6e 6f 6e 79 6d 6f 75 73 22 29 21 3d  n,"anonymous")!=
b7b0: 30 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 52 65 74 75  0;.}../*.** Retu
b7c0: 72 6e 20 74 68 65 20 6c 6f 67 69 6e 20 6e 61 6d  rn the login nam
b7d0: 65 2e 20 20 49 66 20 6e 6f 20 6c 6f 67 69 6e 20  e.  If no login 
b7e0: 6e 61 6d 65 20 69 73 20 73 70 65 63 69 66 69 65  name is specifie
b7f0: 64 2c 20 72 65 74 75 72 6e 20 22 6e 6f 62 6f 64  d, return "nobod
b800: 79 22 2e 0a 2a 2f 0a 63 6f 6e 73 74 20 63 68 61  y"..*/.const cha
b810: 72 20 2a 6c 6f 67 69 6e 5f 6e 61 6d 65 28 76 6f  r *login_name(vo
b820: 69 64 29 7b 0a 20 20 72 65 74 75 72 6e 20 28 67  id){.  return (g
b830: 2e 7a 4c 6f 67 69 6e 20 26 26 20 67 2e 7a 4c 6f  .zLogin && g.zLo
b840: 67 69 6e 5b 30 5d 29 20 3f 20 67 2e 7a 4c 6f 67  gin[0]) ? g.zLog
b850: 69 6e 20 3a 20 22 6e 6f 62 6f 64 79 22 3b 0a 7d  in : "nobody";.}
b860: 0a 0a 2f 2a 0a 2a 2a 20 43 61 6c 6c 20 74 68 69  ../*.** Call thi
b870: 73 20 72 6f 75 74 69 6e 65 20 77 68 65 6e 20 74  s routine when t
b880: 68 65 20 63 72 65 64 65 6e 74 69 61 6c 20 63 68  he credential ch
b890: 65 63 6b 20 66 61 69 6c 73 2e 20 20 49 74 20 63  eck fails.  It c
b8a0: 61 75 73 65 73 0a 2a 2a 20 61 20 72 65 64 69 72  auses.** a redir
b8b0: 65 63 74 20 74 6f 20 74 68 65 20 22 6c 6f 67 69  ect to the "logi
b8c0: 6e 22 20 70 61 67 65 2e 0a 2a 2f 0a 76 6f 69 64  n" page..*/.void
b8d0: 20 6c 6f 67 69 6e 5f 6e 65 65 64 65 64 28 69 6e   login_needed(in
b8e0: 74 20 61 6e 6f 6e 4f 6b 29 7b 0a 23 69 66 64 65  t anonOk){.#ifde
b8f0: 66 20 46 4f 53 53 49 4c 5f 45 4e 41 42 4c 45 5f  f FOSSIL_ENABLE_
b900: 4a 53 4f 4e 0a 20 20 69 66 28 67 2e 6a 73 6f 6e  JSON.  if(g.json
b910: 2e 69 73 4a 73 6f 6e 4d 6f 64 65 29 7b 0a 20 20  .isJsonMode){.  
b920: 20 20 6a 73 6f 6e 5f 65 72 72 28 20 46 53 4c 5f    json_err( FSL_
b930: 4a 53 4f 4e 5f 45 5f 44 45 4e 49 45 44 2c 20 4e  JSON_E_DENIED, N
b940: 55 4c 4c 2c 20 31 20 29 3b 0a 20 20 20 20 66 6f  ULL, 1 );.    fo
b950: 73 73 69 6c 5f 65 78 69 74 28 30 29 3b 0a 20 20  ssil_exit(0);.  
b960: 20 20 2f 2a 20 4e 4f 54 52 45 41 43 48 45 44 20    /* NOTREACHED 
b970: 2a 2f 0a 20 20 20 20 61 73 73 65 72 74 28 30 29  */.    assert(0)
b980: 3b 0a 20 20 7d 65 6c 73 65 0a 23 65 6e 64 69 66  ;.  }else.#endif
b990: 20 2f 2a 20 46 4f 53 53 49 4c 5f 45 4e 41 42 4c   /* FOSSIL_ENABL
b9a0: 45 5f 4a 53 4f 4e 20 2a 2f 0a 20 20 7b 0a 20 20  E_JSON */.  {.  
b9b0: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 55    const char *zU
b9c0: 72 6c 20 3d 20 50 44 28 22 52 45 51 55 45 53 54  rl = PD("REQUEST
b9d0: 5f 55 52 49 22 2c 20 22 69 6e 64 65 78 22 29 3b  _URI", "index");
b9e0: 0a 20 20 20 20 63 6f 6e 73 74 20 63 68 61 72 20  .    const char 
b9f0: 2a 7a 51 53 20 3d 20 50 28 22 51 55 45 52 59 5f  *zQS = P("QUERY_
ba00: 53 54 52 49 4e 47 22 29 3b 0a 20 20 20 20 42 6c  STRING");.    Bl
ba10: 6f 62 20 72 65 64 69 72 3b 0a 20 20 20 20 62 6c  ob redir;.    bl
ba20: 6f 62 5f 69 6e 69 74 28 26 72 65 64 69 72 2c 20  ob_init(&redir, 
ba30: 30 2c 20 30 29 3b 0a 20 20 20 20 69 66 28 20 66  0, 0);.    if( f
ba40: 6f 73 73 69 6c 5f 77 61 6e 74 73 5f 68 74 74 70  ossil_wants_http
ba50: 73 28 31 29 20 29 7b 0a 20 20 20 20 20 20 62 6c  s(1) ){.      bl
ba60: 6f 62 5f 61 70 70 65 6e 64 66 28 26 72 65 64 69  ob_appendf(&redi
ba70: 72 2c 20 22 25 73 2f 6c 6f 67 69 6e 3f 67 3d 25  r, "%s/login?g=%
ba80: 54 22 2c 20 67 2e 7a 48 74 74 70 73 55 52 4c 2c  T", g.zHttpsURL,
ba90: 20 7a 55 72 6c 29 3b 0a 20 20 20 20 7d 65 6c 73   zUrl);.    }els
baa0: 65 7b 0a 20 20 20 20 20 20 62 6c 6f 62 5f 61 70  e{.      blob_ap
bab0: 70 65 6e 64 66 28 26 72 65 64 69 72 2c 20 22 25  pendf(&redir, "%
bac0: 52 2f 6c 6f 67 69 6e 3f 67 3d 25 54 22 2c 20 7a  R/login?g=%T", z
bad0: 55 72 6c 29 3b 0a 20 20 20 20 7d 0a 20 20 20 20  Url);.    }.    
bae0: 69 66 28 20 7a 51 53 20 26 26 20 7a 51 53 5b 30  if( zQS && zQS[0
baf0: 5d 20 29 7b 0a 20 20 20 20 20 20 62 6c 6f 62 5f  ] ){.      blob_
bb00: 61 70 70 65 6e 64 66 28 26 72 65 64 69 72 2c 20  appendf(&redir, 
bb10: 22 25 25 33 66 25 54 22 2c 20 7a 51 53 29 3b 0a  "%%3f%T", zQS);.
bb20: 20 20 20 20 7d 0a 20 20 20 20 69 66 28 20 61 6e      }.    if( an
bb30: 6f 6e 4f 6b 20 29 20 62 6c 6f 62 5f 61 70 70 65  onOk ) blob_appe
bb40: 6e 64 28 26 72 65 64 69 72 2c 20 22 26 61 6e 6f  nd(&redir, "&ano
bb50: 6e 22 2c 20 35 29 3b 0a 20 20 20 20 63 67 69 5f  n", 5);.    cgi_
bb60: 72 65 64 69 72 65 63 74 28 62 6c 6f 62 5f 73 74  redirect(blob_st
bb70: 72 28 26 72 65 64 69 72 29 29 3b 0a 20 20 20 20  r(&redir));.    
bb80: 2f 2a 20 4e 4f 54 52 45 41 43 48 45 44 20 2a 2f  /* NOTREACHED */
bb90: 0a 20 20 20 20 61 73 73 65 72 74 28 30 29 3b 0a  .    assert(0);.
bba0: 20 20 7d 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 43 61 6c    }.}../*.** Cal
bbb0: 6c 20 74 68 69 73 20 72 6f 75 74 69 6e 65 20 69  l this routine i
bbc0: 66 20 74 68 65 20 75 73 65 72 20 6c 61 63 6b 73  f the user lacks
bbd0: 20 67 2e 70 65 72 6d 2e 48 79 70 65 72 6c 69 6e   g.perm.Hyperlin
bbe0: 6b 20 70 65 72 6d 69 73 73 69 6f 6e 2e 20 20 49  k permission.  I
bbf0: 66 0a 2a 2a 20 74 68 65 20 61 6e 6f 6e 79 6d 6f  f.** the anonymo
bc00: 75 73 20 75 73 65 72 20 68 61 73 20 48 79 70 65  us user has Hype
bc10: 72 6c 69 6e 6b 20 70 65 72 6d 69 73 73 69 6f 6e  rlink permission
bc20: 2c 20 74 68 65 6e 20 70 61 69 6e 74 20 61 20 6d  , then paint a m
bc30: 65 73 61 67 65 0a 2a 2a 20 74 6f 20 69 6e 66 6f  esage.** to info
bc40: 72 6d 20 74 68 65 20 75 73 65 72 20 74 68 61 74  rm the user that
bc50: 20 6d 75 63 68 20 6d 6f 72 65 20 69 6e 66 6f 72   much more infor
bc60: 6d 61 74 69 6f 6e 20 69 73 20 61 76 61 69 6c 61  mation is availa
bc70: 62 6c 65 20 62 79 0a 2a 2a 20 6c 6f 67 67 69 6e  ble by.** loggin
bc80: 67 20 69 6e 20 61 73 20 61 6e 6f 6e 79 6d 6f 75  g in as anonymou
bc90: 73 2e 0a 2a 2f 0a 76 6f 69 64 20 6c 6f 67 69 6e  s..*/.void login
bca0: 5f 61 6e 6f 6e 79 6d 6f 75 73 5f 61 76 61 69 6c  _anonymous_avail
bcb0: 61 62 6c 65 28 76 6f 69 64 29 7b 0a 20 20 69 66  able(void){.  if
bcc0: 28 20 21 67 2e 70 65 72 6d 2e 48 79 70 65 72 6c  ( !g.perm.Hyperl
bcd0: 69 6e 6b 20 26 26 20 67 2e 61 6e 6f 6e 2e 48 79  ink && g.anon.Hy
bce0: 70 65 72 6c 69 6e 6b 20 29 7b 0a 20 20 20 20 63  perlink ){.    c
bcf0: 6f 6e 73 74 20 63 68 61 72 20 2a 7a 55 72 6c 20  onst char *zUrl 
bd00: 3d 20 50 44 28 22 52 45 51 55 45 53 54 5f 55 52  = PD("REQUEST_UR
bd10: 49 22 2c 20 22 69 6e 64 65 78 22 29 3b 0a 20 20  I", "index");.  
bd20: 20 20 40 20 3c 70 3e 4d 61 6e 79 20 3c 73 70 61    @ <p>Many <spa
bd30: 6e 20 63 6c 61 73 73 3d 22 64 69 73 61 62 6c 65  n class="disable
bd40: 64 22 3e 68 79 70 65 72 6c 69 6e 6b 73 20 61 72  d">hyperlinks ar
bd50: 65 20 64 69 73 61 62 6c 65 64 2e 3c 2f 73 70 61  e disabled.</spa
bd60: 6e 3e 3c 62 72 20 2f 3e 0a 20 20 20 20 40 20 55  n><br />.    @ U
bd70: 73 65 20 3c 61 20 68 72 65 66 3d 22 25 52 2f 6c  se <a href="%R/l
bd80: 6f 67 69 6e 3f 61 6e 6f 6e 3d 31 26 61 6d 70 3b  ogin?anon=1&amp;
bd90: 67 3d 25 54 28 7a 55 72 6c 29 22 3e 61 6e 6f 6e  g=%T(zUrl)">anon
bda0: 79 6d 6f 75 73 20 6c 6f 67 69 6e 3c 2f 61 3e 0a  ymous login</a>.
bdb0: 20 20 20 20 40 20 74 6f 20 65 6e 61 62 6c 65 20      @ to enable 
bdc0: 68 79 70 65 72 6c 69 6e 6b 73 2e 3c 2f 70 3e 0a  hyperlinks.</p>.
bdd0: 20 20 7d 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 57 68 69    }.}../*.** Whi
bde0: 6c 65 20 72 65 6e 64 65 72 69 6e 67 20 61 20 66  le rendering a f
bdf0: 6f 72 6d 2c 20 63 61 6c 6c 20 74 68 69 73 20 72  orm, call this r
be00: 6f 75 74 69 6e 65 20 74 6f 20 61 64 64 20 74 68  outine to add th
be10: 65 20 41 6e 74 69 2d 43 53 52 46 20 74 6f 6b 65  e Anti-CSRF toke
be20: 6e 0a 2a 2a 20 61 73 20 61 20 68 69 64 64 65 6e  n.** as a hidden
be30: 20 65 6c 65 6d 65 6e 74 20 6f 66 20 74 68 65 20   element of the 
be40: 66 6f 72 6d 2e 0a 2a 2f 0a 76 6f 69 64 20 6c 6f  form..*/.void lo
be50: 67 69 6e 5f 69 6e 73 65 72 74 5f 63 73 72 66 5f  gin_insert_csrf_
be60: 73 65 63 72 65 74 28 76 6f 69 64 29 7b 0a 20 20  secret(void){.  
be70: 40 20 3c 69 6e 70 75 74 20 74 79 70 65 3d 22 68  @ <input type="h
be80: 69 64 64 65 6e 22 20 6e 61 6d 65 3d 22 63 73 72  idden" name="csr
be90: 66 22 20 76 61 6c 75 65 3d 22 25 73 28 67 2e 7a  f" value="%s(g.z
bea0: 43 73 72 66 54 6f 6b 65 6e 29 22 20 2f 3e 0a 7d  CsrfToken)" />.}
beb0: 0a 0a 2f 2a 0a 2a 2a 20 42 65 66 6f 72 65 20 75  ../*.** Before u
bec0: 73 69 6e 67 20 74 68 65 20 72 65 73 75 6c 74 73  sing the results
bed0: 20 6f 66 20 61 20 66 6f 72 6d 2c 20 66 69 72 73   of a form, firs
bee0: 74 20 63 61 6c 6c 20 74 68 69 73 20 72 6f 75 74  t call this rout
bef0: 69 6e 65 20 74 6f 20 76 65 72 69 66 79 0a 2a 2a  ine to verify.**
bf00: 20 74 68 61 74 20 74 68 69 73 20 41 6e 74 69 2d   that this Anti-
bf10: 43 53 52 46 20 74 6f 6b 65 6e 20 69 73 20 70 72  CSRF token is pr
bf20: 65 73 65 6e 74 20 61 6e 64 20 69 73 20 76 61 6c  esent and is val
bf30: 69 64 2e 20 20 49 66 20 74 68 65 20 41 6e 74 69  id.  If the Anti
bf40: 2d 43 53 52 46 20 74 6f 6b 65 6e 0a 2a 2a 20 69  -CSRF token.** i
bf50: 73 20 6d 69 73 73 69 6e 67 20 6f 72 20 69 73 20  s missing or is 
bf60: 69 6e 63 6f 72 72 65 63 74 2c 20 74 68 61 74 20  incorrect, that 
bf70: 69 6e 64 69 63 61 74 65 73 20 61 20 63 72 6f 73  indicates a cros
bf80: 73 2d 73 69 74 65 20 73 63 72 69 70 74 69 6e 67  s-site scripting
bf90: 20 61 74 74 61 63 6b 2e 0a 2a 2a 20 49 66 20 74   attack..** If t
bfa0: 68 65 20 65 76 65 6e 74 20 6f 66 20 61 6e 20 61  he event of an a
bfb0: 74 74 61 63 6b 20 69 73 20 64 65 74 65 63 74 65  ttack is detecte
bfc0: 64 2c 20 61 6e 20 65 72 72 6f 72 20 6d 65 73 73  d, an error mess
bfd0: 61 67 65 20 69 73 20 67 65 6e 65 72 61 74 65 64  age is generated
bfe0: 20 61 6e 64 0a 2a 2a 20 61 6c 6c 20 66 75 72 74   and.** all furt
bff0: 68 65 72 20 70 72 6f 63 65 73 73 69 6e 67 20 69  her processing i
c000: 73 20 61 62 6f 72 74 65 64 2e 0a 2a 2f 0a 76 6f  s aborted..*/.vo
c010: 69 64 20 6c 6f 67 69 6e 5f 76 65 72 69 66 79 5f  id login_verify_
c020: 63 73 72 66 5f 73 65 63 72 65 74 28 76 6f 69 64  csrf_secret(void
c030: 29 7b 0a 20 20 69 66 28 20 67 2e 6f 6b 43 73 72  ){.  if( g.okCsr
c040: 66 20 29 20 72 65 74 75 72 6e 3b 0a 20 20 69 66  f ) return;.  if
c050: 28 20 66 6f 73 73 69 6c 5f 73 74 72 63 6d 70 28  ( fossil_strcmp(
c060: 50 28 22 63 73 72 66 22 29 2c 20 67 2e 7a 43 73  P("csrf"), g.zCs
c070: 72 66 54 6f 6b 65 6e 29 3d 3d 30 20 29 7b 0a 20  rfToken)==0 ){. 
c080: 20 20 20 67 2e 6f 6b 43 73 72 66 20 3d 20 31 3b     g.okCsrf = 1;
c090: 0a 20 20 20 20 72 65 74 75 72 6e 3b 0a 20 20 7d  .    return;.  }
c0a0: 0a 20 20 66 6f 73 73 69 6c 5f 66 61 74 61 6c 28  .  fossil_fatal(
c0b0: 22 43 72 6f 73 73 2d 73 69 74 65 20 72 65 71 75  "Cross-site requ
c0c0: 65 73 74 20 66 6f 72 67 65 72 79 20 61 74 74 65  est forgery atte
c0d0: 6d 70 74 22 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20  mpt");.}../*.** 
c0e0: 57 45 42 50 41 47 45 3a 20 72 65 67 69 73 74 65  WEBPAGE: registe
c0f0: 72 0a 2a 2a 0a 2a 2a 20 50 61 67 65 20 74 6f 20  r.**.** Page to 
c100: 61 6c 6c 6f 77 20 75 73 65 72 73 20 74 6f 20 73  allow users to s
c110: 65 6c 66 2d 72 65 67 69 73 74 65 72 2e 20 20 54  elf-register.  T
c120: 68 65 20 22 73 65 6c 66 2d 72 65 67 69 73 74 65  he "self-registe
c130: 72 22 20 73 65 74 74 69 6e 67 0a 2a 2a 20 6d 75  r" setting.** mu
c140: 73 74 20 62 65 20 65 6e 61 62 6c 65 64 20 66 6f  st be enabled fo
c150: 72 20 74 68 69 73 20 70 61 67 65 20 74 6f 20 6f  r this page to o
c160: 70 65 72 61 74 65 2e 0a 2a 2f 0a 76 6f 69 64 20  perate..*/.void 
c170: 72 65 67 69 73 74 65 72 5f 70 61 67 65 28 76 6f  register_page(vo
c180: 69 64 29 7b 0a 20 20 63 6f 6e 73 74 20 63 68 61  id){.  const cha
c190: 72 20 2a 7a 55 73 65 72 49 44 2c 20 2a 7a 50 61  r *zUserID, *zPa
c1a0: 73 73 77 64 2c 20 2a 7a 43 6f 6e 66 69 72 6d 2c  sswd, *zConfirm,
c1b0: 20 2a 7a 45 41 64 64 72 3b 0a 20 20 63 6f 6e 73   *zEAddr;.  cons
c1c0: 74 20 63 68 61 72 20 2a 7a 44 4e 61 6d 65 3b 0a  t char *zDName;.
c1d0: 20 20 75 6e 73 69 67 6e 65 64 20 69 6e 74 20 75    unsigned int u
c1e0: 53 65 65 64 3b 0a 20 20 63 6f 6e 73 74 20 63 68  Seed;.  const ch
c1f0: 61 72 20 2a 7a 44 65 63 6f 64 65 64 3b 0a 20 20  ar *zDecoded;.  
c200: 63 68 61 72 20 2a 7a 43 61 70 74 63 68 61 3b 0a  char *zCaptcha;.
c210: 20 20 69 6e 74 20 69 45 72 72 4c 69 6e 65 20 3d    int iErrLine =
c220: 20 2d 31 3b 0a 20 20 63 6f 6e 73 74 20 63 68 61   -1;.  const cha
c230: 72 20 2a 7a 45 72 72 20 3d 20 30 3b 0a 20 20 63  r *zErr = 0;.  c
c240: 68 61 72 20 2a 7a 50 65 72 6d 73 3b 20 20 20 20  har *zPerms;    
c250: 20 20 20 20 20 20 20 20 20 2f 2a 20 50 65 72 6d           /* Perm
c260: 69 73 73 69 6f 6e 73 20 66 6f 72 20 74 68 65 20  issions for the 
c270: 64 65 66 61 75 6c 74 20 75 73 65 72 20 2a 2f 0a  default user */.
c280: 20 20 69 6e 74 20 63 61 6e 44 6f 41 6c 65 72 74    int canDoAlert
c290: 73 20 3d 20 30 3b 20 20 20 20 20 20 2f 2a 20 54  s = 0;      /* T
c2a0: 72 75 65 20 69 66 20 72 65 63 65 69 76 69 6e 67  rue if receiving
c2b0: 20 65 6d 61 69 6c 20 61 6c 65 72 74 73 20 69 73   email alerts is
c2c0: 20 70 6f 73 73 69 62 6c 65 20 2a 2f 0a 20 20 69   possible */.  i
c2d0: 6e 74 20 64 6f 41 6c 65 72 74 73 20 3d 20 30 3b  nt doAlerts = 0;
c2e0: 20 20 20 20 20 20 20 20 20 2f 2a 20 54 72 75 65           /* True
c2f0: 20 69 66 20 73 75 62 73 63 72 69 70 74 69 6f 6e   if subscription
c300: 20 69 73 20 77 61 6e 74 65 64 20 74 6f 6f 20 2a   is wanted too *
c310: 2f 0a 20 20 69 66 28 20 21 64 62 5f 67 65 74 5f  /.  if( !db_get_
c320: 62 6f 6f 6c 65 61 6e 28 22 73 65 6c 66 2d 72 65  boolean("self-re
c330: 67 69 73 74 65 72 22 2c 20 30 29 20 29 7b 0a 20  gister", 0) ){. 
c340: 20 20 20 73 74 79 6c 65 5f 68 65 61 64 65 72 28     style_header(
c350: 22 52 65 67 69 73 74 72 61 74 69 6f 6e 20 6e 6f  "Registration no
c360: 74 20 70 6f 73 73 69 62 6c 65 22 29 3b 0a 20 20  t possible");.  
c370: 20 20 40 20 3c 70 3e 54 68 69 73 20 70 72 6f 6a    @ <p>This proj
c380: 65 63 74 20 64 6f 65 73 20 6e 6f 74 20 61 6c 6c  ect does not all
c390: 6f 77 20 75 73 65 72 20 73 65 6c 66 2d 72 65 67  ow user self-reg
c3a0: 69 73 74 72 61 74 69 6f 6e 2e 20 50 6c 65 61 73  istration. Pleas
c3b0: 65 20 63 6f 6e 74 61 63 74 20 74 68 65 0a 20 20  e contact the.  
c3c0: 20 20 40 20 70 72 6f 6a 65 63 74 20 61 64 6d 69    @ project admi
c3d0: 6e 69 73 74 72 61 74 6f 72 20 74 6f 20 6f 62 74  nistrator to obt
c3e0: 61 69 6e 20 61 6e 20 61 63 63 6f 75 6e 74 2e 3c  ain an account.<
c3f0: 2f 70 3e 0a 20 20 20 20 73 74 79 6c 65 5f 66 6f  /p>.    style_fo
c400: 6f 74 65 72 28 29 3b 0a 20 20 20 20 72 65 74 75  oter();.    retu
c410: 72 6e 3b 0a 20 20 7d 0a 20 20 7a 50 65 72 6d 73  rn;.  }.  zPerms
c420: 20 3d 20 64 62 5f 67 65 74 28 22 64 65 66 61 75   = db_get("defau
c430: 6c 74 2d 70 65 72 6d 73 22 2c 22 75 22 29 3b 0a  lt-perms","u");.
c440: 0a 20 20 2f 2a 20 50 72 6f 6d 70 74 20 74 68 65  .  /* Prompt the
c450: 20 75 73 65 72 20 66 6f 72 20 65 6d 61 69 6c 20   user for email 
c460: 61 6c 65 72 74 73 20 69 66 20 74 68 69 73 20 72  alerts if this r
c470: 65 70 6f 73 69 74 6f 72 79 20 69 73 20 63 6f 6e  epository is con
c480: 66 69 67 75 72 65 64 20 66 6f 72 0a 20 20 2a 2a  figured for.  **
c490: 20 65 6d 61 69 6c 20 61 6c 65 72 74 73 20 61 6e   email alerts an
c4a0: 64 20 69 66 20 74 68 65 20 64 65 66 61 75 6c 74  d if the default
c4b0: 20 70 65 72 6d 69 73 73 69 6f 6e 73 20 69 6e 63   permissions inc
c4c0: 6c 75 64 65 20 22 37 22 20 2a 2f 0a 20 20 63 61  lude "7" */.  ca
c4d0: 6e 44 6f 41 6c 65 72 74 73 20 3d 20 61 6c 65 72  nDoAlerts = aler
c4e0: 74 5f 74 61 62 6c 65 73 5f 65 78 69 73 74 28 29  t_tables_exist()
c4f0: 20 26 26 20 64 62 5f 69 6e 74 28 30 2c 0a 20 20   && db_int(0,.  
c500: 20 20 22 53 45 4c 45 43 54 20 66 75 6c 6c 63 61    "SELECT fullca
c510: 70 28 25 51 29 20 47 4c 4f 42 20 27 2a 37 2a 27  p(%Q) GLOB '*7*'
c520: 22 2c 20 7a 50 65 72 6d 73 0a 20 20 29 3b 0a 20  ", zPerms.  );. 
c530: 20 64 6f 41 6c 65 72 74 73 20 3d 20 63 61 6e 44   doAlerts = canD
c540: 6f 41 6c 65 72 74 73 20 26 26 20 61 74 6f 69 28  oAlerts && atoi(
c550: 50 44 28 22 61 6c 65 72 74 73 22 2c 22 31 22 29  PD("alerts","1")
c560: 29 21 3d 30 3b 0a 0a 20 20 7a 55 73 65 72 49 44  )!=0;..  zUserID
c570: 20 3d 20 50 44 54 28 22 75 22 2c 22 22 29 3b 0a   = PDT("u","");.
c580: 20 20 7a 50 61 73 73 77 64 20 3d 20 50 44 54 28    zPasswd = PDT(
c590: 22 70 22 2c 22 22 29 3b 0a 20 20 7a 43 6f 6e 66  "p","");.  zConf
c5a0: 69 72 6d 20 3d 20 50 44 54 28 22 63 70 22 2c 22  irm = PDT("cp","
c5b0: 22 29 3b 0a 20 20 7a 45 41 64 64 72 20 3d 20 50  ");.  zEAddr = P
c5c0: 44 54 28 22 65 61 22 2c 22 22 29 3b 0a 20 20 7a  DT("ea","");.  z
c5d0: 44 4e 61 6d 65 20 3d 20 50 44 54 28 22 64 6e 22  DName = PDT("dn"
c5e0: 2c 22 22 29 3b 0a 0a 20 20 2f 2a 20 56 65 72 69  ,"");..  /* Veri
c5f0: 66 79 20 75 73 65 72 20 69 6d 70 75 74 73 20 2a  fy user imputs *
c600: 2f 0a 20 20 69 66 28 20 50 28 22 6e 65 77 22 29  /.  if( P("new")
c610: 3d 3d 30 20 7c 7c 20 21 63 67 69 5f 63 73 72 66  ==0 || !cgi_csrf
c620: 5f 73 61 66 65 28 31 29 20 29 7b 0a 20 20 20 20  _safe(1) ){.    
c630: 2f 2a 20 54 68 69 73 20 69 73 20 6e 6f 74 20 61  /* This is not a
c640: 20 76 61 6c 69 64 20 66 6f 72 6d 20 73 75 62 6d   valid form subm
c650: 69 73 73 69 6f 6e 2e 20 20 46 61 6c 6c 20 74 68  ission.  Fall th
c660: 72 6f 75 67 68 20 69 6e 74 6f 0a 20 20 20 20 2a  rough into.    *
c670: 2a 20 74 68 65 20 66 6f 72 6d 20 64 69 73 70 6c  * the form displ
c680: 61 79 20 2a 2f 0a 20 20 7d 65 6c 73 65 20 69 66  ay */.  }else if
c690: 28 20 21 63 61 70 74 63 68 61 5f 69 73 5f 63 6f  ( !captcha_is_co
c6a0: 72 72 65 63 74 28 31 29 20 29 7b 0a 20 20 20 20  rrect(1) ){.    
c6b0: 69 45 72 72 4c 69 6e 65 20 3d 20 36 3b 0a 20 20  iErrLine = 6;.  
c6c0: 20 20 7a 45 72 72 20 3d 20 22 49 6e 63 6f 72 72    zErr = "Incorr
c6d0: 65 63 74 20 43 41 50 54 43 48 41 22 3b 0a 20 20  ect CAPTCHA";.  
c6e0: 7d 65 6c 73 65 20 69 66 28 20 73 74 72 6c 65 6e  }else if( strlen
c6f0: 28 7a 55 73 65 72 49 44 29 3c 33 20 29 7b 0a 20  (zUserID)<3 ){. 
c700: 20 20 20 69 45 72 72 4c 69 6e 65 20 3d 20 31 3b     iErrLine = 1;
c710: 0a 20 20 20 20 7a 45 72 72 20 3d 20 22 55 73 65  .    zErr = "Use
c720: 72 20 49 44 20 74 6f 6f 20 73 68 6f 72 74 2e 20  r ID too short. 
c730: 4d 75 73 74 20 62 65 20 61 74 20 6c 65 61 73 74  Must be at least
c740: 20 33 20 63 68 61 72 61 63 74 65 72 73 2e 22 3b   3 characters.";
c750: 0a 20 20 7d 65 6c 73 65 20 69 66 28 20 73 71 6c  .  }else if( sql
c760: 69 74 65 33 5f 73 74 72 67 6c 6f 62 28 22 2a 5b  ite3_strglob("*[
c770: 5e 2d 61 2d 7a 41 2d 5a 30 2d 39 5f 2e 5d 2a 22  ^-a-zA-Z0-9_.]*"
c780: 2c 7a 55 73 65 72 49 44 29 3d 3d 30 20 29 7b 0a  ,zUserID)==0 ){.
c790: 20 20 20 20 69 45 72 72 4c 69 6e 65 20 3d 20 31      iErrLine = 1
c7a0: 3b 0a 20 20 20 20 7a 45 72 72 20 3d 20 22 55 73  ;.    zErr = "Us
c7b0: 65 72 20 49 44 20 6d 61 79 20 6e 6f 74 20 63 6f  er ID may not co
c7c0: 6e 74 61 69 6e 20 73 70 61 63 65 73 20 6f 72 20  ntain spaces or 
c7d0: 73 70 65 63 69 61 6c 20 63 68 61 72 61 63 74 65  special characte
c7e0: 72 73 2e 22 3b 0a 20 20 7d 65 6c 73 65 20 69 66  rs.";.  }else if
c7f0: 28 20 7a 44 4e 61 6d 65 5b 30 5d 3d 3d 30 20 29  ( zDName[0]==0 )
c800: 7b 0a 20 20 20 20 69 45 72 72 4c 69 6e 65 20 3d  {.    iErrLine =
c810: 20 32 3b 0a 20 20 20 20 7a 45 72 72 20 3d 20 22   2;.    zErr = "
c820: 52 65 71 75 69 72 65 64 22 3b 0a 20 20 7d 65 6c  Required";.  }el
c830: 73 65 20 69 66 28 20 7a 45 41 64 64 72 5b 30 5d  se if( zEAddr[0]
c840: 3d 3d 30 20 29 7b 0a 20 20 20 20 69 45 72 72 4c  ==0 ){.    iErrL
c850: 69 6e 65 20 3d 20 33 3b 0a 20 20 20 20 7a 45 72  ine = 3;.    zEr
c860: 72 20 3d 20 22 52 65 71 75 69 72 65 64 22 3b 0a  r = "Required";.
c870: 20 20 7d 65 6c 73 65 20 69 66 28 20 65 6d 61 69    }else if( emai
c880: 6c 5f 63 6f 70 79 5f 61 64 64 72 28 7a 45 41 64  l_copy_addr(zEAd
c890: 64 72 2c 30 29 3d 3d 30 20 29 7b 0a 20 20 20 20  dr,0)==0 ){.    
c8a0: 69 45 72 72 4c 69 6e 65 20 3d 20 33 3b 0a 20 20  iErrLine = 3;.  
c8b0: 20 20 7a 45 72 72 20 3d 20 22 4e 6f 74 20 61 20    zErr = "Not a 
c8c0: 76 61 6c 69 64 20 65 6d 61 69 6c 20 61 64 64 72  valid email addr
c8d0: 65 73 73 22 3b 0a 20 20 7d 65 6c 73 65 20 69 66  ess";.  }else if
c8e0: 28 20 73 74 72 6c 65 6e 28 7a 50 61 73 73 77 64  ( strlen(zPasswd
c8f0: 29 3c 36 20 29 7b 0a 20 20 20 20 69 45 72 72 4c  )<6 ){.    iErrL
c900: 69 6e 65 20 3d 20 34 3b 0a 20 20 20 20 7a 45 72  ine = 4;.    zEr
c910: 72 20 3d 20 22 50 61 73 73 77 6f 72 64 20 6d 75  r = "Password mu
c920: 73 74 20 62 65 20 61 74 20 6c 65 61 73 74 20 36  st be at least 6
c930: 20 63 68 61 72 61 63 74 65 72 73 20 6c 6f 6e 67   characters long
c940: 22 3b 0a 20 20 7d 65 6c 73 65 20 69 66 28 20 66  ";.  }else if( f
c950: 6f 73 73 69 6c 5f 73 74 72 63 6d 70 28 7a 50 61  ossil_strcmp(zPa
c960: 73 73 77 64 2c 7a 43 6f 6e 66 69 72 6d 29 21 3d  sswd,zConfirm)!=
c970: 30 20 29 7b 0a 20 20 20 20 69 45 72 72 4c 69 6e  0 ){.    iErrLin
c980: 65 20 3d 20 35 3b 0a 20 20 20 20 7a 45 72 72 20  e = 5;.    zErr 
c990: 3d 20 22 50 61 73 73 77 6f 72 64 73 20 64 6f 20  = "Passwords do 
c9a0: 6e 6f 74 20 6d 61 74 63 68 22 3b 0a 20 20 7d 65  not match";.  }e
c9b0: 6c 73 65 20 69 66 28 20 64 62 5f 65 78 69 73 74  lse if( db_exist
c9c0: 73 28 22 53 45 4c 45 43 54 20 31 20 46 52 4f 4d  s("SELECT 1 FROM
c9d0: 20 75 73 65 72 20 57 48 45 52 45 20 6c 6f 67 69   user WHERE logi
c9e0: 6e 3d 25 51 22 2c 20 7a 55 73 65 72 49 44 29 20  n=%Q", zUserID) 
c9f0: 29 7b 0a 20 20 20 20 69 45 72 72 4c 69 6e 65 20  ){.    iErrLine 
ca00: 3d 20 31 3b 0a 20 20 20 20 7a 45 72 72 20 3d 20  = 1;.    zErr = 
ca10: 22 54 68 69 73 20 55 73 65 72 20 49 44 20 69 73  "This User ID is
ca20: 20 61 6c 72 65 61 64 79 20 74 61 6b 65 6e 2e 20   already taken. 
ca30: 43 68 6f 6f 73 65 20 73 6f 6d 65 74 68 69 6e 67  Choose something
ca40: 20 64 69 66 66 65 72 65 6e 74 2e 22 3b 0a 20 20   different.";.  
ca50: 7d 65 6c 73 65 20 69 66 28 0a 20 20 20 20 20 20  }else if(.      
ca60: 2f 2a 20 49 66 20 74 68 65 20 65 6d 61 69 6c 20  /* If the email 
ca70: 69 73 20 66 6f 75 6e 64 20 61 6e 79 77 68 65 72  is found anywher
ca80: 65 20 69 6e 20 55 53 45 52 2e 49 4e 46 4f 2e 2e  e in USER.INFO..
ca90: 2e 20 2a 2f 0a 20 20 20 20 20 20 64 62 5f 65 78  . */.      db_ex
caa0: 69 73 74 73 28 22 53 45 4c 45 43 54 20 31 20 46  ists("SELECT 1 F
cab0: 52 4f 4d 20 75 73 65 72 20 57 48 45 52 45 20 69  ROM user WHERE i
cac0: 6e 66 6f 20 4c 49 4b 45 20 27 25 25 25 71 25 25  nfo LIKE '%%%q%%
cad0: 27 22 2c 20 7a 45 41 64 64 72 29 0a 20 20 20 20  '", zEAddr).    
cae0: 7c 7c 0a 20 20 20 20 20 20 2f 2a 20 4f 72 20 69  ||.      /* Or i
caf0: 66 20 74 68 65 20 65 6d 61 69 6c 20 69 73 20 61  f the email is a
cb00: 20 76 65 72 69 66 79 20 73 75 62 73 63 72 69 62   verify subscrib
cb10: 65 72 20 65 6d 61 69 6c 20 77 69 74 68 20 61 6e  er email with an
cb20: 20 61 73 73 6f 63 69 61 74 65 64 0a 20 20 20 20   associated.    
cb30: 20 20 2a 2a 20 75 73 65 72 2e 2e 2e 20 2a 2f 0a    ** user... */.
cb40: 20 20 20 20 20 20 64 62 5f 65 78 69 73 74 73 28        db_exists(
cb50: 0a 20 20 20 20 20 20 20 20 22 53 45 4c 45 43 54  .        "SELECT
cb60: 20 31 20 46 52 4f 4d 20 73 75 62 73 63 72 69 62   1 FROM subscrib
cb70: 65 72 20 57 48 45 52 45 20 73 65 6d 61 69 6c 3d  er WHERE semail=
cb80: 25 51 20 41 4e 44 20 73 75 6e 61 6d 65 20 49 53  %Q AND suname IS
cb90: 20 4e 4f 54 20 4e 55 4c 4c 22 0a 20 20 20 20 20   NOT NULL".     
cba0: 20 20 20 22 20 41 4e 44 20 73 76 65 72 69 66 69     " AND sverifi
cbb0: 65 64 22 2c 7a 45 41 64 64 72 29 0a 20 20 20 29  ed",zEAddr).   )
cbc0: 7b 0a 20 20 20 20 69 45 72 72 4c 69 6e 65 20 3d  {.    iErrLine =
cbd0: 20 33 3b 0a 20 20 20 20 7a 45 72 72 20 3d 20 22   3;.    zErr = "
cbe0: 54 68 69 73 20 65 6d 61 69 6c 20 61 64 64 72 65  This email addre
cbf0: 73 73 20 69 73 20 61 6c 72 65 61 64 79 20 63 6c  ss is already cl
cc00: 61 69 6d 65 64 20 62 79 20 61 6e 6f 74 68 65 72  aimed by another
cc10: 20 75 73 65 72 22 3b 0a 20 20 7d 65 6c 73 65 7b   user";.  }else{
cc20: 0a 20 20 20 20 2f 2a 20 49 66 20 61 6c 6c 20 6f  .    /* If all o
cc30: 66 20 74 68 65 20 74 65 73 74 73 20 61 62 6f 76  f the tests abov
cc40: 65 20 68 61 76 65 20 70 61 73 73 65 64 2c 20 74  e have passed, t
cc50: 68 61 74 20 6d 65 61 6e 73 20 74 68 61 74 20 74  hat means that t
cc60: 68 65 20 73 75 62 6d 69 74 74 65 64 0a 20 20 20  he submitted.   
cc70: 20 2a 2a 20 66 6f 72 6d 20 63 6f 6e 74 61 69 6e   ** form contain
cc80: 73 20 76 61 6c 69 64 20 64 61 74 61 20 61 6e 64  s valid data and
cc90: 20 77 65 20 63 61 6e 20 70 72 6f 63 65 65 64 20   we can proceed 
cca0: 74 6f 20 63 72 65 61 74 65 20 74 68 65 20 6e 65  to create the ne
ccb0: 77 20 6c 6f 67 69 6e 20 2a 2f 0a 20 20 20 20 42  w login */.    B
ccc0: 6c 6f 62 20 73 71 6c 3b 0a 20 20 20 20 69 6e 74  lob sql;.    int
ccd0: 20 75 69 64 3b 0a 20 20 20 20 63 68 61 72 20 2a   uid;.    char *
cce0: 7a 50 61 73 73 20 3d 20 73 68 61 31 5f 73 68 61  zPass = sha1_sha
ccf0: 72 65 64 5f 73 65 63 72 65 74 28 7a 50 61 73 73  red_secret(zPass
cd00: 77 64 2c 20 7a 55 73 65 72 49 44 2c 20 30 29 3b  wd, zUserID, 0);
cd10: 0a 20 20 20 20 62 6c 6f 62 5f 69 6e 69 74 28 26  .    blob_init(&
cd20: 73 71 6c 2c 20 30 2c 20 30 29 3b 0a 20 20 20 20  sql, 0, 0);.    
cd30: 62 6c 6f 62 5f 61 70 70 65 6e 64 5f 73 71 6c 28  blob_append_sql(
cd40: 26 73 71 6c 2c 0a 20 20 20 20 20 20 20 22 49 4e  &sql,.       "IN
cd50: 53 45 52 54 20 49 4e 54 4f 20 75 73 65 72 28 6c  SERT INTO user(l
cd60: 6f 67 69 6e 2c 70 77 2c 63 61 70 2c 69 6e 66 6f  ogin,pw,cap,info
cd70: 2c 6d 74 69 6d 65 29 5c 6e 22 0a 20 20 20 20 20  ,mtime)\n".     
cd80: 20 20 22 56 41 4c 55 45 53 28 25 51 2c 25 51 2c    "VALUES(%Q,%Q,
cd90: 25 51 2c 22 0a 20 20 20 20 20 20 20 22 27 25 71  %Q,".       "'%q
cda0: 20 3c 25 71 3e 5c 6e 73 65 6c 66 2d 72 65 67 69   <%q>\nself-regi
cdb0: 73 74 65 72 20 66 72 6f 6d 20 69 70 20 25 71 20  ster from ip %q 
cdc0: 6f 6e 20 27 7c 7c 64 61 74 65 74 69 6d 65 28 27  on '||datetime('
cdd0: 6e 6f 77 27 29 2c 6e 6f 77 28 29 29 22 2c 0a 20  now'),now())",. 
cde0: 20 20 20 20 20 20 7a 55 73 65 72 49 44 2c 20 7a        zUserID, z
cdf0: 50 61 73 73 2c 20 7a 50 65 72 6d 73 2c 20 7a 44  Pass, zPerms, zD
ce00: 4e 61 6d 65 2c 20 7a 45 41 64 64 72 2c 20 67 2e  Name, zEAddr, g.
ce10: 7a 49 70 41 64 64 72 29 3b 0a 20 20 20 20 66 6f  zIpAddr);.    fo
ce20: 73 73 69 6c 5f 66 72 65 65 28 7a 50 61 73 73 29  ssil_free(zPass)
ce30: 3b 0a 20 20 20 20 64 62 5f 6d 75 6c 74 69 5f 65  ;.    db_multi_e
ce40: 78 65 63 28 22 25 73 22 2c 20 62 6c 6f 62 5f 73  xec("%s", blob_s
ce50: 71 6c 5f 74 65 78 74 28 26 73 71 6c 29 29 3b 0a  ql_text(&sql));.
ce60: 20 20 20 20 75 69 64 20 3d 20 64 62 5f 69 6e 74      uid = db_int
ce70: 28 30 2c 20 22 53 45 4c 45 43 54 20 75 69 64 20  (0, "SELECT uid 
ce80: 46 52 4f 4d 20 75 73 65 72 20 57 48 45 52 45 20  FROM user WHERE 
ce90: 6c 6f 67 69 6e 3d 25 51 22 2c 20 7a 55 73 65 72  login=%Q", zUser
cea0: 49 44 29 3b 0a 20 20 20 20 6c 6f 67 69 6e 5f 73  ID);.    login_s
ceb0: 65 74 5f 75 73 65 72 5f 63 6f 6f 6b 69 65 28 7a  et_user_cookie(z
cec0: 55 73 65 72 49 44 2c 20 75 69 64 2c 20 4e 55 4c  UserID, uid, NUL
ced0: 4c 29 3b 0a 20 20 20 20 69 66 28 20 64 6f 41 6c  L);.    if( doAl
cee0: 65 72 74 73 20 29 7b 0a 20 20 20 20 20 20 2f 2a  erts ){.      /*
cef0: 20 41 6c 73 6f 20 6d 61 6b 65 20 74 68 65 20 6e   Also make the n
cf00: 65 77 20 75 73 65 72 20 61 20 73 75 62 73 63 72  ew user a subscr
cf10: 69 62 65 72 2e 20 2a 2f 0a 20 20 20 20 20 20 42  iber. */.      B
cf20: 6c 6f 62 20 68 64 72 2c 20 62 6f 64 79 3b 0a 20  lob hdr, body;. 
cf30: 20 20 20 20 20 41 6c 65 72 74 53 65 6e 64 65 72       AlertSender
cf40: 20 2a 70 53 65 6e 64 65 72 3b 0a 20 20 20 20 20   *pSender;.     
cf50: 20 73 71 6c 69 74 65 33 5f 69 6e 74 36 34 20 69   sqlite3_int64 i
cf60: 64 3b 20 20 20 2f 2a 20 4e 65 77 20 73 75 62 73  d;   /* New subs
cf70: 63 72 69 62 65 72 20 49 64 20 2a 2f 0a 20 20 20  criber Id */.   
cf80: 20 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a     const char *z
cf90: 43 6f 64 65 3b 20 20 2f 2a 20 4e 65 77 20 73 75  Code;  /* New su
cfa0: 62 73 63 72 69 62 65 72 20 63 6f 64 65 20 28 69  bscriber code (i
cfb0: 6e 20 68 65 78 29 20 2a 2f 0a 20 20 20 20 20 20  n hex) */.      
cfc0: 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 47 6f 74  const char *zGot
cfd0: 6f 20 3d 20 50 28 22 67 22 29 3b 0a 20 20 20 20  o = P("g");.    
cfe0: 20 20 69 6e 74 20 6e 73 75 62 20 3d 20 30 3b 0a    int nsub = 0;.
cff0: 20 20 20 20 20 20 63 68 61 72 20 73 73 75 62 5b        char ssub[
d000: 32 30 5d 3b 0a 20 20 20 20 20 20 73 73 75 62 5b  20];.      ssub[
d010: 6e 73 75 62 2b 2b 5d 20 3d 20 27 61 27 3b 0a 20  nsub++] = 'a';. 
d020: 20 20 20 20 20 69 66 28 20 67 2e 70 65 72 6d 2e       if( g.perm.
d030: 52 65 61 64 20 29 20 20 20 20 73 73 75 62 5b 6e  Read )    ssub[n
d040: 73 75 62 2b 2b 5d 20 3d 20 27 63 27 3b 0a 20 20  sub++] = 'c';.  
d050: 20 20 20 20 69 66 28 20 67 2e 70 65 72 6d 2e 52      if( g.perm.R
d060: 64 46 6f 72 75 6d 20 29 20 73 73 75 62 5b 6e 73  dForum ) ssub[ns
d070: 75 62 2b 2b 5d 20 3d 20 27 66 27 3b 0a 20 20 20  ub++] = 'f';.   
d080: 20 20 20 69 66 28 20 67 2e 70 65 72 6d 2e 52 64     if( g.perm.Rd
d090: 54 6b 74 20 29 20 20 20 73 73 75 62 5b 6e 73 75  Tkt )   ssub[nsu
d0a0: 62 2b 2b 5d 20 3d 20 27 74 27 3b 0a 20 20 20 20  b++] = 't';.    
d0b0: 20 20 69 66 28 20 67 2e 70 65 72 6d 2e 52 64 57    if( g.perm.RdW
d0c0: 69 6b 69 20 29 20 20 73 73 75 62 5b 6e 73 75 62  iki )  ssub[nsub
d0d0: 2b 2b 5d 20 3d 20 27 77 27 3b 0a 20 20 20 20 20  ++] = 'w';.     
d0e0: 20 73 73 75 62 5b 6e 73 75 62 5d 20 3d 20 30 3b   ssub[nsub] = 0;
d0f0: 0a 20 20 20 20 20 20 2f 2a 20 41 6c 73 6f 20 61  .      /* Also a
d100: 64 64 20 74 68 65 20 75 73 65 72 20 74 6f 20 74  dd the user to t
d110: 68 65 20 73 75 62 73 63 72 69 62 65 72 20 74 61  he subscriber ta
d120: 62 6c 65 2e 20 2a 2f 0a 20 20 20 20 20 20 64 62  ble. */.      db
d130: 5f 6d 75 6c 74 69 5f 65 78 65 63 28 0a 20 20 20  _multi_exec(.   
d140: 20 20 20 20 20 22 49 4e 53 45 52 54 20 49 4e 54       "INSERT INT
d150: 4f 20 73 75 62 73 63 72 69 62 65 72 28 73 65 6d  O subscriber(sem
d160: 61 69 6c 2c 73 75 6e 61 6d 65 2c 22 0a 20 20 20  ail,suname,".   
d170: 20 20 20 20 20 22 20 20 73 76 65 72 69 66 69 65       "  sverifie
d180: 64 2c 73 64 6f 6e 6f 74 63 61 6c 6c 2c 73 64 69  d,sdonotcall,sdi
d190: 67 65 73 74 2c 73 73 75 62 2c 73 63 74 69 6d 65  gest,ssub,sctime
d1a0: 2c 6d 74 69 6d 65 2c 73 6d 69 70 29 22 0a 20 20  ,mtime,smip)".  
d1b0: 20 20 20 20 20 20 22 20 56 41 4c 55 45 53 28 25        " VALUES(%
d1c0: 51 2c 25 51 2c 25 64 2c 30 2c 25 64 2c 25 51 2c  Q,%Q,%d,0,%d,%Q,
d1d0: 6e 6f 77 28 29 2c 6e 6f 77 28 29 2c 25 51 29 22  now(),now(),%Q)"
d1e0: 0a 20 20 20 20 20 20 20 20 22 20 4f 4e 20 43 4f  .        " ON CO
d1f0: 4e 46 4c 49 43 54 28 73 65 6d 61 69 6c 29 20 44  NFLICT(semail) D
d200: 4f 20 55 50 44 41 54 45 22 0a 20 20 20 20 20 20  O UPDATE".      
d210: 20 20 22 20 20 20 53 45 54 20 73 75 6e 61 6d 65    "   SET suname
d220: 3d 65 78 63 6c 75 64 65 64 2e 73 75 6e 61 6d 65  =excluded.suname
d230: 22 2c 0a 20 20 20 20 20 20 20 20 2f 2a 20 73 65  ",.        /* se
d240: 6d 61 69 6c 20 2a 2f 20 20 20 20 7a 45 41 64 64  mail */    zEAdd
d250: 72 2c 0a 20 20 20 20 20 20 20 20 2f 2a 20 73 75  r,.        /* su
d260: 6e 61 6d 65 20 2a 2f 20 20 20 20 7a 55 73 65 72  name */    zUser
d270: 49 44 2c 0a 20 20 20 20 20 20 20 20 2f 2a 20 73  ID,.        /* s
d280: 76 65 72 69 66 69 65 64 20 2a 2f 20 30 2c 0a 20  verified */ 0,. 
d290: 20 20 20 20 20 20 20 2f 2a 20 73 64 69 67 65 73         /* sdiges
d2a0: 74 20 2a 2f 20 20 20 30 2c 0a 20 20 20 20 20 20  t */   0,.      
d2b0: 20 20 2f 2a 20 73 73 75 62 20 2a 2f 20 20 20 20    /* ssub */    
d2c0: 20 20 73 73 75 62 2c 0a 20 20 20 20 20 20 20 20    ssub,.        
d2d0: 2f 2a 20 73 6d 69 70 20 2a 2f 20 20 20 20 20 20  /* smip */      
d2e0: 67 2e 7a 49 70 41 64 64 72 0a 20 20 20 20 20 20  g.zIpAddr.      
d2f0: 29 3b 0a 20 20 20 20 20 20 69 64 20 3d 20 64 62  );.      id = db
d300: 5f 6c 61 73 74 5f 69 6e 73 65 72 74 5f 72 6f 77  _last_insert_row
d310: 69 64 28 29 3b 0a 20 20 20 20 20 20 69 66 28 20  id();.      if( 
d320: 64 62 5f 65 78 69 73 74 73 28 22 53 45 4c 45 43  db_exists("SELEC
d330: 54 20 31 20 46 52 4f 4d 20 73 75 62 73 63 72 69  T 1 FROM subscri
d340: 62 65 72 20 57 48 45 52 45 20 73 65 6d 61 69 6c  ber WHERE semail
d350: 3d 25 51 22 0a 20 20 20 20 20 20 20 20 20 20 20  =%Q".           
d360: 20 20 20 20 20 20 20 20 20 22 20 20 41 4e 44 20           "  AND 
d370: 73 76 65 72 69 66 69 65 64 22 2c 20 7a 45 41 64  sverified", zEAd
d380: 64 72 29 20 29 7b 0a 20 20 20 20 20 20 20 20 2f  dr) ){.        /
d390: 2a 20 54 68 69 73 20 74 68 65 20 63 61 73 65 20  * This the case 
d3a0: 77 68 65 72 65 20 74 68 65 20 75 73 65 72 20 77  where the user w
d3b0: 61 73 20 66 6f 72 6d 65 72 6c 79 20 61 20 76 65  as formerly a ve
d3c0: 72 69 66 69 65 64 20 73 75 62 73 63 72 69 62 65  rified subscribe
d3d0: 72 0a 20 20 20 20 20 20 20 20 2a 2a 20 61 6e 64  r.        ** and
d3e0: 20 68 65 72 65 20 74 68 65 79 20 68 61 76 65 20   here they have 
d3f0: 61 6c 73 6f 20 72 65 67 69 73 74 65 72 65 64 20  also registered 
d400: 61 73 20 61 20 75 73 65 72 20 61 73 20 77 65 6c  as a user as wel
d410: 6c 2e 20 20 49 74 20 69 73 0a 20 20 20 20 20 20  l.  It is.      
d420: 20 20 2a 2a 20 6e 6f 74 20 6e 65 63 65 73 73 61    ** not necessa
d430: 72 79 20 74 6f 20 72 65 70 65 61 74 20 74 68 65  ry to repeat the
d440: 20 76 65 72 66 69 63 61 74 69 6f 6e 20 73 74 65   verfication ste
d450: 70 20 2a 2f 0a 20 20 20 20 20 20 20 20 72 65 64  p */.        red
d460: 69 72 65 63 74 5f 74 6f 5f 67 28 29 3b 0a 20 20  irect_to_g();.  
d470: 20 20 20 20 7d 0a 20 20 20 20 20 20 7a 43 6f 64      }.      zCod
d480: 65 20 3d 20 64 62 5f 74 65 78 74 28 30 2c 0a 20  e = db_text(0,. 
d490: 20 20 20 20 20 20 20 20 20 20 22 53 45 4c 45 43            "SELEC
d4a0: 54 20 68 65 78 28 73 75 62 73 63 72 69 62 65 72  T hex(subscriber
d4b0: 43 6f 64 65 29 20 46 52 4f 4d 20 73 75 62 73 63  Code) FROM subsc
d4c0: 72 69 62 65 72 20 57 48 45 52 45 20 73 75 62 73  riber WHERE subs
d4d0: 63 72 69 62 65 72 49 64 3d 25 6c 6c 64 22 2c 0a  criberId=%lld",.
d4e0: 20 20 20 20 20 20 20 20 20 20 20 69 64 29 3b 0a             id);.
d4f0: 20 20 20 20 20 20 2f 2a 20 41 20 76 65 72 69 66        /* A verif
d500: 69 63 61 74 69 6f 6e 20 65 6d 61 69 6c 20 2a 2f  ication email */
d510: 0a 20 20 20 20 20 20 70 53 65 6e 64 65 72 20 3d  .      pSender =
d520: 20 61 6c 65 72 74 5f 73 65 6e 64 65 72 5f 6e 65   alert_sender_ne
d530: 77 28 30 2c 30 29 3b 0a 20 20 20 20 20 20 62 6c  w(0,0);.      bl
d540: 6f 62 5f 69 6e 69 74 28 26 68 64 72 2c 30 2c 30  ob_init(&hdr,0,0
d550: 29 3b 0a 20 20 20 20 20 20 62 6c 6f 62 5f 69 6e  );.      blob_in
d560: 69 74 28 26 62 6f 64 79 2c 30 2c 30 29 3b 0a 20  it(&body,0,0);. 
d570: 20 20 20 20 20 62 6c 6f 62 5f 61 70 70 65 6e 64       blob_append
d580: 66 28 26 68 64 72 2c 20 22 54 6f 3a 20 3c 25 73  f(&hdr, "To: <%s
d590: 3e 5c 6e 22 2c 20 7a 45 41 64 64 72 29 3b 0a 20  >\n", zEAddr);. 
d5a0: 20 20 20 20 20 62 6c 6f 62 5f 61 70 70 65 6e 64       blob_append
d5b0: 66 28 26 68 64 72 2c 20 22 53 75 62 6a 65 63 74  f(&hdr, "Subject
d5c0: 3a 20 53 75 62 73 63 72 69 70 74 69 6f 6e 20 76  : Subscription v
d5d0: 65 72 69 66 69 63 61 74 69 6f 6e 5c 6e 22 29 3b  erification\n");
d5e0: 0a 20 20 20 20 20 20 61 6c 65 72 74 5f 61 70 70  .      alert_app
d5f0: 65 6e 64 5f 63 6f 6e 66 69 72 6d 61 74 69 6f 6e  end_confirmation
d600: 5f 6d 65 73 73 61 67 65 28 26 62 6f 64 79 2c 20  _message(&body, 
d610: 7a 43 6f 64 65 29 3b 0a 20 20 20 20 20 20 61 6c  zCode);.      al
d620: 65 72 74 5f 73 65 6e 64 28 70 53 65 6e 64 65 72  ert_send(pSender
d630: 2c 20 26 68 64 72 2c 20 26 62 6f 64 79 2c 20 30  , &hdr, &body, 0
d640: 29 3b 0a 20 20 20 20 20 20 73 74 79 6c 65 5f 68  );.      style_h
d650: 65 61 64 65 72 28 22 45 6d 61 69 6c 20 56 65 72  eader("Email Ver
d660: 69 66 69 63 61 74 69 6f 6e 22 29 3b 0a 20 20 20  ification");.   
d670: 20 20 20 69 66 28 20 70 53 65 6e 64 65 72 2d 3e     if( pSender->
d680: 7a 45 72 72 20 29 7b 0a 20 20 20 20 20 20 20 20  zErr ){.        
d690: 40 20 3c 68 31 3e 49 6e 74 65 72 6e 61 6c 20 45  @ <h1>Internal E
d6a0: 72 72 6f 72 3c 2f 68 31 3e 0a 20 20 20 20 20 20  rror</h1>.      
d6b0: 20 20 40 20 3c 70 3e 54 68 65 20 66 6f 6c 6c 6f    @ <p>The follo
d6c0: 77 69 6e 67 20 69 6e 74 65 72 6e 61 6c 20 65 72  wing internal er
d6d0: 72 6f 72 20 77 61 73 20 65 6e 63 6f 75 6e 74 65  ror was encounte
d6e0: 72 65 64 20 77 68 69 6c 65 20 74 72 79 69 6e 67  red while trying
d6f0: 0a 20 20 20 20 20 20 20 20 40 20 74 6f 20 73 65  .        @ to se
d700: 6e 64 20 74 68 65 20 63 6f 6e 66 69 72 6d 61 74  nd the confirmat
d710: 69 6f 6e 20 65 6d 61 69 6c 3a 0a 20 20 20 20 20  ion email:.     
d720: 20 20 20 40 20 3c 62 6c 6f 63 6b 71 75 6f 74 65     @ <blockquote
d730: 3e 3c 70 72 65 3e 0a 20 20 20 20 20 20 20 20 40  ><pre>.        @
d740: 20 25 68 28 70 53 65 6e 64 65 72 2d 3e 7a 45 72   %h(pSender->zEr
d750: 72 29 0a 20 20 20 20 20 20 20 20 40 20 3c 2f 70  r).        @ </p
d760: 72 65 3e 3c 2f 62 6c 6f 63 6b 71 75 6f 74 65 3e  re></blockquote>
d770: 0a 20 20 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20  .      }else{.  
d780: 20 20 20 20 20 20 40 20 3c 70 3e 41 6e 20 65 6d        @ <p>An em
d790: 61 69 6c 20 68 61 73 20 62 65 65 6e 20 73 65 6e  ail has been sen
d7a0: 74 20 74 6f 20 22 25 68 28 7a 45 41 64 64 72 29  t to "%h(zEAddr)
d7b0: 22 2e 20 54 68 61 74 20 65 6d 61 69 6c 20 63 6f  ". That email co
d7c0: 6e 74 61 69 6e 73 20 61 0a 20 20 20 20 20 20 20  ntains a.       
d7d0: 20 40 20 68 79 70 65 72 6c 69 6e 6b 20 74 68 61   @ hyperlink tha
d7e0: 74 20 79 6f 75 20 6d 75 73 74 20 63 6c 69 63 6b  t you must click
d7f0: 20 6f 6e 20 69 6e 20 6f 72 64 65 72 20 74 6f 20   on in order to 
d800: 61 63 74 69 76 61 74 65 20 79 6f 75 72 0a 20 20  activate your.  
d810: 20 20 20 20 20 20 40 20 73 75 62 73 63 72 69 70        @ subscrip
d820: 74 69 6f 6e 2e 3c 2f 70 3e 0a 20 20 20 20 20 20  tion.</p>.      
d830: 7d 0a 20 20 20 20 20 20 61 6c 65 72 74 5f 73 65  }.      alert_se
d840: 6e 64 65 72 5f 66 72 65 65 28 70 53 65 6e 64 65  nder_free(pSende
d850: 72 29 3b 0a 20 20 20 20 20 20 69 66 28 20 7a 47  r);.      if( zG
d860: 6f 74 6f 20 29 7b 0a 20 20 20 20 20 20 20 20 40  oto ){.        @
d870: 20 3c 70 3e 3c 61 20 68 72 65 66 3d 27 25 68 28   <p><a href='%h(
d880: 7a 47 6f 74 6f 29 27 3e 43 6f 6e 74 69 6e 75 65  zGoto)'>Continue
d890: 3c 2f 61 3e 0a 20 20 20 20 20 20 7d 0a 20 20 20  </a>.      }.   
d8a0: 20 20 20 73 74 79 6c 65 5f 66 6f 6f 74 65 72 28     style_footer(
d8b0: 29 3b 0a 20 20 20 20 20 20 72 65 74 75 72 6e 3b  );.      return;
d8c0: 0a 20 20 20 20 7d 0a 20 20 20 20 72 65 64 69 72  .    }.    redir
d8d0: 65 63 74 5f 74 6f 5f 67 28 29 3b 0a 20 20 7d 0a  ect_to_g();.  }.
d8e0: 0a 20 20 2f 2a 20 50 72 65 70 61 72 65 20 74 68  .  /* Prepare th
d8f0: 65 20 63 61 70 74 63 68 61 2e 20 2a 2f 0a 20 20  e captcha. */.  
d900: 75 53 65 65 64 20 3d 20 63 61 70 74 63 68 61 5f  uSeed = captcha_
d910: 73 65 65 64 28 29 3b 0a 20 20 7a 44 65 63 6f 64  seed();.  zDecod
d920: 65 64 20 3d 20 63 61 70 74 63 68 61 5f 64 65 63  ed = captcha_dec
d930: 6f 64 65 28 75 53 65 65 64 29 3b 0a 20 20 7a 43  ode(uSeed);.  zC
d940: 61 70 74 63 68 61 20 3d 20 63 61 70 74 63 68 61  aptcha = captcha
d950: 5f 72 65 6e 64 65 72 28 7a 44 65 63 6f 64 65 64  _render(zDecoded
d960: 29 3b 0a 0a 20 20 73 74 79 6c 65 5f 68 65 61 64  );..  style_head
d970: 65 72 28 22 52 65 67 69 73 74 65 72 22 29 3b 0a  er("Register");.
d980: 20 20 2f 2a 20 50 72 69 6e 74 20 6f 75 74 20 74    /* Print out t
d990: 68 65 20 72 65 67 69 73 74 72 61 74 69 6f 6e 20  he registration 
d9a0: 66 6f 72 6d 2e 20 2a 2f 0a 20 20 66 6f 72 6d 5f  form. */.  form_
d9b0: 62 65 67 69 6e 28 30 2c 20 22 25 52 2f 72 65 67  begin(0, "%R/reg
d9c0: 69 73 74 65 72 22 29 3b 0a 20 20 69 66 28 20 50  ister");.  if( P
d9d0: 28 22 67 22 29 20 29 7b 0a 20 20 20 20 40 20 3c  ("g") ){.    @ <
d9e0: 69 6e 70 75 74 20 74 79 70 65 3d 22 68 69 64 64  input type="hidd
d9f0: 65 6e 22 20 6e 61 6d 65 3d 22 67 22 20 76 61 6c  en" name="g" val
da00: 75 65 3d 22 25 68 28 50 28 22 67 22 29 29 22 20  ue="%h(P("g"))" 
da10: 2f 3e 0a 20 20 7d 0a 20 20 40 20 3c 70 3e 3c 69  />.  }.  @ <p><i
da20: 6e 70 75 74 20 74 79 70 65 3d 22 68 69 64 64 65  nput type="hidde
da30: 6e 22 20 6e 61 6d 65 3d 22 63 61 70 74 63 68 61  n" name="captcha
da40: 73 65 65 64 22 20 76 61 6c 75 65 3d 22 25 75 28  seed" value="%u(
da50: 75 53 65 65 64 29 22 20 2f 3e 0a 20 20 40 20 3c  uSeed)" />.  @ <
da60: 74 61 62 6c 65 20 63 6c 61 73 73 3d 22 6c 6f 67  table class="log
da70: 69 6e 5f 6f 75 74 22 3e 0a 20 20 40 20 3c 74 72  in_out">.  @ <tr
da80: 3e 0a 20 20 40 20 20 20 3c 74 64 20 63 6c 61 73  >.  @   <td clas
da90: 73 3d 22 66 6f 72 6d 5f 6c 61 62 65 6c 22 20 61  s="form_label" a
daa0: 6c 69 67 6e 3d 22 72 69 67 68 74 22 3e 55 73 65  lign="right">Use
dab0: 72 20 49 44 3a 3c 2f 74 64 3e 0a 20 20 40 20 20  r ID:</td>.  @  
dac0: 20 3c 74 64 3e 3c 69 6e 70 75 74 20 74 79 70 65   <td><input type
dad0: 3d 22 74 65 78 74 22 20 6e 61 6d 65 3d 22 75 22  ="text" name="u"
dae0: 20 76 61 6c 75 65 3d 22 25 68 28 7a 55 73 65 72   value="%h(zUser
daf0: 49 44 29 22 20 73 69 7a 65 3d 22 33 30 22 3e 3c  ID)" size="30"><
db00: 2f 74 64 3e 0a 20 20 40 0a 20 20 69 66 28 20 69  /td>.  @.  if( i
db10: 45 72 72 4c 69 6e 65 3d 3d 31 20 29 7b 0a 20 20  ErrLine==1 ){.  
db20: 20 20 40 20 3c 74 72 3e 3c 74 64 3e 3c 74 64 3e    @ <tr><td><td>
db30: 3c 73 70 61 6e 20 63 6c 61 73 73 3d 27 6c 6f 67  <span class='log
db40: 69 6e 45 72 72 6f 72 27 3e 26 75 61 72 72 3b 20  inError'>&uarr; 
db50: 25 68 28 7a 45 72 72 29 3c 2f 73 70 61 6e 3e 3c  %h(zErr)</span><
db60: 2f 74 64 3e 3c 2f 74 72 3e 0a 20 20 7d 0a 20 20  /td></tr>.  }.  
db70: 40 20 3c 74 72 3e 0a 20 20 40 20 20 20 3c 74 64  @ <tr>.  @   <td
db80: 20 63 6c 61 73 73 3d 22 66 6f 72 6d 5f 6c 61 62   class="form_lab
db90: 65 6c 22 20 61 6c 69 67 6e 3d 22 72 69 67 68 74  el" align="right
dba0: 22 3e 44 69 73 70 6c 61 79 20 4e 61 6d 65 3a 3c  ">Display Name:<
dbb0: 2f 74 64 3e 0a 20 20 40 20 20 20 3c 74 64 3e 3c  /td>.  @   <td><
dbc0: 69 6e 70 75 74 20 74 79 70 65 3d 22 74 65 78 74  input type="text
dbd0: 22 20 6e 61 6d 65 3d 22 64 6e 22 20 76 61 6c 75  " name="dn" valu
dbe0: 65 3d 22 25 68 28 7a 44 4e 61 6d 65 29 22 20 73  e="%h(zDName)" s
dbf0: 69 7a 65 3d 22 33 30 22 3e 3c 2f 74 64 3e 0a 20  ize="30"></td>. 
dc00: 20 40 20 3c 2f 74 72 3e 0a 20 20 69 66 28 20 69   @ </tr>.  if( i
dc10: 45 72 72 4c 69 6e 65 3d 3d 32 20 29 7b 0a 20 20  ErrLine==2 ){.  
dc20: 20 20 40 20 3c 74 72 3e 3c 74 64 3e 3c 74 64 3e    @ <tr><td><td>
dc30: 3c 73 70 61 6e 20 63 6c 61 73 73 3d 27 6c 6f 67  <span class='log
dc40: 69 6e 45 72 72 6f 72 27 3e 26 75 61 72 72 3b 20  inError'>&uarr; 
dc50: 25 68 28 7a 45 72 72 29 3c 2f 73 70 61 6e 3e 3c  %h(zErr)</span><
dc60: 2f 74 64 3e 3c 2f 74 72 3e 0a 20 20 7d 0a 20 20  /td></tr>.  }.  
dc70: 40 20 3c 2f 74 72 3e 0a 20 20 40 20 3c 74 72 3e  @ </tr>.  @ <tr>
dc80: 0a 20 20 40 20 20 20 3c 74 64 20 63 6c 61 73 73  .  @   <td class
dc90: 3d 22 66 6f 72 6d 5f 6c 61 62 65 6c 22 20 61 6c  ="form_label" al
dca0: 69 67 6e 3d 22 72 69 67 68 74 22 3e 45 6d 61 69  ign="right">Emai
dcb0: 6c 20 41 64 64 72 65 73 73 3a 3c 2f 74 64 3e 0a  l Address:</td>.
dcc0: 20 20 40 20 20 20 3c 74 64 3e 3c 69 6e 70 75 74    @   <td><input
dcd0: 20 74 79 70 65 3d 22 74 65 78 74 22 20 6e 61 6d   type="text" nam
dce0: 65 3d 22 65 61 22 20 76 61 6c 75 65 3d 22 25 68  e="ea" value="%h
dcf0: 28 7a 45 41 64 64 72 29 22 20 73 69 7a 65 3d 22  (zEAddr)" size="
dd00: 33 30 22 3e 3c 2f 74 64 3e 0a 20 20 40 20 3c 2f  30"></td>.  @ </
dd10: 74 72 3e 0a 20 20 69 66 28 20 69 45 72 72 4c 69  tr>.  if( iErrLi
dd20: 6e 65 3d 3d 33 20 29 7b 0a 20 20 20 20 40 20 3c  ne==3 ){.    @ <
dd30: 74 72 3e 3c 74 64 3e 3c 74 64 3e 3c 73 70 61 6e  tr><td><td><span
dd40: 20 63 6c 61 73 73 3d 27 6c 6f 67 69 6e 45 72 72   class='loginErr
dd50: 6f 72 27 3e 26 75 61 72 72 3b 20 25 68 28 7a 45  or'>&uarr; %h(zE
dd60: 72 72 29 3c 2f 73 70 61 6e 3e 3c 2f 74 64 3e 3c  rr)</span></td><
dd70: 2f 74 72 3e 0a 20 20 7d 0a 20 20 69 66 28 20 63  /tr>.  }.  if( c
dd80: 61 6e 44 6f 41 6c 65 72 74 73 20 29 7b 0a 20 20  anDoAlerts ){.  
dd90: 20 20 69 6e 74 20 61 20 3d 20 61 74 6f 69 28 50    int a = atoi(P
dda0: 44 28 22 61 6c 65 72 74 73 22 2c 22 31 22 29 29  D("alerts","1"))
ddb0: 3b 0a 20 20 20 20 40 20 3c 74 72 3e 0a 20 20 20  ;.    @ <tr>.   
ddc0: 20 40 20 20 20 3c 74 64 20 63 6c 61 73 73 3d 22   @   <td class="
ddd0: 66 6f 72 6d 5f 6c 61 62 65 6c 22 20 61 6c 69 67  form_label" alig
dde0: 6e 3d 22 72 69 67 68 74 22 3e 45 6d 61 69 6c 26  n="right">Email&
ddf0: 6e 62 73 70 3b 41 6c 65 72 74 73 3f 3c 2f 74 64  nbsp;Alerts?</td
de00: 3e 0a 20 20 20 20 40 20 20 20 3c 74 64 3e 3c 73  >.    @   <td><s
de10: 65 6c 65 63 74 20 73 69 7a 65 3d 27 31 27 20 6e  elect size='1' n
de20: 61 6d 65 3d 27 61 6c 65 72 74 73 27 3e 0a 20 20  ame='alerts'>.  
de30: 20 20 40 20 20 20 20 20 20 20 3c 6f 70 74 69 6f    @       <optio
de40: 6e 20 76 61 6c 75 65 3d 22 31 22 20 25 73 28 61  n value="1" %s(a
de50: 3f 22 73 65 6c 65 63 74 65 64 22 3a 22 22 29 3e  ?"selected":"")>
de60: 59 65 73 3c 2f 6f 70 74 69 6f 6e 3e 0a 20 20 20  Yes</option>.   
de70: 20 40 20 20 20 20 20 20 20 3c 6f 70 74 69 6f 6e   @       <option
de80: 20 76 61 6c 75 65 3d 22 30 22 20 25 73 28 21 61   value="0" %s(!a
de90: 3f 22 73 65 6c 65 63 74 65 64 22 3a 22 22 29 3e  ?"selected":"")>
dea0: 4e 6f 3c 2f 6f 70 74 69 6f 6e 3e 0a 20 20 20 20  No</option>.    
deb0: 40 20 20 20 3c 2f 73 65 6c 65 63 74 3e 3c 2f 74  @   </select></t
dec0: 64 3e 3c 2f 74 72 3e 0a 20 20 7d 0a 20 20 40 20  d></tr>.  }.  @ 
ded0: 3c 74 72 3e 0a 20 20 40 20 20 20 3c 74 64 20 63  <tr>.  @   <td c
dee0: 6c 61 73 73 3d 22 66 6f 72 6d 5f 6c 61 62 65 6c  lass="form_label
def0: 22 20 61 6c 69 67 6e 3d 22 72 69 67 68 74 22 3e  " align="right">
df00: 50 61 73 73 77 6f 72 64 3a 3c 2f 74 64 3e 0a 20  Password:</td>. 
df10: 20 40 20 20 20 3c 74 64 3e 3c 69 6e 70 75 74 20   @   <td><input 
df20: 74 79 70 65 3d 22 70 61 73 73 77 6f 72 64 22 20  type="password" 
df30: 6e 61 6d 65 3d 22 70 22 20 76 61 6c 75 65 3d 22  name="p" value="
df40: 25 68 28 7a 50 61 73 73 77 64 29 22 20 73 69 7a  %h(zPasswd)" siz
df50: 65 3d 22 33 30 22 3e 3c 2f 74 64 3e 0a 20 20 40  e="30"></td>.  @
df60: 20 3c 74 72 3e 0a 20 20 69 66 28 20 69 45 72 72   <tr>.  if( iErr
df70: 4c 69 6e 65 3d 3d 34 20 29 7b 0a 20 20 20 20 40  Line==4 ){.    @
df80: 20 3c 74 72 3e 3c 74 64 3e 3c 74 64 3e 3c 73 70   <tr><td><td><sp
df90: 61 6e 20 63 6c 61 73 73 3d 27 6c 6f 67 69 6e 45  an class='loginE
dfa0: 72 72 6f 72 27 3e 26 75 61 72 72 3b 20 25 68 28  rror'>&uarr; %h(
dfb0: 7a 45 72 72 29 3c 2f 73 70 61 6e 3e 3c 2f 74 64  zErr)</span></td
dfc0: 3e 3c 2f 74 72 3e 0a 20 20 7d 0a 20 20 40 20 3c  ></tr>.  }.  @ <
dfd0: 74 72 3e 0a 20 20 40 20 20 20 3c 74 64 20 63 6c  tr>.  @   <td cl
dfe0: 61 73 73 3d 22 66 6f 72 6d 5f 6c 61 62 65 6c 22  ass="form_label"
dff0: 20 61 6c 69 67 6e 3d 22 72 69 67 68 74 22 3e 43   align="right">C
e000: 6f 6e 66 69 72 6d 3a 3c 2f 74 64 3e 0a 20 20 40  onfirm:</td>.  @
e010: 20 20 20 3c 74 64 3e 3c 69 6e 70 75 74 20 74 79     <td><input ty
e020: 70 65 3d 22 70 61 73 73 77 6f 72 64 22 20 6e 61  pe="password" na
e030: 6d 65 3d 22 63 70 22 20 76 61 6c 75 65 3d 22 25  me="cp" value="%
e040: 68 28 7a 43 6f 6e 66 69 72 6d 29 22 20 73 69 7a  h(zConfirm)" siz
e050: 65 3d 22 33 30 22 3e 3c 2f 74 64 3e 0a 20 20 40  e="30"></td>.  @
e060: 20 3c 2f 74 72 3e 0a 20 20 69 66 28 20 69 45 72   </tr>.  if( iEr
e070: 72 4c 69 6e 65 3d 3d 35 20 29 7b 0a 20 20 20 20  rLine==5 ){.    
e080: 40 20 3c 74 72 3e 3c 74 64 3e 3c 74 64 3e 3c 73  @ <tr><td><td><s
e090: 70 61 6e 20 63 6c 61 73 73 3d 27 6c 6f 67 69 6e  pan class='login
e0a0: 45 72 72 6f 72 27 3e 26 75 61 72 72 3b 20 25 68  Error'>&uarr; %h
e0b0: 28 7a 45 72 72 29 3c 2f 73 70 61 6e 3e 3c 2f 74  (zErr)</span></t
e0c0: 64 3e 3c 2f 74 72 3e 0a 20 20 7d 0a 20 20 40 20  d></tr>.  }.  @ 
e0d0: 3c 74 72 3e 0a 20 20 40 20 20 20 3c 74 64 20 63  <tr>.  @   <td c
e0e0: 6c 61 73 73 3d 22 66 6f 72 6d 5f 6c 61 62 65 6c  lass="form_label
e0f0: 22 20 61 6c 69 67 6e 3d 22 72 69 67 68 74 22 3e  " align="right">
e100: 43 61 70 74 63 68 61 3a 3c 2f 74 64 3e 0a 20 20  Captcha:</td>.  
e110: 40 20 20 20 3c 74 64 3e 3c 69 6e 70 75 74 20 74  @   <td><input t
e120: 79 70 65 3d 22 74 65 78 74 22 20 6e 61 6d 65 3d  ype="text" name=
e130: 22 63 61 70 74 63 68 61 22 20 76 61 6c 75 65 3d  "captcha" value=
e140: 22 22 20 73 69 7a 65 3d 22 33 30 22 3e 3c 2f 74  "" size="30"></t
e150: 64 3e 0a 20 20 40 20 3c 2f 74 72 3e 0a 20 20 69  d>.  @ </tr>.  i
e160: 66 28 20 69 45 72 72 4c 69 6e 65 3d 3d 36 20 29  f( iErrLine==6 )
e170: 7b 0a 20 20 20 20 40 20 3c 74 72 3e 3c 74 64 3e  {.    @ <tr><td>
e180: 3c 74 64 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d  <td><span class=
e190: 27 6c 6f 67 69 6e 45 72 72 6f 72 27 3e 26 75 61  'loginError'>&ua
e1a0: 72 72 3b 20 25 68 28 7a 45 72 72 29 3c 2f 73 70  rr; %h(zErr)</sp
e1b0: 61 6e 3e 3c 2f 74 64 3e 3c 2f 74 72 3e 0a 20 20  an></td></tr>.  
e1c0: 7d 0a 20 20 40 20 3c 74 72 3e 3c 74 64 3e 3c 2f  }.  @ <tr><td></
e1d0: 74 64 3e 0a 20 20 40 20 3c 74 64 3e 3c 69 6e 70  td>.  @ <td><inp
e1e0: 75 74 20 74 79 70 65 3d 22 73 75 62 6d 69 74 22  ut type="submit"
e1f0: 20 6e 61 6d 65 3d 22 6e 65 77 22 20 76 61 6c 75   name="new" valu
e200: 65 3d 22 52 65 67 69 73 74 65 72 22 20 2f 3e 3c  e="Register" /><
e210: 2f 74 64 3e 3c 2f 74 72 3e 0a 20 20 40 20 3c 2f  /td></tr>.  @ </
e220: 74 61 62 6c 65 3e 0a 20 20 40 20 3c 64 69 76 20  table>.  @ <div 
e230: 63 6c 61 73 73 3d 22 63 61 70 74 63 68 61 22 3e  class="captcha">
e240: 3c 74 61 62 6c 65 20 63 6c 61 73 73 3d 22 63 61  <table class="ca
e250: 70 74 63 68 61 22 3e 3c 74 72 3e 3c 74 64 3e 3c  ptcha"><tr><td><
e260: 70 72 65 20 63 6c 61 73 73 3d 22 63 61 70 74 63  pre class="captc
e270: 68 61 22 3e 0a 20 20 40 20 25 68 28 7a 43 61 70  ha">.  @ %h(zCap
e280: 74 63 68 61 29 0a 20 20 40 20 3c 2f 70 72 65 3e  tcha).  @ </pre>
e290: 0a 20 20 40 20 45 6e 74 65 72 20 74 68 69 73 20  .  @ Enter this 
e2a0: 38 2d 6c 65 74 74 65 72 20 63 6f 64 65 20 69 6e  8-letter code in
e2b0: 20 74 68 65 20 22 43 61 70 74 63 68 61 22 20 62   the "Captcha" b
e2c0: 6f 78 20 61 62 6f 76 65 2e 0a 20 20 40 20 3c 2f  ox above..  @ </
e2d0: 74 64 3e 3c 2f 74 72 3e 3c 2f 74 61 62 6c 65 3e  td></tr></table>
e2e0: 3c 2f 64 69 76 3e 0a 20 20 40 20 3c 2f 66 6f 72  </div>.  @ </for
e2f0: 6d 3e 0a 20 20 73 74 79 6c 65 5f 66 6f 6f 74 65  m>.  style_foote
e300: 72 28 29 3b 0a 0a 20 20 66 72 65 65 28 7a 43 61  r();..  free(zCa
e310: 70 74 63 68 61 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a  ptcha);.}../*.**
e320: 20 52 75 6e 20 53 51 4c 20 6f 6e 20 74 68 65 20   Run SQL on the 
e330: 72 65 70 6f 73 69 74 6f 72 79 20 64 61 74 61 62  repository datab
e340: 61 73 65 20 66 6f 72 20 65 76 65 72 79 20 72 65  ase for every re
e350: 70 6f 73 69 74 6f 72 79 20 69 6e 20 6f 75 72 0a  pository in our.
e360: 2a 2a 20 6c 6f 67 69 6e 20 67 72 6f 75 70 2e 20  ** login group. 
e370: 20 54 68 65 20 53 51 4c 20 69 73 20 72 75 6e 20   The SQL is run 
e380: 69 6e 20 61 20 73 65 70 61 72 61 74 65 20 64 61  in a separate da
e390: 74 61 62 61 73 65 20 63 6f 6e 6e 65 63 74 69 6f  tabase connectio
e3a0: 6e 2e 0a 2a 2a 0a 2a 2a 20 41 6e 79 20 6d 65 6d  n..**.** Any mem
e3b0: 62 65 72 73 20 6f 66 20 74 68 65 20 6c 6f 67 69  bers of the logi
e3c0: 6e 20 67 72 6f 75 70 20 77 68 6f 73 65 20 72 65  n group whose re
e3d0: 70 6f 73 69 74 6f 72 79 20 64 61 74 61 62 61 73  pository databas
e3e0: 65 20 66 69 6c 65 0a 2a 2a 20 63 61 6e 6e 6f 74  e file.** cannot
e3f0: 20 62 65 20 66 6f 75 6e 64 20 69 73 20 73 69 6c   be found is sil
e400: 65 6e 74 6c 79 20 72 65 6d 6f 76 65 64 20 66 72  ently removed fr
e410: 6f 6d 20 74 68 65 20 67 72 6f 75 70 2e 0a 2a 2a  om the group..**
e420: 0a 2a 2a 20 45 72 72 6f 72 20 6d 65 73 73 61 67  .** Error messag
e430: 65 73 20 61 63 63 75 6d 75 6c 61 74 65 20 61 6e  es accumulate an
e440: 64 20 61 72 65 20 72 65 74 75 72 6e 65 64 20 69  d are returned i
e450: 6e 20 2a 70 7a 45 72 72 6f 72 4d 73 67 2e 20 20  n *pzErrorMsg.  
e460: 54 68 65 0a 2a 2a 20 6d 65 6d 6f 72 79 20 75 73  The.** memory us
e470: 65 64 20 74 6f 20 68 6f 6c 64 20 74 68 65 73 65  ed to hold these
e480: 20 6d 65 73 73 61 67 65 73 20 73 68 6f 75 6c 64   messages should
e490: 20 62 65 20 66 72 65 65 64 20 75 73 69 6e 67 0a   be freed using.
e4a0: 2a 2a 20 66 6f 73 73 69 6c 5f 66 72 65 65 28 29  ** fossil_free()
e4b0: 20 69 66 20 6f 6e 65 20 64 65 73 69 72 65 64 20   if one desired 
e4c0: 74 6f 20 61 76 6f 69 64 20 61 20 6d 65 6d 6f 72  to avoid a memor
e4d0: 79 20 6c 65 61 6b 2e 20 20 54 68 65 0a 2a 2a 20  y leak.  The.** 
e4e0: 7a 50 72 65 66 69 78 20 61 6e 64 20 7a 53 75 66  zPrefix and zSuf
e4f0: 66 69 78 20 73 74 72 69 6e 67 73 20 73 75 72 72  fix strings surr
e500: 6f 75 6e 64 20 65 61 63 68 20 65 72 72 6f 72 20  ound each error 
e510: 6d 65 73 73 61 67 65 2e 0a 2a 2a 0a 2a 2a 20 52  message..**.** R
e520: 65 74 75 72 6e 20 74 68 65 20 6e 75 6d 62 65 72  eturn the number
e530: 20 6f 66 20 65 72 72 6f 72 73 2e 0a 2a 2f 0a 69   of errors..*/.i
e540: 6e 74 20 6c 6f 67 69 6e 5f 67 72 6f 75 70 5f 73  nt login_group_s
e550: 71 6c 28 0a 20 20 63 6f 6e 73 74 20 63 68 61 72  ql(.  const char
e560: 20 2a 7a 53 71 6c 2c 20 20 20 20 20 20 20 20 2f   *zSql,        /
e570: 2a 20 54 68 65 20 53 51 4c 20 74 6f 20 72 75 6e  * The SQL to run
e580: 20 2a 2f 0a 20 20 63 6f 6e 73 74 20 63 68 61 72   */.  const char
e590: 20 2a 7a 50 72 65 66 69 78 2c 20 20 20 20 20 2f   *zPrefix,     /
e5a0: 2a 20 50 72 65 66 69 78 20 74 6f 20 65 61 63 68  * Prefix to each
e5b0: 20 65 72 72 6f 72 20 6d 65 73 73 61 67 65 20 2a   error message *
e5c0: 2f 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a  /.  const char *
e5d0: 7a 53 75 66 66 69 78 2c 20 20 20 20 20 2f 2a 20  zSuffix,     /* 
e5e0: 53 75 66 66 69 78 20 74 6f 20 65 61 63 68 20 65  Suffix to each e
e5f0: 72 72 6f 72 20 6d 65 73 73 61 67 65 20 2a 2f 0a  rror message */.
e600: 20 20 63 68 61 72 20 2a 2a 70 7a 45 72 72 6f 72    char **pzError
e610: 4d 73 67 20 20 20 20 20 20 20 20 2f 2a 20 57 72  Msg        /* Wr
e620: 69 74 65 20 65 72 72 6f 72 20 6d 65 73 73 61 67  ite error messag
e630: 65 20 68 65 72 65 2c 20 69 66 20 6e 6f 74 20 4e  e here, if not N
e640: 55 4c 4c 20 2a 2f 0a 29 7b 0a 20 20 73 71 6c 69  ULL */.){.  sqli
e650: 74 65 33 20 2a 70 50 65 65 72 3b 20 20 20 20 20  te3 *pPeer;     
e660: 20 20 20 20 20 2f 2a 20 43 6f 6e 6e 65 63 74 69       /* Connecti
e670: 6f 6e 20 74 6f 20 61 6e 6f 74 68 65 72 20 64 61  on to another da
e680: 74 61 62 61 73 65 20 2a 2f 0a 20 20 69 6e 74 20  tabase */.  int 
e690: 6e 45 72 72 20 3d 20 30 3b 20 20 20 20 20 20 20  nErr = 0;       
e6a0: 20 20 20 20 20 2f 2a 20 4e 75 6d 62 65 72 20 6f       /* Number o
e6b0: 66 20 65 72 72 6f 72 73 20 73 65 65 6e 20 73 6f  f errors seen so
e6c0: 20 66 61 72 20 2a 2f 0a 20 20 69 6e 74 20 72 63   far */.  int rc
e6d0: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ;               
e6e0: 20 20 20 2f 2a 20 52 65 73 75 6c 74 20 63 6f 64     /* Result cod
e6f0: 65 20 66 72 6f 6d 20 73 75 62 72 6f 75 74 69 6e  e from subroutin
e700: 65 20 63 61 6c 6c 73 20 2a 2f 0a 20 20 63 68 61  e calls */.  cha
e710: 72 20 2a 7a 45 72 72 3b 20 20 20 20 20 20 20 20  r *zErr;        
e720: 20 20 20 20 20 20 2f 2a 20 53 51 4c 69 74 65 20        /* SQLite 
e730: 65 72 72 6f 72 20 74 65 78 74 20 2a 2f 0a 20 20  error text */.  
e740: 63 68 61 72 20 2a 7a 53 65 6c 66 43 6f 64 65 3b  char *zSelfCode;
e750: 20 20 20 20 20 20 20 20 20 2f 2a 20 50 72 6f 6a           /* Proj
e760: 65 63 74 20 63 6f 64 65 20 66 6f 72 20 6f 75 72  ect code for our
e770: 73 65 6c 66 20 2a 2f 0a 20 20 42 6c 6f 62 20 65  self */.  Blob e
e780: 72 72 3b 20 20 20 20 20 20 20 20 20 20 20 20 20  rr;             
e790: 20 20 20 2f 2a 20 41 63 63 75 6d 75 6c 61 74 65     /* Accumulate
e7a0: 20 65 72 72 6f 72 73 20 68 65 72 65 20 2a 2f 0a   errors here */.
e7b0: 20 20 53 74 6d 74 20 71 3b 20 20 20 20 20 20 20    Stmt q;       
e7c0: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 51 75             /* Qu
e7d0: 65 72 79 20 6f 66 20 61 6c 6c 20 70 65 65 72 2d  ery of all peer-
e7e0: 2a 20 65 6e 74 72 69 65 73 20 69 6e 20 43 4f 4e  * entries in CON
e7f0: 46 49 47 20 2a 2f 0a 0a 20 20 69 66 28 20 7a 50  FIG */..  if( zP
e800: 72 65 66 69 78 3d 3d 30 20 29 20 7a 50 72 65 66  refix==0 ) zPref
e810: 69 78 20 3d 20 22 22 3b 0a 20 20 69 66 28 20 7a  ix = "";.  if( z
e820: 53 75 66 66 69 78 3d 3d 30 20 29 20 7a 53 75 66  Suffix==0 ) zSuf
e830: 66 69 78 20 3d 20 22 22 3b 0a 20 20 69 66 28 20  fix = "";.  if( 
e840: 70 7a 45 72 72 6f 72 4d 73 67 20 29 20 2a 70 7a  pzErrorMsg ) *pz
e850: 45 72 72 6f 72 4d 73 67 20 3d 20 30 3b 0a 20 20  ErrorMsg = 0;.  
e860: 7a 53 65 6c 66 43 6f 64 65 20 3d 20 61 62 62 72  zSelfCode = abbr
e870: 65 76 69 61 74 65 64 5f 70 72 6f 6a 65 63 74 5f  eviated_project_
e880: 63 6f 64 65 28 64 62 5f 67 65 74 28 22 70 72 6f  code(db_get("pro
e890: 6a 65 63 74 2d 63 6f 64 65 22 2c 20 22 78 22 29  ject-code", "x")
e8a0: 29 3b 0a 20 20 62 6c 6f 62 5f 7a 65 72 6f 28 26  );.  blob_zero(&
e8b0: 65 72 72 29 3b 0a 20 20 64 62 5f 70 72 65 70 61  err);.  db_prepa
e8c0: 72 65 28 26 71 2c 0a 20 20 20 20 22 53 45 4c 45  re(&q,.    "SELE
e8d0: 43 54 20 6e 61 6d 65 2c 20 76 61 6c 75 65 20 46  CT name, value F
e8e0: 52 4f 4d 20 63 6f 6e 66 69 67 22 0a 20 20 20 20  ROM config".    
e8f0: 22 20 57 48 45 52 45 20 6e 61 6d 65 20 47 4c 4f  " WHERE name GLO
e900: 42 20 27 70 65 65 72 2d 72 65 70 6f 2d 2a 27 22  B 'peer-repo-*'"
e910: 0a 20 20 20 20 22 20 20 20 41 4e 44 20 6e 61 6d  .    "   AND nam
e920: 65 20 3c 3e 20 27 70 65 65 72 2d 72 65 70 6f 2d  e <> 'peer-repo-
e930: 25 71 27 22 0a 20 20 20 20 22 20 4f 52 44 45 52  %q'".    " ORDER
e940: 20 42 59 20 2b 76 61 6c 75 65 22 2c 0a 20 20 20   BY +value",.   
e950: 20 7a 53 65 6c 66 43 6f 64 65 0a 20 20 29 3b 0a   zSelfCode.  );.
e960: 20 20 77 68 69 6c 65 28 20 64 62 5f 73 74 65 70    while( db_step
e970: 28 26 71 29 3d 3d 53 51 4c 49 54 45 5f 52 4f 57  (&q)==SQLITE_ROW
e980: 20 29 7b 0a 20 20 20 20 63 6f 6e 73 74 20 63 68   ){.    const ch
e990: 61 72 20 2a 7a 52 65 70 6f 4e 61 6d 65 20 3d 20  ar *zRepoName = 
e9a0: 64 62 5f 63 6f 6c 75 6d 6e 5f 74 65 78 74 28 26  db_column_text(&
e9b0: 71 2c 20 31 29 3b 0a 20 20 20 20 69 66 28 20 66  q, 1);.    if( f
e9c0: 69 6c 65 5f 73 69 7a 65 28 7a 52 65 70 6f 4e 61  ile_size(zRepoNa
e9d0: 6d 65 2c 20 45 78 74 46 49 4c 45 29 3c 30 20 29  me, ExtFILE)<0 )
e9e0: 7b 0a 20 20 20 20 20 20 2f 2a 20 53 69 6c 65 6e  {.      /* Silen
e9f0: 74 6c 79 20 72 65 6d 6f 76 65 20 6e 6f 6e 2d 65  tly remove non-e
ea00: 78 69 73 74 65 6e 74 20 72 65 70 6f 73 69 74 6f  xistent reposito
ea10: 72 69 65 73 20 66 72 6f 6d 20 74 68 65 20 6c 6f  ries from the lo
ea20: 67 69 6e 20 67 72 6f 75 70 2e 20 2a 2f 0a 20 20  gin group. */.  
ea30: 20 20 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a      const char *
ea40: 7a 4c 61 62 65 6c 20 3d 20 64 62 5f 63 6f 6c 75  zLabel = db_colu
ea50: 6d 6e 5f 74 65 78 74 28 26 71 2c 20 30 29 3b 0a  mn_text(&q, 0);.
ea60: 20 20 20 20 20 20 64 62 5f 6d 75 6c 74 69 5f 65        db_multi_e
ea70: 78 65 63 28 0a 20 20 20 20 20 20 20 20 20 22 44  xec(.         "D
ea80: 45 4c 45 54 45 20 46 52 4f 4d 20 63 6f 6e 66 69  ELETE FROM confi
ea90: 67 20 57 48 45 52 45 20 6e 61 6d 65 20 47 4c 4f  g WHERE name GLO
eaa0: 42 20 27 70 65 65 72 2d 2a 2d 25 71 27 22 2c 0a  B 'peer-*-%q'",.
eab0: 20 20 20 20 20 20 20 20 20 26 7a 4c 61 62 65 6c           &zLabel
eac0: 5b 31 30 5d 0a 20 20 20 20 20 20 29 3b 0a 20 20  [10].      );.  
ead0: 20 20 20 20 63 6f 6e 74 69 6e 75 65 3b 0a 20 20      continue;.  
eae0: 20 20 7d 0a 20 20 20 20 72 63 20 3d 20 73 71 6c    }.    rc = sql
eaf0: 69 74 65 33 5f 6f 70 65 6e 5f 76 32 28 0a 20 20  ite3_open_v2(.  
eb00: 20 20 20 20 20 20 20 7a 52 65 70 6f 4e 61 6d 65         zRepoName
eb10: 2c 20 26 70 50 65 65 72 2c 0a 20 20 20 20 20 20  , &pPeer,.      
eb20: 20 20 20 53 51 4c 49 54 45 5f 4f 50 45 4e 5f 52     SQLITE_OPEN_R
eb30: 45 41 44 57 52 49 54 45 2c 0a 20 20 20 20 20 20  EADWRITE,.      
eb40: 20 20 20 67 2e 7a 56 66 73 4e 61 6d 65 0a 20 20     g.zVfsName.  
eb50: 20 20 29 3b 0a 20 20 20 20 69 66 28 20 72 63 21    );.    if( rc!
eb60: 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20  =SQLITE_OK ){.  
eb70: 20 20 20 20 62 6c 6f 62 5f 61 70 70 65 6e 64 66      blob_appendf
eb80: 28 26 65 72 72 2c 20 22 25 73 25 73 3a 20 25 73  (&err, "%s%s: %s
eb90: 25 73 22 2c 20 7a 50 72 65 66 69 78 2c 20 7a 52  %s", zPrefix, zR
eba0: 65 70 6f 4e 61 6d 65 2c 0a 20 20 20 20 20 20 20  epoName,.       
ebb0: 20 20 20 20 20 20 20 20 20 20 20 20 73 71 6c 69              sqli
ebc0: 74 65 33 5f 65 72 72 6d 73 67 28 70 50 65 65 72  te3_errmsg(pPeer
ebd0: 29 2c 20 7a 53 75 66 66 69 78 29 3b 0a 20 20 20  ), zSuffix);.   
ebe0: 20 20 20 6e 45 72 72 2b 2b 3b 0a 20 20 20 20 20     nErr++;.     
ebf0: 20 73 71 6c 69 74 65 33 5f 63 6c 6f 73 65 28 70   sqlite3_close(p
ec00: 50 65 65 72 29 3b 0a 20 20 20 20 20 20 63 6f 6e  Peer);.      con
ec10: 74 69 6e 75 65 3b 0a 20 20 20 20 7d 0a 20 20 20  tinue;.    }.   
ec20: 20 73 71 6c 69 74 65 33 5f 63 72 65 61 74 65 5f   sqlite3_create_
ec30: 66 75 6e 63 74 69 6f 6e 28 70 50 65 65 72 2c 20  function(pPeer, 
ec40: 22 73 68 61 72 65 64 5f 73 65 63 72 65 74 22 2c  "shared_secret",
ec50: 20 33 2c 20 53 51 4c 49 54 45 5f 55 54 46 38 2c   3, SQLITE_UTF8,
ec60: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
ec70: 20 20 20 20 20 20 20 20 20 20 20 20 20 30 2c 20               0, 
ec80: 73 68 61 31 5f 73 68 61 72 65 64 5f 73 65 63 72  sha1_shared_secr
ec90: 65 74 5f 73 71 6c 5f 66 75 6e 63 74 69 6f 6e 2c  et_sql_function,
eca0: 20 30 2c 20 30 29 3b 0a 20 20 20 20 73 71 6c 69   0, 0);.    sqli
ecb0: 74 65 33 5f 63 72 65 61 74 65 5f 66 75 6e 63 74  te3_create_funct
ecc0: 69 6f 6e 28 70 50 65 65 72 2c 20 22 6e 6f 77 22  ion(pPeer, "now"
ecd0: 2c 20 30 2c 53 51 4c 49 54 45 5f 55 54 46 38 2c  , 0,SQLITE_UTF8,
ece0: 30 2c 64 62 5f 6e 6f 77 5f 66 75 6e 63 74 69 6f  0,db_now_functio
ecf0: 6e 2c 30 2c 30 29 3b 0a 20 20 20 20 73 71 6c 69  n,0,0);.    sqli
ed00: 74 65 33 5f 62 75 73 79 5f 74 69 6d 65 6f 75 74  te3_busy_timeout
ed10: 28 70 50 65 65 72 2c 20 35 30 30 30 29 3b 0a 20  (pPeer, 5000);. 
ed20: 20 20 20 7a 45 72 72 20 3d 20 30 3b 0a 20 20 20     zErr = 0;.   
ed30: 20 72 63 20 3d 20 73 71 6c 69 74 65 33 5f 65 78   rc = sqlite3_ex
ed40: 65 63 28 70 50 65 65 72 2c 20 7a 53 71 6c 2c 20  ec(pPeer, zSql, 
ed50: 30 2c 20 30 2c 20 26 7a 45 72 72 29 3b 0a 20 20  0, 0, &zErr);.  
ed60: 20 20 69 66 28 20 7a 45 72 72 20 29 7b 0a 20 20    if( zErr ){.  
ed70: 20 20 20 20 62 6c 6f 62 5f 61 70 70 65 6e 64 66      blob_appendf
ed80: 28 26 65 72 72 2c 20 22 25 73 25 73 3a 20 25 73  (&err, "%s%s: %s
ed90: 25 73 22 2c 20 7a 50 72 65 66 69 78 2c 20 7a 52  %s", zPrefix, zR
eda0: 65 70 6f 4e 61 6d 65 2c 20 7a 45 72 72 2c 20 7a  epoName, zErr, z
edb0: 53 75 66 66 69 78 29 3b 0a 20 20 20 20 20 20 73  Suffix);.      s
edc0: 71 6c 69 74 65 33 5f 66 72 65 65 28 7a 45 72 72  qlite3_free(zErr
edd0: 29 3b 0a 20 20 20 20 20 20 6e 45 72 72 2b 2b 3b  );.      nErr++;
ede0: 0a 20 20 20 20 7d 65 6c 73 65 20 69 66 28 20 72  .    }else if( r
edf0: 63 21 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b 0a  c!=SQLITE_OK ){.
ee00: 20 20 20 20 20 20 62 6c 6f 62 5f 61 70 70 65 6e        blob_appen
ee10: 64 66 28 26 65 72 72 2c 20 22 25 73 25 73 3a 20  df(&err, "%s%s: 
ee20: 25 73 25 73 22 2c 20 7a 50 72 65 66 69 78 2c 20  %s%s", zPrefix, 
ee30: 7a 52 65 70 6f 4e 61 6d 65 2c 0a 20 20 20 20 20  zRepoName,.     
ee40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73 71                sq
ee50: 6c 69 74 65 33 5f 65 72 72 6d 73 67 28 70 50 65  lite3_errmsg(pPe
ee60: 65 72 29 2c 20 7a 53 75 66 66 69 78 29 3b 0a 20  er), zSuffix);. 
ee70: 20 20 20 20 20 6e 45 72 72 2b 2b 3b 0a 20 20 20       nErr++;.   
ee80: 20 7d 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 63   }.    sqlite3_c
ee90: 6c 6f 73 65 28 70 50 65 65 72 29 3b 0a 20 20 7d  lose(pPeer);.  }
eea0: 0a 20 20 64 62 5f 66 69 6e 61 6c 69 7a 65 28 26  .  db_finalize(&
eeb0: 71 29 3b 0a 20 20 69 66 28 20 70 7a 45 72 72 6f  q);.  if( pzErro
eec0: 72 4d 73 67 20 26 26 20 62 6c 6f 62 5f 73 69 7a  rMsg && blob_siz
eed0: 65 28 26 65 72 72 29 3e 30 20 29 7b 0a 20 20 20  e(&err)>0 ){.   
eee0: 20 2a 70 7a 45 72 72 6f 72 4d 73 67 20 3d 20 66   *pzErrorMsg = f
eef0: 6f 73 73 69 6c 5f 73 74 72 64 75 70 28 62 6c 6f  ossil_strdup(blo
ef00: 62 5f 73 74 72 28 26 65 72 72 29 29 3b 0a 20 20  b_str(&err));.  
ef10: 7d 0a 20 20 62 6c 6f 62 5f 72 65 73 65 74 28 26  }.  blob_reset(&
ef20: 65 72 72 29 3b 0a 20 20 66 6f 73 73 69 6c 5f 66  err);.  fossil_f
ef30: 72 65 65 28 7a 53 65 6c 66 43 6f 64 65 29 3b 0a  ree(zSelfCode);.
ef40: 20 20 72 65 74 75 72 6e 20 6e 45 72 72 3b 0a 7d    return nErr;.}
ef50: 0a 0a 2f 2a 0a 2a 2a 20 41 74 74 65 6d 70 74 20  ../*.** Attempt 
ef60: 74 6f 20 6a 6f 69 6e 20 61 20 6c 6f 67 69 6e 2d  to join a login-
ef70: 67 72 6f 75 70 2e 0a 2a 2a 0a 2a 2a 20 49 66 20  group..**.** If 
ef80: 70 72 6f 62 6c 65 6d 73 20 61 72 69 73 65 2c 20  problems arise, 
ef90: 6c 65 61 76 65 20 61 6e 20 65 72 72 6f 72 20 6d  leave an error m
efa0: 65 73 73 61 67 65 20 69 6e 20 2a 70 7a 45 72 72  essage in *pzErr
efb0: 4d 73 67 2e 0a 2a 2f 0a 76 6f 69 64 20 6c 6f 67  Msg..*/.void log
efc0: 69 6e 5f 67 72 6f 75 70 5f 6a 6f 69 6e 28 0a 20  in_group_join(. 
efd0: 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 52 65   const char *zRe
efe0: 70 6f 2c 20 20 20 20 20 20 20 20 20 2f 2a 20 52  po,         /* R
eff0: 65 70 6f 73 69 74 6f 72 79 20 66 69 6c 65 20 69  epository file i
f000: 6e 20 74 68 65 20 6c 6f 67 69 6e 20 67 72 6f 75  n the login grou
f010: 70 20 2a 2f 0a 20 20 69 6e 74 20 62 50 77 52 65  p */.  int bPwRe
f020: 71 75 69 72 65 64 2c 20 20 20 20 20 20 20 20 20  quired,         
f030: 20 20 2f 2a 20 54 72 75 65 20 69 66 20 74 68 65    /* True if the
f040: 20 6c 6f 67 69 6e 2c 70 61 73 73 77 6f 72 64 20   login,password 
f050: 69 73 20 72 65 71 75 69 72 65 64 20 2a 2f 0a 20  is required */. 
f060: 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 4c 6f   const char *zLo
f070: 67 69 6e 2c 20 20 20 20 20 20 20 20 2f 2a 20 4c  gin,        /* L
f080: 6f 67 69 6e 20 6e 61 6d 65 20 66 6f 72 20 74 68  ogin name for th
f090: 65 20 6f 74 68 65 72 20 72 65 70 6f 20 2a 2f 0a  e other repo */.
f0a0: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 50    const char *zP
f0b0: 61 73 73 77 6f 72 64 2c 20 20 20 20 20 2f 2a 20  assword,     /* 
f0c0: 50 61 73 73 77 6f 72 64 20 74 6f 20 70 72 6f 76  Password to prov
f0d0: 65 20 77 65 20 61 72 65 20 61 75 74 68 6f 72 69  e we are authori
f0e0: 7a 65 64 20 74 6f 20 6a 6f 69 6e 20 2a 2f 0a 20  zed to join */. 
f0f0: 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 4e 65   const char *zNe
f100: 77 4e 61 6d 65 2c 20 20 20 20 20 20 2f 2a 20 4e  wName,      /* N
f110: 61 6d 65 20 6f 66 20 6e 65 77 20 6c 6f 67 69 6e  ame of new login
f120: 20 67 72 6f 75 70 20 69 66 20 6d 61 6b 69 6e 67   group if making
f130: 20 61 20 6e 65 77 20 6f 6e 65 20 2a 2f 0a 20 20   a new one */.  
f140: 63 68 61 72 20 2a 2a 70 7a 45 72 72 4d 73 67 20  char **pzErrMsg 
f150: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4c 65             /* Le
f160: 61 76 65 20 61 6e 20 65 72 72 6f 72 20 6d 65 73  ave an error mes
f170: 73 61 67 65 20 68 65 72 65 20 2a 2f 0a 29 7b 0a  sage here */.){.
f180: 20 20 42 6c 6f 62 20 66 75 6c 6c 4e 61 6d 65 3b    Blob fullName;
f190: 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20               /* 
f1a0: 42 6c 6f 62 20 66 6f 72 20 66 69 6e 64 69 6e 67  Blob for finding
f1b0: 20 66 75 6c 6c 20 70 61 74 68 6e 61 6d 65 73 20   full pathnames 
f1c0: 2a 2f 0a 20 20 73 71 6c 69 74 65 33 20 2a 70 4f  */.  sqlite3 *pO
f1d0: 74 68 65 72 3b 20 20 20 20 20 20 20 20 20 20 20  ther;           
f1e0: 2f 2a 20 54 68 65 20 6f 74 68 65 72 20 72 65 70  /* The other rep
f1f0: 6f 73 69 74 6f 72 79 20 2a 2f 0a 20 20 69 6e 74  ository */.  int
f200: 20 72 63 3b 20 20 20 20 20 20 20 20 20 20 20 20   rc;            
f210: 20 20 20 20 20 20 20 20 2f 2a 20 52 65 74 75 72          /* Retur
f220: 6e 20 63 6f 64 65 20 66 72 6f 6d 20 73 71 6c 69  n code from sqli
f230: 74 65 33 20 66 75 6e 63 74 69 6f 6e 73 20 2a 2f  te3 functions */
f240: 0a 20 20 63 68 61 72 20 2a 7a 4f 74 68 65 72 50  .  char *zOtherP
f250: 72 6f 6a 43 6f 64 65 3b 20 20 20 20 20 20 2f 2a  rojCode;      /*
f260: 20 50 72 6f 6a 65 63 74 20 63 6f 64 65 20 66 6f   Project code fo
f270: 72 20 70 4f 74 68 65 72 20 2a 2f 0a 20 20 63 68  r pOther */.  ch
f280: 61 72 20 2a 7a 53 65 6c 66 52 65 70 6f 3b 20 20  ar *zSelfRepo;  
f290: 20 20 20 20 20 20 20 20 20 2f 2a 20 4e 61 6d 65           /* Name
f2a0: 20 6f 66 20 6f 75 72 20 72 65 70 6f 73 69 74 6f   of our reposito
f2b0: 72 79 20 2a 2f 0a 20 20 63 68 61 72 20 2a 7a 53  ry */.  char *zS
f2c0: 65 6c 66 4c 61 62 65 6c 3b 20 20 20 20 20 20 20  elfLabel;       
f2d0: 20 20 20 2f 2a 20 50 72 6f 6a 65 63 74 2d 6e 61     /* Project-na
f2e0: 6d 65 20 66 6f 72 20 6f 75 72 20 72 65 70 6f 73  me for our repos
f2f0: 69 74 6f 72 79 20 2a 2f 0a 20 20 63 68 61 72 20  itory */.  char 
f300: 2a 7a 53 65 6c 66 50 72 6f 6a 43 6f 64 65 3b 20  *zSelfProjCode; 
f310: 20 20 20 20 20 20 2f 2a 20 4f 75 72 20 70 72 6f        /* Our pro
f320: 6a 65 63 74 2d 63 6f 64 65 20 2a 2f 0a 20 20 63  ject-code */.  c
f330: 68 61 72 20 2a 7a 53 71 6c 3b 20 20 20 20 20 20  har *zSql;      
f340: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 53 51 4c            /* SQL
f350: 20 74 6f 20 72 75 6e 20 6f 6e 20 61 6c 6c 20 70   to run on all p
f360: 65 65 72 73 20 2a 2f 0a 20 20 63 6f 6e 73 74 20  eers */.  const 
f370: 63 68 61 72 20 2a 7a 53 65 6c 66 3b 20 20 20 20  char *zSelf;    
f380: 20 20 20 20 20 2f 2a 20 54 68 65 20 41 54 54 41       /* The ATTA
f390: 43 48 20 6e 61 6d 65 20 6f 66 20 6f 75 72 20 72  CH name of our r
f3a0: 65 70 6f 73 69 74 6f 72 79 20 2a 2f 0a 0a 20 20  epository */..  
f3b0: 2a 70 7a 45 72 72 4d 73 67 20 3d 20 30 3b 20 20  *pzErrMsg = 0;  
f3c0: 20 2f 2a 20 44 65 66 61 75 6c 74 20 74 6f 20 6e   /* Default to n
f3d0: 6f 20 65 72 72 6f 72 73 20 2a 2f 0a 20 20 7a 53  o errors */.  zS
f3e0: 65 6c 66 20 3d 20 22 72 65 70 6f 73 69 74 6f 72  elf = "repositor
f3f0: 79 22 3b 0a 0a 20 20 2f 2a 20 47 65 74 20 74 68  y";..  /* Get th
f400: 65 20 66 75 6c 6c 20 70 61 74 68 6e 61 6d 65 20  e full pathname 
f410: 6f 66 20 74 68 65 20 6f 74 68 65 72 20 72 65 70  of the other rep
f420: 6f 73 69 74 6f 72 79 20 2a 2f 0a 20 20 66 69 6c  ository */.  fil
f430: 65 5f 63 61 6e 6f 6e 69 63 61 6c 5f 6e 61 6d 65  e_canonical_name
f440: 28 7a 52 65 70 6f 2c 20 26 66 75 6c 6c 4e 61 6d  (zRepo, &fullNam
f450: 65 2c 20 30 29 3b 0a 20 20 7a 52 65 70 6f 20 3d  e, 0);.  zRepo =
f460: 20 66 6f 73 73 69 6c 5f 73 74 72 64 75 70 28 62   fossil_strdup(b
f470: 6c 6f 62 5f 73 74 72 28 26 66 75 6c 6c 4e 61 6d  lob_str(&fullNam
f480: 65 29 29 3b 0a 20 20 62 6c 6f 62 5f 72 65 73 65  e));.  blob_rese
f490: 74 28 26 66 75 6c 6c 4e 61 6d 65 29 3b 0a 0a 20  t(&fullName);.. 
f4a0: 20 2f 2a 20 47 65 74 20 74 68 65 20 66 75 6c 6c   /* Get the full
f4b0: 20 70 61 74 68 6e 61 6d 65 20 66 6f 72 20 6f 75   pathname for ou
f4c0: 72 20 72 65 70 6f 73 69 74 6f 72 79 2e 20 20 41  r repository.  A
f4d0: 6c 73 6f 20 74 68 65 20 70 72 6f 6a 65 63 74 20  lso the project 
f4e0: 63 6f 64 65 0a 20 20 2a 2a 20 61 6e 64 20 70 72  code.  ** and pr
f4f0: 6f 6a 65 63 74 20 6e 61 6d 65 20 66 6f 72 20 6f  oject name for o
f500: 75 72 73 65 6c 66 2e 20 2a 2f 0a 20 20 66 69 6c  urself. */.  fil
f510: 65 5f 63 61 6e 6f 6e 69 63 61 6c 5f 6e 61 6d 65  e_canonical_name
f520: 28 67 2e 7a 52 65 70 6f 73 69 74 6f 72 79 4e 61  (g.zRepositoryNa
f530: 6d 65 2c 20 26 66 75 6c 6c 4e 61 6d 65 2c 20 30  me, &fullName, 0
f540: 29 3b 0a 20 20 7a 53 65 6c 66 52 65 70 6f 20 3d  );.  zSelfRepo =
f550: 20 66 6f 73 73 69 6c 5f 73 74 72 64 75 70 28 62   fossil_strdup(b
f560: 6c 6f 62 5f 73 74 72 28 26 66 75 6c 6c 4e 61 6d  lob_str(&fullNam
f570: 65 29 29 3b 0a 20 20 62 6c 6f 62 5f 72 65 73 65  e));.  blob_rese
f580: 74 28 26 66 75 6c 6c 4e 61 6d 65 29 3b 0a 20 20  t(&fullName);.  
f590: 7a 53 65 6c 66 50 72 6f 6a 43 6f 64 65 20 3d 20  zSelfProjCode = 
f5a0: 64 62 5f 67 65 74 28 22 70 72 6f 6a 65 63 74 2d  db_get("project-
f5b0: 63 6f 64 65 22 2c 20 22 75 6e 6b 6e 6f 77 6e 22  code", "unknown"
f5c0: 29 3b 0a 20 20 7a 53 65 6c 66 4c 61 62 65 6c 20  );.  zSelfLabel 
f5d0: 3d 20 64 62 5f 67 65 74 28 22 70 72 6f 6a 65 63  = db_get("projec
f5e0: 74 2d 6e 61 6d 65 22 2c 20 30 29 3b 0a 20 20 69  t-name", 0);.  i
f5f0: 66 28 20 7a 53 65 6c 66 4c 61 62 65 6c 3d 3d 30  f( zSelfLabel==0
f600: 20 29 7b 0a 20 20 20 20 7a 53 65 6c 66 4c 61 62   ){.    zSelfLab
f610: 65 6c 20 3d 20 7a 53 65 6c 66 50 72 6f 6a 43 6f  el = zSelfProjCo
f620: 64 65 3b 0a 20 20 7d 0a 0a 20 20 2f 2a 20 4d 61  de;.  }..  /* Ma
f630: 6b 65 20 73 75 72 65 20 77 65 20 61 72 65 20 6e  ke sure we are n
f640: 6f 74 20 74 72 79 69 6e 67 20 74 6f 20 6a 6f 69  ot trying to joi
f650: 6e 20 6f 75 72 73 65 6c 76 65 73 20 2a 2f 0a 20  n ourselves */. 
f660: 20 69 66 28 20 66 6f 73 73 69 6c 5f 73 74 72 63   if( fossil_strc
f670: 6d 70 28 7a 52 65 70 6f 2c 20 7a 53 65 6c 66 52  mp(zRepo, zSelfR
f680: 65 70 6f 29 3d 3d 30 20 29 7b 0a 20 20 20 20 2a  epo)==0 ){.    *
f690: 70 7a 45 72 72 4d 73 67 20 3d 20 6d 70 72 69 6e  pzErrMsg = mprin
f6a0: 74 66 28 22 54 68 65 20 5c 22 6f 74 68 65 72 5c  tf("The \"other\
f6b0: 22 20 72 65 70 6f 73 69 74 6f 72 79 20 69 73 20  " repository is 
f6c0: 74 68 65 20 73 61 6d 65 20 61 73 20 74 68 69 73  the same as this
f6d0: 20 6f 6e 65 2e 22 29 3b 0a 20 20 20 20 72 65 74   one.");.    ret
f6e0: 75 72 6e 3b 0a 20 20 7d 0a 0a 20 20 2f 2a 20 4d  urn;.  }..  /* M
f6f0: 61 6b 65 20 73 75 72 65 20 74 68 65 20 6f 74 68  ake sure the oth
f700: 65 72 20 72 65 70 6f 73 69 74 6f 72 79 20 69 73  er repository is
f710: 20 61 20 76 61 6c 69 64 20 46 6f 73 73 69 6c 20   a valid Fossil 
f720: 64 61 74 61 62 61 73 65 20 2a 2f 0a 20 20 69 66  database */.  if
f730: 28 20 66 69 6c 65 5f 73 69 7a 65 28 7a 52 65 70  ( file_size(zRep
f740: 6f 2c 20 45 78 74 46 49 4c 45 29 3c 30 20 29 7b  o, ExtFILE)<0 ){
f750: 0a 20 20 20 20 2a 70 7a 45 72 72 4d 73 67 20 3d  .    *pzErrMsg =
f760: 20 6d 70 72 69 6e 74 66 28 22 72 65 70 6f 73 69   mprintf("reposi
f770: 74 6f 72 79 20 66 69 6c 65 20 5c 22 25 73 5c 22  tory file \"%s\"
f780: 20 64 6f 65 73 20 6e 6f 74 20 65 78 69 73 74 22   does not exist"
f790: 2c 20 7a 52 65 70 6f 29 3b 0a 20 20 20 20 72 65  , zRepo);.    re
f7a0: 74 75 72 6e 3b 0a 20 20 7d 0a 20 20 72 63 20 3d  turn;.  }.  rc =
f7b0: 20 73 71 6c 69 74 65 33 5f 6f 70 65 6e 5f 76 32   sqlite3_open_v2
f7c0: 28 0a 20 20 20 20 20 20 20 7a 52 65 70 6f 2c 20  (.       zRepo, 
f7d0: 26 70 4f 74 68 65 72 2c 0a 20 20 20 20 20 20 20  &pOther,.       
f7e0: 53 51 4c 49 54 45 5f 4f 50 45 4e 5f 52 45 41 44  SQLITE_OPEN_READ
f7f0: 57 52 49 54 45 20 7c 20 53 51 4c 49 54 45 5f 4f  WRITE | SQLITE_O
f800: 50 45 4e 5f 43 52 45 41 54 45 2c 0a 20 20 20 20  PEN_CREATE,.    
f810: 20 20 20 67 2e 7a 56 66 73 4e 61 6d 65 0a 20 20     g.zVfsName.  
f820: 29 3b 0a 20 20 69 66 28 20 72 63 21 3d 53 51 4c  );.  if( rc!=SQL
f830: 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 2a 70  ITE_OK ){.    *p
f840: 7a 45 72 72 4d 73 67 20 3d 20 66 6f 73 73 69 6c  zErrMsg = fossil
f850: 5f 73 74 72 64 75 70 28 73 71 6c 69 74 65 33 5f  _strdup(sqlite3_
f860: 65 72 72 6d 73 67 28 70 4f 74 68 65 72 29 29 3b  errmsg(pOther));
f870: 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 72 63  .  }else{.    rc
f880: 20 3d 20 73 71 6c 69 74 65 33 5f 65 78 65 63 28   = sqlite3_exec(
f890: 70 4f 74 68 65 72 2c 20 22 53 45 4c 45 43 54 20  pOther, "SELECT 
f8a0: 63 6f 75 6e 74 28 2a 29 20 46 52 4f 4d 20 75 73  count(*) FROM us
f8b0: 65 72 22 2c 20 30 2c 20 30 2c 20 70 7a 45 72 72  er", 0, 0, pzErr
f8c0: 4d 73 67 29 3b 0a 20 20 7d 0a 20 20 73 71 6c 69  Msg);.  }.  sqli
f8d0: 74 65 33 5f 63 6c 6f 73 65 28 70 4f 74 68 65 72  te3_close(pOther
f8e0: 29 3b 0a 20 20 69 66 28 20 72 63 20 29 20 72 65  );.  if( rc ) re
f8f0: 74 75 72 6e 3b 0a 0a 20 20 2f 2a 20 41 74 74 61  turn;..  /* Atta
f900: 63 68 20 74 68 65 20 6f 74 68 65 72 20 72 65 70  ch the other rep
f910: 6f 73 69 74 6f 72 79 2e 20 20 4d 61 6b 65 20 73  ository.  Make s
f920: 75 72 65 20 74 68 65 20 75 73 65 72 6e 61 6d 65  ure the username
f930: 2f 70 61 73 73 77 6f 72 64 20 69 73 0a 20 20 2a  /password is.  *
f940: 2a 20 76 61 6c 69 64 20 61 6e 64 20 68 61 73 20  * valid and has 
f950: 53 65 74 75 70 20 70 65 72 6d 69 73 73 69 6f 6e  Setup permission
f960: 2e 0a 20 20 2a 2f 0a 20 20 64 62 5f 61 74 74 61  ..  */.  db_atta
f970: 63 68 28 7a 52 65 70 6f 2c 20 22 6f 74 68 65 72  ch(zRepo, "other
f980: 22 29 3b 0a 20 20 7a 4f 74 68 65 72 50 72 6f 6a  ");.  zOtherProj
f990: 43 6f 64 65 20 3d 20 64 62 5f 74 65 78 74 28 22  Code = db_text("
f9a0: 78 22 2c 20 22 53 45 4c 45 43 54 20 76 61 6c 75  x", "SELECT valu
f9b0: 65 20 46 52 4f 4d 20 6f 74 68 65 72 2e 63 6f 6e  e FROM other.con
f9c0: 66 69 67 22 0a 20 20 20 20 20 20 20 20 20 20 20  fig".           
f9d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
f9e0: 20 20 20 20 20 22 20 57 48 45 52 45 20 6e 61 6d       " WHERE nam
f9f0: 65 3d 27 70 72 6f 6a 65 63 74 2d 63 6f 64 65 27  e='project-code'
fa00: 22 29 3b 0a 20 20 69 66 28 20 62 50 77 52 65 71  ");.  if( bPwReq
fa10: 75 69 72 65 64 20 29 7b 0a 20 20 20 20 63 68 61  uired ){.    cha
fa20: 72 20 2a 7a 50 77 48 61 73 68 3b 20 20 20 20 20  r *zPwHash;     
fa30: 20 20 20 20 20 20 20 20 2f 2a 20 50 61 73 73 77          /* Passw
fa40: 6f 72 64 20 68 61 73 68 20 6f 6e 20 70 4f 74 68  ord hash on pOth
fa50: 65 72 20 2a 2f 0a 20 20 20 20 7a 50 77 48 61 73  er */.    zPwHas
fa60: 68 20 3d 20 73 68 61 31 5f 73 68 61 72 65 64 5f  h = sha1_shared_
fa70: 73 65 63 72 65 74 28 7a 50 61 73 73 77 6f 72 64  secret(zPassword
fa80: 2c 20 7a 4c 6f 67 69 6e 2c 20 7a 4f 74 68 65 72  , zLogin, zOther
fa90: 50 72 6f 6a 43 6f 64 65 29 3b 0a 20 20 20 20 69  ProjCode);.    i
faa0: 66 28 20 21 64 62 5f 65 78 69 73 74 73 28 0a 20  f( !db_exists(. 
fab0: 20 20 20 20 20 22 53 45 4c 45 43 54 20 31 20 46       "SELECT 1 F
fac0: 52 4f 4d 20 6f 74 68 65 72 2e 75 73 65 72 22 0a  ROM other.user".
fad0: 20 20 20 20 20 20 22 20 57 48 45 52 45 20 6c 6f        " WHERE lo
fae0: 67 69 6e 3d 25 51 20 41 4e 44 20 63 61 70 20 47  gin=%Q AND cap G
faf0: 4c 4f 42 20 27 2a 73 2a 27 22 0a 20 20 20 20 20  LOB '*s*'".     
fb00: 20 22 20 20 20 41 4e 44 20 28 70 77 3d 25 51 20   "   AND (pw=%Q 
fb10: 4f 52 20 70 77 3d 25 51 29 22 2c 0a 20 20 20 20  OR pw=%Q)",.    
fb20: 20 20 7a 4c 6f 67 69 6e 2c 20 7a 50 61 73 73 77    zLogin, zPassw
fb30: 6f 72 64 2c 20 7a 50 77 48 61 73 68 29 0a 20 20  ord, zPwHash).  
fb40: 20 20 29 7b 0a 20 20 20 20 20 20 64 62 5f 64 65    ){.      db_de
fb50: 74 61 63 68 28 22 6f 74 68 65 72 22 29 3b 0a 20  tach("other");. 
fb60: 20 20 20 20 20 2a 70 7a 45 72 72 4d 73 67 20 3d       *pzErrMsg =
fb70: 20 22 54 68 65 20 73 75 70 70 6c 69 65 64 20 75   "The supplied u
fb80: 73 65 72 6e 61 6d 65 2f 70 61 73 73 77 6f 72 64  sername/password
fb90: 20 64 6f 65 73 20 6e 6f 74 20 63 6f 72 72 65 73   does not corres
fba0: 70 6f 6e 64 20 74 6f 20 61 22 0a 20 20 20 20 20  pond to a".     
fbb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 22 20 75               " u
fbc0: 73 65 72 20 53 65 74 75 70 20 70 65 72 6d 69 73  ser Setup permis
fbd0: 73 69 6f 6e 20 6f 6e 20 74 68 65 20 6f 74 68 65  sion on the othe
fbe0: 72 20 72 65 70 6f 73 69 74 6f 72 79 2e 22 3b 0a  r repository.";.
fbf0: 20 20 20 20 20 20 72 65 74 75 72 6e 3b 0a 20 20        return;.  
fc00: 20 20 7d 0a 20 20 7d 0a 0a 20 20 2f 2a 20 43 72    }.  }..  /* Cr
fc10: 65 61 74 65 20 61 6c 6c 20 74 68 65 20 6e 65 63  eate all the nec
fc20: 65 73 73 61 72 79 20 43 4f 4e 46 49 47 20 74 61  essary CONFIG ta
fc30: 62 6c 65 20 65 6e 74 72 69 65 73 20 6f 6e 20 62  ble entries on b
fc40: 6f 74 68 20 74 68 65 0a 20 20 2a 2a 20 6f 74 68  oth the.  ** oth
fc50: 65 72 20 72 65 70 6f 73 69 74 6f 72 79 20 61 6e  er repository an
fc60: 64 20 6f 6e 20 6f 75 72 20 6f 77 6e 20 72 65 70  d on our own rep
fc70: 6f 73 69 74 6f 72 79 2e 0a 20 20 2a 2f 0a 20 20  ository..  */.  
fc80: 7a 53 65 6c 66 50 72 6f 6a 43 6f 64 65 20 3d 20  zSelfProjCode = 
fc90: 61 62 62 72 65 76 69 61 74 65 64 5f 70 72 6f 6a  abbreviated_proj
fca0: 65 63 74 5f 63 6f 64 65 28 7a 53 65 6c 66 50 72  ect_code(zSelfPr
fcb0: 6f 6a 43 6f 64 65 29 3b 0a 20 20 7a 4f 74 68 65  ojCode);.  zOthe
fcc0: 72 50 72 6f 6a 43 6f 64 65 20 3d 20 61 62 62 72  rProjCode = abbr
fcd0: 65 76 69 61 74 65 64 5f 70 72 6f 6a 65 63 74 5f  eviated_project_
fce0: 63 6f 64 65 28 7a 4f 74 68 65 72 50 72 6f 6a 43  code(zOtherProjC
fcf0: 6f 64 65 29 3b 0a 20 20 64 62 5f 62 65 67 69 6e  ode);.  db_begin
fd00: 5f 74 72 61 6e 73 61 63 74 69 6f 6e 28 29 3b 0a  _transaction();.
fd10: 20 20 64 62 5f 6d 75 6c 74 69 5f 65 78 65 63 28    db_multi_exec(
fd20: 0a 20 20 20 20 22 44 45 4c 45 54 45 20 46 52 4f  .    "DELETE FRO
fd30: 4d 20 5c 22 25 77 5c 22 2e 63 6f 6e 66 69 67 20  M \"%w\".config 
fd40: 57 48 45 52 45 20 6e 61 6d 65 20 47 4c 4f 42 20  WHERE name GLOB 
fd50: 27 70 65 65 72 2d 2a 27 3b 22 0a 20 20 20 20 22  'peer-*';".    "
fd60: 49 4e 53 45 52 54 20 49 4e 54 4f 20 5c 22 25 77  INSERT INTO \"%w
fd70: 5c 22 2e 63 6f 6e 66 69 67 28 6e 61 6d 65 2c 76  \".config(name,v
fd80: 61 6c 75 65 29 20 56 41 4c 55 45 53 28 27 70 65  alue) VALUES('pe
fd90: 65 72 2d 72 65 70 6f 2d 25 71 27 2c 25 51 29 3b  er-repo-%q',%Q);
fda0: 22 0a 20 20 20 20 22 49 4e 53 45 52 54 20 49 4e  ".    "INSERT IN
fdb0: 54 4f 20 5c 22 25 77 5c 22 2e 63 6f 6e 66 69 67  TO \"%w\".config
fdc0: 28 6e 61 6d 65 2c 76 61 6c 75 65 29 20 22 0a 20  (name,value) ". 
fdd0: 20 20 20 22 20 20 53 45 4c 45 43 54 20 27 70 65     "  SELECT 'pe
fde0: 65 72 2d 6e 61 6d 65 2d 25 71 27 2c 20 76 61 6c  er-name-%q', val
fdf0: 75 65 20 46 52 4f 4d 20 6f 74 68 65 72 2e 63 6f  ue FROM other.co
fe00: 6e 66 69 67 22 0a 20 20 20 20 22 20 20 20 57 48  nfig".    "   WH
fe10: 45 52 45 20 6e 61 6d 65 3d 27 70 72 6f 6a 65 63  ERE name='projec
fe20: 74 2d 6e 61 6d 65 27 3b 22 2c 0a 20 20 20 20 7a  t-name';",.    z
fe30: 53 65 6c 66 2c 0a 20 20 20 20 7a 53 65 6c 66 2c  Self,.    zSelf,
fe40: 20 7a 4f 74 68 65 72 50 72 6f 6a 43 6f 64 65 2c   zOtherProjCode,
fe50: 20 7a 52 65 70 6f 2c 0a 20 20 20 20 7a 53 65 6c   zRepo,.    zSel
fe60: 66 2c 20 7a 4f 74 68 65 72 50 72 6f 6a 43 6f 64  f, zOtherProjCod
fe70: 65 0a 20 20 29 3b 0a 20 20 64 62 5f 6d 75 6c 74  e.  );.  db_mult
fe80: 69 5f 65 78 65 63 28 0a 20 20 20 20 22 49 4e 53  i_exec(.    "INS
fe90: 45 52 54 20 4f 52 20 49 47 4e 4f 52 45 20 49 4e  ERT OR IGNORE IN
fea0: 54 4f 20 6f 74 68 65 72 2e 63 6f 6e 66 69 67 28  TO other.config(
feb0: 6e 61 6d 65 2c 76 61 6c 75 65 29 22 0a 20 20 20  name,value)".   
fec0: 20 22 20 56 41 4c 55 45 53 28 27 6c 6f 67 69 6e   " VALUES('login
fed0: 2d 67 72 6f 75 70 2d 6e 61 6d 65 27 2c 25 51 29  -group-name',%Q)
fee0: 3b 22 0a 20 20 20 20 22 49 4e 53 45 52 54 20 4f  ;".    "INSERT O
fef0: 52 20 49 47 4e 4f 52 45 20 49 4e 54 4f 20 6f 74  R IGNORE INTO ot
ff00: 68 65 72 2e 63 6f 6e 66 69 67 28 6e 61 6d 65 2c  her.config(name,
ff10: 76 61 6c 75 65 29 22 0a 20 20 20 20 22 20 56 41  value)".    " VA
ff20: 4c 55 45 53 28 27 6c 6f 67 69 6e 2d 67 72 6f 75  LUES('login-grou
ff30: 70 2d 63 6f 64 65 27 2c 6c 6f 77 65 72 28 68 65  p-code',lower(he
ff40: 78 28 72 61 6e 64 6f 6d 62 6c 6f 62 28 38 29 29  x(randomblob(8))
ff50: 29 29 3b 22 2c 0a 20 20 20 20 7a 4e 65 77 4e 61  ));",.    zNewNa
ff60: 6d 65 0a 20 20 29 3b 0a 20 20 64 62 5f 6d 75 6c  me.  );.  db_mul
ff70: 74 69 5f 65 78 65 63 28 0a 20 20 20 20 22 52 45  ti_exec(.    "RE
ff80: 50 4c 41 43 45 20 49 4e 54 4f 20 5c 22 25 77 5c  PLACE INTO \"%w\
ff90: 22 2e 63 6f 6e 66 69 67 28 6e 61 6d 65 2c 76 61  ".config(name,va
ffa0: 6c 75 65 29 22 0a 20 20 20 20 22 20 20 53 45 4c  lue)".    "  SEL
ffb0: 45 43 54 20 6e 61 6d 65 2c 20 76 61 6c 75 65 20  ECT name, value 
ffc0: 46 52 4f 4d 20 6f 74 68 65 72 2e 63 6f 6e 66 69  FROM other.confi
ffd0: 67 22 0a 20 20 20 20 22 20 20 20 57 48 45 52 45  g".    "   WHERE
ffe0: 20 6e 61 6d 65 20 47 4c 4f 42 20 27 70 65 65 72   name GLOB 'peer
fff0: 2d 2a 27 20 4f 52 20 6e 61 6d 65 20 47 4c 4f 42  -*' OR name GLOB
10000 20 27 6c 6f 67 69 6e 2d 67 72 6f 75 70 2d 2a 27   'login-group-*'
10010 22 2c 0a 20 20 20 20 7a 53 65 6c 66 0a 20 20 29  ",.    zSelf.  )
10020 3b 0a 20 20 64 62 5f 65 6e 64 5f 74 72 61 6e 73  ;.  db_end_trans
10030 61 63 74 69 6f 6e 28 30 29 3b 0a 20 20 64 62 5f  action(0);.  db_
10040 6d 75 6c 74 69 5f 65 78 65 63 28 22 44 45 54 41  multi_exec("DETA
10050 43 48 20 6f 74 68 65 72 22 29 3b 0a 0a 20 20 2f  CH other");..  /
10060 2a 20 50 72 6f 70 61 67 61 74 65 20 74 68 65 20  * Propagate the 
10070 63 68 61 6e 67 65 73 20 74 6f 20 61 6c 6c 20 6f  changes to all o
10080 74 68 65 72 20 6d 65 6d 62 65 72 73 20 6f 66 20  ther members of 
10090 74 68 65 20 6c 6f 67 69 6e 2d 67 72 6f 75 70 20  the login-group 
100a0 2a 2f 0a 20 20 7a 53 71 6c 20 3d 20 6d 70 72 69  */.  zSql = mpri
100b0 6e 74 66 28 0a 20 20 20 20 22 42 45 47 49 4e 3b  ntf(.    "BEGIN;
100c0 22 0a 20 20 20 20 22 52 45 50 4c 41 43 45 20 49  ".    "REPLACE I
100d0 4e 54 4f 20 63 6f 6e 66 69 67 28 6e 61 6d 65 2c  NTO config(name,
100e0 76 61 6c 75 65 2c 6d 74 69 6d 65 29 20 56 41 4c  value,mtime) VAL
100f0 55 45 53 28 27 70 65 65 72 2d 6e 61 6d 65 2d 25  UES('peer-name-%
10100 71 27 2c 25 51 2c 6e 6f 77 28 29 29 3b 22 0a 20  q',%Q,now());". 
10110 20 20 20 22 52 45 50 4c 41 43 45 20 49 4e 54 4f     "REPLACE INTO
10120 20 63 6f 6e 66 69 67 28 6e 61 6d 65 2c 76 61 6c   config(name,val
10130 75 65 2c 6d 74 69 6d 65 29 20 56 41 4c 55 45 53  ue,mtime) VALUES
10140 28 27 70 65 65 72 2d 72 65 70 6f 2d 25 71 27 2c  ('peer-repo-%q',
10150 25 51 2c 6e 6f 77 28 29 29 3b 22 0a 20 20 20 20  %Q,now());".    
10160 22 43 4f 4d 4d 49 54 3b 22 2c 0a 20 20 20 20 7a  "COMMIT;",.    z
10170 53 65 6c 66 50 72 6f 6a 43 6f 64 65 2c 20 7a 53  SelfProjCode, zS
10180 65 6c 66 4c 61 62 65 6c 2c 20 7a 53 65 6c 66 50  elfLabel, zSelfP
10190 72 6f 6a 43 6f 64 65 2c 20 7a 53 65 6c 66 52 65  rojCode, zSelfRe
101a0 70 6f 0a 20 20 29 3b 0a 20 20 6c 6f 67 69 6e 5f  po.  );.  login_
101b0 67 72 6f 75 70 5f 73 71 6c 28 7a 53 71 6c 2c 20  group_sql(zSql, 
101c0 22 3c 6c 69 3e 20 22 2c 20 22 3c 2f 6c 69 3e 22  "<li> ", "</li>"
101d0 2c 20 70 7a 45 72 72 4d 73 67 29 3b 0a 20 20 66  , pzErrMsg);.  f
101e0 6f 73 73 69 6c 5f 66 72 65 65 28 7a 53 71 6c 29  ossil_free(zSql)
101f0 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 4c 65 61 76 65  ;.}../*.** Leave
10200 20 74 68 65 20 6c 6f 67 69 6e 20 67 72 6f 75 70   the login group
10210 20 74 68 61 74 20 77 65 20 61 72 65 20 63 75 72   that we are cur
10220 72 65 6e 74 6c 79 20 70 61 72 74 20 6f 66 2e 0a  rently part of..
10230 2a 2f 0a 76 6f 69 64 20 6c 6f 67 69 6e 5f 67 72  */.void login_gr
10240 6f 75 70 5f 6c 65 61 76 65 28 63 68 61 72 20 2a  oup_leave(char *
10250 2a 70 7a 45 72 72 4d 73 67 29 7b 0a 20 20 63 68  *pzErrMsg){.  ch
10260 61 72 20 2a 7a 50 72 6f 6a 43 6f 64 65 3b 0a 20  ar *zProjCode;. 
10270 20 63 68 61 72 20 2a 7a 53 71 6c 3b 0a 0a 20 20   char *zSql;..  
10280 2a 70 7a 45 72 72 4d 73 67 20 3d 20 30 3b 0a 20  *pzErrMsg = 0;. 
10290 20 7a 50 72 6f 6a 43 6f 64 65 20 3d 20 61 62 62   zProjCode = abb
102a0 72 65 76 69 61 74 65 64 5f 70 72 6f 6a 65 63 74  reviated_project
102b0 5f 63 6f 64 65 28 64 62 5f 67 65 74 28 22 70 72  _code(db_get("pr
102c0 6f 6a 65 63 74 2d 63 6f 64 65 22 2c 22 78 22 29  oject-code","x")
102d0 29 3b 0a 20 20 7a 53 71 6c 20 3d 20 6d 70 72 69  );.  zSql = mpri
102e0 6e 74 66 28 0a 20 20 20 20 22 44 45 4c 45 54 45  ntf(.    "DELETE
102f0 20 46 52 4f 4d 20 63 6f 6e 66 69 67 20 57 48 45   FROM config WHE
10300 52 45 20 6e 61 6d 65 20 47 4c 4f 42 20 27 70 65  RE name GLOB 'pe
10310 65 72 2d 2a 2d 25 71 27 3b 22 0a 20 20 20 20 22  er-*-%q';".    "
10320 44 45 4c 45 54 45 20 46 52 4f 4d 20 63 6f 6e 66  DELETE FROM conf
10330 69 67 22 0a 20 20 20 20 22 20 57 48 45 52 45 20  ig".    " WHERE 
10340 6e 61 6d 65 3d 27 6c 6f 67 69 6e 2d 67 72 6f 75  name='login-grou
10350 70 2d 6e 61 6d 65 27 22 0a 20 20 20 20 22 20 20  p-name'".    "  
10360 20 41 4e 44 20 28 53 45 4c 45 43 54 20 63 6f 75   AND (SELECT cou
10370 6e 74 28 2a 29 20 46 52 4f 4d 20 63 6f 6e 66 69  nt(*) FROM confi
10380 67 20 57 48 45 52 45 20 6e 61 6d 65 20 47 4c 4f  g WHERE name GLO
10390 42 20 27 70 65 65 72 2d 2a 27 29 3d 3d 30 3b 22  B 'peer-*')==0;"
103a0 2c 0a 20 20 20 20 7a 50 72 6f 6a 43 6f 64 65 0a  ,.    zProjCode.
103b0 20 20 29 3b 0a 20 20 66 6f 73 73 69 6c 5f 66 72    );.  fossil_fr
103c0 65 65 28 7a 50 72 6f 6a 43 6f 64 65 29 3b 0a 20  ee(zProjCode);. 
103d0 20 6c 6f 67 69 6e 5f 67 72 6f 75 70 5f 73 71 6c   login_group_sql
103e0 28 7a 53 71 6c 2c 20 22 3c 6c 69 3e 20 22 2c 20  (zSql, "<li> ", 
103f0 22 3c 2f 6c 69 3e 22 2c 20 70 7a 45 72 72 4d 73  "</li>", pzErrMs
10400 67 29 3b 0a 20 20 66 6f 73 73 69 6c 5f 66 72 65  g);.  fossil_fre
10410 65 28 7a 53 71 6c 29 3b 0a 20 20 64 62 5f 6d 75  e(zSql);.  db_mu
10420 6c 74 69 5f 65 78 65 63 28 0a 20 20 20 20 22 44  lti_exec(.    "D
10430 45 4c 45 54 45 20 46 52 4f 4d 20 63 6f 6e 66 69  ELETE FROM confi
10440 67 20 22 0a 20 20 20 20 22 20 57 48 45 52 45 20  g ".    " WHERE 
10450 6e 61 6d 65 20 47 4c 4f 42 20 27 70 65 65 72 2d  name GLOB 'peer-
10460 2a 27 22 0a 20 20 20 20 22 20 20 20 20 4f 52 20  *'".    "    OR 
10470 6e 61 6d 65 20 47 4c 4f 42 20 27 6c 6f 67 69 6e  name GLOB 'login
10480 2d 67 72 6f 75 70 2d 2a 27 3b 22 0a 20 20 29 3b  -group-*';".  );
10490 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 43 4f 4d 4d 41 4e  .}../*.** COMMAN
104a0 44 3a 20 6c 6f 67 69 6e 2d 67 72 6f 75 70 2a 0a  D: login-group*.
104b0 2a 2a 0a 2a 2a 20 55 73 61 67 65 3a 20 25 66 6f  **.** Usage: %fo
104c0 73 73 69 6c 20 6c 6f 67 69 6e 2d 67 72 6f 75 70  ssil login-group
104d0 0a 2a 2a 20 20 20 20 6f 72 3a 20 25 66 6f 73 73  .**    or: %foss
104e0 69 6c 20 6c 6f 67 69 6e 2d 67 72 6f 75 70 20 6a  il login-group j
104f0 6f 69 6e 20 52 45 50 4f 20 5b 2d 6e 61 6d 65 20  oin REPO [-name 
10500 4e 41 4d 45 5d 0a 2a 2a 20 20 20 20 6f 72 3a 20  NAME].**    or: 
10510 25 66 6f 73 73 69 6c 20 6c 6f 67 69 6e 2d 67 72  %fossil login-gr
10520 6f 75 70 20 6c 65 61 76 65 0a 2a 2a 0a 2a 2a 20  oup leave.**.** 
10530 57 69 74 68 20 6e 6f 20 61 72 67 75 6d 65 6e 74  With no argument
10540 73 2c 20 74 68 69 73 20 63 6f 6d 6d 61 6e 64 20  s, this command 
10550 73 68 6f 77 73 20 74 68 65 20 6c 6f 67 69 6e 2d  shows the login-
10560 67 72 6f 75 70 20 74 6f 20 77 68 69 63 68 20 74  group to which t
10570 68 65 0a 2a 2a 20 72 65 70 6f 73 69 74 6f 72 79  he.** repository
10580 20 62 65 6c 6f 6e 67 73 2e 0a 2a 2a 0a 2a 2a 20   belongs..**.** 
10590 54 68 65 20 22 6a 6f 69 6e 22 20 63 6f 6d 6d 61  The "join" comma
105a0 6e 64 20 61 64 64 73 20 74 68 69 73 20 72 65 70  nd adds this rep
105b0 6f 73 69 74 6f 72 79 20 74 6f 20 6c 6f 67 69 6e  ository to login
105c0 20 67 72 6f 75 70 20 74 6f 20 77 68 69 63 68 20   group to which 
105d0 52 45 50 4f 0a 2a 2a 20 62 65 6c 6f 6e 67 73 2c  REPO.** belongs,
105e0 20 6f 72 20 63 72 65 61 74 65 73 20 61 20 6e 65   or creates a ne
105f0 77 20 6c 6f 67 69 6e 20 67 72 6f 75 70 20 62 65  w login group be
10600 74 77 65 65 6e 20 69 74 73 65 6c 66 20 61 6e 64  tween itself and
10610 20 52 45 50 4f 20 69 66 20 52 45 50 4f 0a 2a 2a   REPO if REPO.**
10620 20 64 6f 65 73 20 6e 6f 74 20 61 6c 72 65 61 64   does not alread
10630 79 20 62 65 6c 6f 6e 67 20 74 6f 20 61 20 6c 6f  y belong to a lo
10640 67 69 6e 2d 67 72 6f 75 70 2e 20 20 57 68 65 6e  gin-group.  When
10650 20 63 72 65 61 74 69 6e 67 20 61 20 6e 65 77 20   creating a new 
10660 6c 6f 67 69 6e 2d 0a 2a 2a 20 67 72 6f 75 70 2c  login-.** group,
10670 20 74 68 65 20 6e 61 6d 65 20 6f 66 20 74 68 65   the name of the
10680 20 6e 65 77 20 67 72 6f 75 70 20 69 73 20 64 65   new group is de
10690 74 65 72 6d 69 6e 65 64 20 62 79 20 74 68 65 20  termined by the 
106a0 22 2d 2d 6e 61 6d 65 22 20 6f 70 74 69 6f 6e 2e  "--name" option.
106b0 0a 2a 2a 0a 2a 2a 20 54 68 65 20 22 6c 65 61 76  .**.** The "leav
106c0 65 22 20 63 6f 6d 6d 61 6e 64 20 74 61 6b 65 73  e" command takes
106d0 20 74 68 65 20 72 65 70 6f 73 69 74 6f 72 79 20   the repository 
106e0 6f 75 74 20 6f 66 20 77 68 61 74 65 76 65 72 20  out of whatever 
106f0 6c 6f 67 69 6e 20 67 72 6f 75 70 0a 2a 2a 20 69  login group.** i
10700 74 20 69 73 20 63 75 72 72 65 6e 74 6c 79 20 61  t is currently a
10710 20 70 61 72 74 20 6f 66 2e 0a 2a 2a 0a 2a 2a 20   part of..**.** 
10720 41 62 6f 75 74 20 4c 6f 67 69 6e 20 47 72 6f 75  About Login Grou
10730 70 73 3a 0a 2a 2a 0a 2a 2a 20 41 20 6c 6f 67 69  ps:.**.** A logi
10740 6e 2d 67 72 6f 75 70 20 69 73 20 61 20 73 65 74  n-group is a set
10750 20 6f 66 20 72 65 70 6f 73 69 74 6f 72 69 65 73   of repositories
10760 20 74 68 61 74 20 73 68 61 72 65 20 75 73 65 72   that share user
10770 20 63 72 65 64 65 6e 74 69 61 6c 73 2e 0a 2a 2a   credentials..**
10780 20 49 66 20 61 20 75 73 65 72 20 69 73 20 6c 6f   If a user is lo
10790 67 67 65 64 20 69 6e 74 6f 20 6f 6e 65 20 6d 65  gged into one me
107a0 6d 62 65 72 20 6f 66 20 74 68 65 20 67 72 6f 75  mber of the grou
107b0 70 2c 20 74 68 65 6e 20 74 68 61 74 20 75 73 65  p, then that use
107c0 72 20 63 61 6e 0a 2a 2a 20 61 63 63 65 73 73 20  r can.** access 
107d0 61 6e 79 20 6f 74 68 65 72 20 67 72 6f 75 70 20  any other group 
107e0 6d 65 6d 62 65 72 20 61 73 20 6c 6f 6e 67 20 61  member as long a
107f0 73 20 74 68 65 79 20 68 61 76 65 20 61 6e 20 65  s they have an e
10800 6e 74 72 79 20 69 6e 20 74 68 65 0a 2a 2a 20 55  ntry in the.** U
10810 53 45 52 20 74 61 62 6c 65 20 6f 66 20 74 68 61  SER table of tha
10820 74 20 6d 65 6d 62 65 72 2e 20 20 49 66 20 61 20  t member.  If a 
10830 75 73 65 72 20 63 68 61 6e 67 65 73 20 74 68 65  user changes the
10840 69 72 20 70 61 73 73 77 6f 72 64 20 75 73 69 6e  ir password usin
10850 67 0a 2a 2a 20 77 65 62 20 69 6e 74 65 72 66 61  g.** web interfa
10860 63 65 2c 20 74 68 65 69 72 20 70 61 73 73 77 6f  ce, their passwo
10870 72 64 20 69 73 20 61 6c 73 6f 20 61 75 74 6f 6d  rd is also autom
10880 61 74 69 63 61 6c 6c 79 20 63 68 61 6e 67 65 64  atically changed
10890 20 69 6e 20 65 76 65 72 79 0a 2a 2a 20 6f 74 68   in every.** oth
108a0 65 72 20 6d 65 6d 62 65 72 20 6f 66 20 74 68 65  er member of the
108b0 20 6c 6f 67 69 6e 20 67 72 6f 75 70 2e 0a 2a 2f   login group..*/
108c0 0a 76 6f 69 64 20 6c 6f 67 69 6e 5f 67 72 6f 75  .void login_grou
108d0 70 5f 63 6f 6d 6d 61 6e 64 28 76 6f 69 64 29 7b  p_command(void){
108e0 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a  .  const char *z
108f0 4c 47 4e 61 6d 65 3b 0a 20 20 63 6f 6e 73 74 20  LGName;.  const 
10900 63 68 61 72 20 2a 7a 43 6d 64 3b 0a 20 20 69 6e  char *zCmd;.  in
10910 74 20 6e 43 6d 64 3b 0a 20 20 53 74 6d 74 20 71  t nCmd;.  Stmt q
10920 3b 0a 20 20 64 62 5f 66 69 6e 64 5f 61 6e 64 5f  ;.  db_find_and_
10930 6f 70 65 6e 5f 72 65 70 6f 73 69 74 6f 72 79 28  open_repository(
10940 30 2c 30 29 3b 0a 20 20 69 66 28 20 67 2e 61 72  0,0);.  if( g.ar
10950 67 63 3e 32 20 29 7b 0a 20 20 20 20 7a 43 6d 64  gc>2 ){.    zCmd
10960 20 3d 20 67 2e 61 72 67 76 5b 32 5d 3b 0a 20 20   = g.argv[2];.  
10970 20 20 6e 43 6d 64 20 3d 20 28 69 6e 74 29 73 74    nCmd = (int)st
10980 72 6c 65 6e 28 7a 43 6d 64 29 3b 0a 20 20 20 20  rlen(zCmd);.    
10990 69 66 28 20 73 74 72 6e 63 6d 70 28 7a 43 6d 64  if( strncmp(zCmd
109a0 2c 22 6a 6f 69 6e 22 2c 6e 43 6d 64 29 3d 3d 30  ,"join",nCmd)==0
109b0 20 26 26 20 6e 43 6d 64 3e 3d 31 20 29 7b 0a 20   && nCmd>=1 ){. 
109c0 20 20 20 20 20 63 6f 6e 73 74 20 63 68 61 72 20       const char 
109d0 2a 7a 4e 65 77 4e 61 6d 65 20 3d 20 66 69 6e 64  *zNewName = find
109e0 5f 6f 70 74 69 6f 6e 28 22 6e 61 6d 65 22 2c 30  _option("name",0
109f0 2c 31 29 3b 0a 20 20 20 20 20 20 63 6f 6e 73 74  ,1);.      const
10a00 20 63 68 61 72 20 2a 7a 4f 74 68 65 72 3b 0a 20   char *zOther;. 
10a10 20 20 20 20 20 63 68 61 72 20 2a 7a 45 72 72 20       char *zErr 
10a20 3d 20 30 3b 0a 20 20 20 20 20 20 76 65 72 69 66  = 0;.      verif
10a30 79 5f 61 6c 6c 5f 6f 70 74 69 6f 6e 73 28 29 3b  y_all_options();
10a40 0a 20 20 20 20 20 20 69 66 28 20 67 2e 61 72 67  .      if( g.arg
10a50 63 21 3d 34 20 29 7b 0a 20 20 20 20 20 20 20 20  c!=4 ){.        
10a60 66 6f 73 73 69 6c 5f 66 61 74 61 6c 28 22 75 6e  fossil_fatal("un
10a70 6b 6e 6f 77 6e 20 65 78 74 72 61 20 61 72 67 75  known extra argu
10a80 6d 65 6e 74 73 20 74 6f 20 5c 22 6c 6f 67 69 6e  ments to \"login
10a90 2d 67 72 6f 75 70 20 6a 6f 69 6e 5c 22 22 29 3b  -group join\"");
10aa0 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 7a  .      }.      z
10ab0 4f 74 68 65 72 20 3d 20 67 2e 61 72 67 76 5b 33  Other = g.argv[3
10ac0 5d 3b 0a 20 20 20 20 20 20 6c 6f 67 69 6e 5f 67  ];.      login_g
10ad0 72 6f 75 70 5f 6c 65 61 76 65 28 26 7a 45 72 72  roup_leave(&zErr
10ae0 29 3b 0a 20 20 20 20 20 20 73 71 6c 69 74 65 33  );.      sqlite3
10af0 5f 66 72 65 65 28 7a 45 72 72 29 3b 0a 20 20 20  _free(zErr);.   
10b00 20 20 20 7a 45 72 72 20 3d 20 30 3b 0a 20 20 20     zErr = 0;.   
10b10 20 20 20 6c 6f 67 69 6e 5f 67 72 6f 75 70 5f 6a     login_group_j
10b20 6f 69 6e 28 7a 4f 74 68 65 72 2c 30 2c 30 2c 30  oin(zOther,0,0,0
10b30 2c 7a 4e 65 77 4e 61 6d 65 2c 26 7a 45 72 72 29  ,zNewName,&zErr)
10b40 3b 0a 20 20 20 20 20 20 69 66 28 20 7a 45 72 72  ;.      if( zErr
10b50 20 29 7b 0a 20 20 20 20 20 20 20 20 66 6f 73 73   ){.        foss
10b60 69 6c 5f 66 61 74 61 6c 28 22 25 73 22 2c 20 7a  il_fatal("%s", z
10b70 45 72 72 29 3b 0a 20 20 20 20 20 20 7d 0a 20 20  Err);.      }.  
10b80 20 20 7d 65 6c 73 65 20 69 66 28 20 73 74 72 6e    }else if( strn
10b90 63 6d 70 28 7a 43 6d 64 2c 22 6c 65 61 76 65 22  cmp(zCmd,"leave"
10ba0 2c 6e 43 6d 64 29 3d 3d 30 20 26 26 20 6e 43 6d  ,nCmd)==0 && nCm
10bb0 64 3e 3d 31 20 29 7b 0a 20 20 20 20 20 20 76 65  d>=1 ){.      ve
10bc0 72 69 66 79 5f 61 6c 6c 5f 6f 70 74 69 6f 6e 73  rify_all_options
10bd0 28 29 3b 0a 20 20 20 20 20 20 69 66 28 20 67 2e  ();.      if( g.
10be0 61 72 67 63 21 3d 33 20 29 7b 0a 20 20 20 20 20  argc!=3 ){.     
10bf0 20 20 20 66 6f 73 73 69 6c 5f 66 61 74 61 6c 28     fossil_fatal(
10c00 22 75 6e 6b 6e 6f 77 6e 20 65 78 74 72 61 20 61  "unknown extra a
10c10 72 67 75 6d 65 6e 74 73 20 74 6f 20 5c 22 6c 6f  rguments to \"lo
10c20 67 69 6e 2d 67 72 6f 75 70 20 6c 65 61 76 65 5c  gin-group leave\
10c30 22 22 29 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20  "");.      }.   
10c40 20 20 20 7a 4c 47 4e 61 6d 65 20 3d 20 6c 6f 67     zLGName = log
10c50 69 6e 5f 67 72 6f 75 70 5f 6e 61 6d 65 28 29 3b  in_group_name();
10c60 0a 20 20 20 20 20 20 69 66 28 20 7a 4c 47 4e 61  .      if( zLGNa
10c70 6d 65 20 29 7b 0a 20 20 20 20 20 20 20 20 63 68  me ){.        ch
10c80 61 72 20 2a 7a 45 72 72 20 3d 20 30 3b 0a 20 20  ar *zErr = 0;.  
10c90 20 20 20 20 20 20 66 6f 73 73 69 6c 5f 70 72 69        fossil_pri
10ca0 6e 74 28 22 4c 65 61 76 69 6e 67 20 6c 6f 67 69  nt("Leaving logi
10cb0 6e 2d 67 72 6f 75 70 20 5c 22 25 73 5c 22 5c 6e  n-group \"%s\"\n
10cc0 22 2c 20 7a 4c 47 4e 61 6d 65 29 3b 0a 20 20 20  ", zLGName);.   
10cd0 20 20 20 20 20 6c 6f 67 69 6e 5f 67 72 6f 75 70       login_group
10ce0 5f 6c 65 61 76 65 28 26 7a 45 72 72 29 3b 0a 20  _leave(&zErr);. 
10cf0 20 20 20 20 20 20 20 69 66 28 20 7a 45 72 72 20         if( zErr 
10d00 29 20 66 6f 73 73 69 6c 5f 66 61 74 61 6c 28 22  ) fossil_fatal("
10d10 4f 6f 70 73 3a 20 25 73 22 2c 20 7a 45 72 72 29  Oops: %s", zErr)
10d20 3b 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e  ;.        return
10d30 3b 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 65  ;.      }.    }e
10d40 6c 73 65 7b 0a 20 20 20 20 20 20 66 6f 73 73 69  lse{.      fossi
10d50 6c 5f 66 61 74 61 6c 28 22 75 6e 6b 6e 6f 77 6e  l_fatal("unknown
10d60 20 63 6f 6d 6d 61 6e 64 20 5c 22 25 73 5c 22 20   command \"%s\" 
10d70 2d 20 73 68 6f 75 6c 64 20 62 65 20 5c 22 6a 6f  - should be \"jo
10d80 69 6e 5c 22 20 6f 72 20 5c 22 6c 65 61 76 65 5c  in\" or \"leave\
10d90 22 22 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20  "",.            
10da0 20 20 20 20 20 20 20 7a 43 6d 64 29 3b 0a 20 20         zCmd);.  
10db0 20 20 7d 0a 20 20 7d 0a 20 20 2f 2a 20 53 68 6f    }.  }.  /* Sho
10dc0 77 20 74 68 65 20 63 75 72 72 65 6e 74 20 6c 6f  w the current lo
10dd0 67 69 6e 20 67 72 6f 75 70 20 69 6e 66 6f 72 6d  gin group inform
10de0 61 74 69 6f 6e 20 2a 2f 0a 20 20 7a 4c 47 4e 61  ation */.  zLGNa
10df0 6d 65 20 3d 20 6c 6f 67 69 6e 5f 67 72 6f 75 70  me = login_group
10e00 5f 6e 61 6d 65 28 29 3b 0a 20 20 69 66 28 20 7a  _name();.  if( z
10e10 4c 47 4e 61 6d 65 3d 3d 30 20 29 7b 0a 20 20 20  LGName==0 ){.   
10e20 20 66 6f 73 73 69 6c 5f 70 72 69 6e 74 28 22 4e   fossil_print("N
10e30 6f 74 20 63 75 72 72 65 6e 74 6c 79 20 61 20 70  ot currently a p
10e40 61 72 74 20 6f 66 20 61 6e 79 20 6c 6f 67 69 6e  art of any login
10e50 2d 67 72 6f 75 70 5c 6e 22 29 3b 0a 20 20 20 20  -group\n");.    
10e60 72 65 74 75 72 6e 3b 0a 20 20 7d 0a 20 20 66 6f  return;.  }.  fo
10e70 73 73 69 6c 5f 70 72 69 6e 74 28 22 4e 6f 77 20  ssil_print("Now 
10e80 70 61 72 74 20 6f 66 20 6c 6f 67 69 6e 2d 67 72  part of login-gr
10e90 6f 75 70 20 5c 22 25 73 5c 22 20 77 69 74 68 3a  oup \"%s\" with:
10ea0 5c 6e 22 2c 20 7a 4c 47 4e 61 6d 65 29 3b 0a 20  \n", zLGName);. 
10eb0 20 64 62 5f 70 72 65 70 61 72 65 28 26 71 2c 20   db_prepare(&q, 
10ec0 22 53 45 4c 45 43 54 20 76 61 6c 75 65 20 46 52  "SELECT value FR
10ed0 4f 4d 20 63 6f 6e 66 69 67 20 57 48 45 52 45 20  OM config WHERE 
10ee0 6e 61 6d 65 20 4c 49 4b 45 20 27 70 65 65 72 2d  name LIKE 'peer-
10ef0 6e 61 6d 65 2d 25 25 27 22 29 3b 0a 20 20 77 68  name-%%'");.  wh
10f00 69 6c 65 28 20 64 62 5f 73 74 65 70 28 26 71 29  ile( db_step(&q)
10f10 3d 3d 53 51 4c 49 54 45 5f 52 4f 57 20 29 7b 0a  ==SQLITE_ROW ){.
10f20 20 20 20 20 66 6f 73 73 69 6c 5f 70 72 69 6e 74      fossil_print
10f30 28 22 20 20 25 73 5c 6e 22 2c 20 64 62 5f 63 6f  ("  %s\n", db_co
10f40 6c 75 6d 6e 5f 74 65 78 74 28 26 71 2c 30 29 29  lumn_text(&q,0))
10f50 3b 0a 20 20 7d 0a 20 20 64 62 5f 66 69 6e 61 6c  ;.  }.  db_final
10f60 69 7a 65 28 26 71 29 3b 0a 0a 7d 0a              ize(&q);..}.