Fossil

Hex Artifact Content
Login

Artifact 73e026debf0868fc7c09d608ecaa23f5b80d46069349f89819915d21d7ba4c3b:


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 20 72 65 74 75 72  gent)==0 ) retur
39c0: 6e 20 31 3b 20 2f 2a 20 49 45 31 31 2b 20 2a 2f  n 1; /* IE11+ */
39d0: 0a 20 20 20 20 69 66 28 20 73 71 6c 69 74 65 33  .    if( sqlite3
39e0: 5f 73 74 72 67 6c 6f 62 28 22 2a 41 70 70 6c 65  _strglob("*Apple
39f0: 57 65 62 4b 69 74 2f 5b 31 2d 39 5d 2a 28 4b 48  WebKit/[1-9]*(KH
3a00: 54 4d 4c 2a 22 2c 20 7a 41 67 65 6e 74 29 3d 3d  TML*", zAgent)==
3a10: 30 20 29 20 72 65 74 75 72 6e 20 31 3b 0a 20 20  0 ) return 1;.  
3a20: 20 20 72 65 74 75 72 6e 20 30 3b 0a 20 20 7d 0a    return 0;.  }.
3a30: 20 20 69 66 28 20 73 74 72 6e 63 6d 70 28 7a 41    if( strncmp(zA
3a40: 67 65 6e 74 2c 20 22 4f 70 65 72 61 2f 22 2c 20  gent, "Opera/", 
3a50: 36 29 3d 3d 30 20 29 20 72 65 74 75 72 6e 20 31  6)==0 ) return 1
3a60: 3b 0a 20 20 69 66 28 20 73 74 72 6e 63 6d 70 28  ;.  if( strncmp(
3a70: 7a 41 67 65 6e 74 2c 20 22 53 61 66 61 72 69 2f  zAgent, "Safari/
3a80: 22 2c 20 37 29 3d 3d 30 20 29 20 72 65 74 75 72  ", 7)==0 ) retur
3a90: 6e 20 31 3b 0a 20 20 69 66 28 20 73 74 72 6e 63  n 1;.  if( strnc
3aa0: 6d 70 28 7a 41 67 65 6e 74 2c 20 22 4c 79 6e 78  mp(zAgent, "Lynx
3ab0: 2f 22 2c 20 35 29 3d 3d 30 20 29 20 72 65 74 75  /", 5)==0 ) retu
3ac0: 72 6e 20 31 3b 0a 20 20 69 66 28 20 73 74 72 6e  rn 1;.  if( strn
3ad0: 63 6d 70 28 7a 41 67 65 6e 74 2c 20 22 4e 65 74  cmp(zAgent, "Net
3ae0: 53 75 72 66 2f 22 2c 20 38 29 3d 3d 30 20 29 20  Surf/", 8)==0 ) 
3af0: 72 65 74 75 72 6e 20 31 3b 0a 20 20 72 65 74 75  return 1;.  retu
3b00: 72 6e 20 30 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 43  rn 0;.}../*.** C
3b10: 4f 4d 4d 41 4e 44 3a 20 74 65 73 74 2d 69 73 68  OMMAND: test-ish
3b20: 75 6d 61 6e 0a 2a 2a 0a 2a 2a 20 52 65 61 64 20  uman.**.** Read 
3b30: 6c 69 6e 65 73 20 6f 66 20 74 65 78 74 20 66 72  lines of text fr
3b40: 6f 6d 20 73 74 61 6e 64 61 72 64 20 69 6e 70 75  om standard inpu
3b50: 74 2e 20 20 49 6e 74 65 72 70 72 65 74 20 65 61  t.  Interpret ea
3b60: 63 68 20 6c 69 6e 65 20 6f 66 20 74 65 78 74 0a  ch line of text.
3b70: 2a 2a 20 61 73 20 61 20 55 73 65 72 2d 41 67 65  ** as a User-Age
3b80: 6e 74 20 73 74 72 69 6e 67 20 66 72 6f 6d 20 61  nt string from a
3b90: 6e 20 48 54 54 50 20 68 65 61 64 65 72 2e 20 20  n HTTP header.  
3ba0: 4c 61 62 65 6c 20 65 61 63 68 20 6c 69 6e 65 20  Label each line 
3bb0: 61 73 20 48 55 4d 41 4e 0a 2a 2a 20 6f 72 20 52  as HUMAN.** or R
3bc0: 4f 42 4f 54 2e 0a 2a 2f 0a 76 6f 69 64 20 74 65  OBOT..*/.void te
3bd0: 73 74 5f 69 73 68 75 6d 61 6e 28 76 6f 69 64 29  st_ishuman(void)
3be0: 7b 0a 20 20 63 68 61 72 20 7a 4c 69 6e 65 5b 33  {.  char zLine[3
3bf0: 30 30 30 5d 3b 0a 20 20 77 68 69 6c 65 28 20 66  000];.  while( f
3c00: 67 65 74 73 28 7a 4c 69 6e 65 2c 20 73 69 7a 65  gets(zLine, size
3c10: 6f 66 28 7a 4c 69 6e 65 29 2c 20 73 74 64 69 6e  of(zLine), stdin
3c20: 29 20 29 7b 0a 20 20 20 20 66 6f 73 73 69 6c 5f  ) ){.    fossil_
3c30: 70 72 69 6e 74 28 22 25 73 20 25 73 22 2c 20 69  print("%s %s", i
3c40: 73 48 75 6d 61 6e 28 7a 4c 69 6e 65 29 20 3f 20  sHuman(zLine) ? 
3c50: 22 48 55 4d 41 4e 22 20 3a 20 22 52 4f 42 4f 54  "HUMAN" : "ROBOT
3c60: 22 2c 20 7a 4c 69 6e 65 29 3b 0a 20 20 7d 0a 7d  ", zLine);.  }.}
3c70: 0a 0a 2f 2a 0a 2a 2a 20 53 51 4c 20 66 75 6e 63  ../*.** SQL func
3c80: 74 69 6f 6e 20 66 6f 72 20 63 6f 6e 73 74 61 6e  tion for constan
3c90: 74 20 74 69 6d 65 20 63 6f 6d 70 61 72 69 73 6f  t time compariso
3ca0: 6e 20 6f 66 20 74 77 6f 20 76 61 6c 75 65 73 2e  n of two values.
3cb0: 0a 2a 2a 20 53 65 74 73 20 72 65 73 75 6c 74 20  .** Sets result 
3cc0: 74 6f 20 30 20 69 66 20 74 77 6f 20 76 61 6c 75  to 0 if two valu
3cd0: 65 73 20 61 72 65 20 65 71 75 61 6c 2e 0a 2a 2f  es are equal..*/
3ce0: 0a 73 74 61 74 69 63 20 76 6f 69 64 20 63 6f 6e  .static void con
3cf0: 73 74 61 6e 74 5f 74 69 6d 65 5f 63 6d 70 5f 66  stant_time_cmp_f
3d00: 75 6e 63 74 69 6f 6e 28 0a 20 73 71 6c 69 74 65  unction(. sqlite
3d10: 33 5f 63 6f 6e 74 65 78 74 20 2a 63 6f 6e 74 65  3_context *conte
3d20: 78 74 2c 0a 20 69 6e 74 20 61 72 67 63 2c 0a 20  xt,. int argc,. 
3d30: 73 71 6c 69 74 65 33 5f 76 61 6c 75 65 20 2a 2a  sqlite3_value **
3d40: 61 72 67 76 0a 29 7b 0a 20 20 63 6f 6e 73 74 20  argv.){.  const 
3d50: 75 6e 73 69 67 6e 65 64 20 63 68 61 72 20 2a 62  unsigned char *b
3d60: 75 66 31 2c 20 2a 62 75 66 32 3b 0a 20 20 69 6e  uf1, *buf2;.  in
3d70: 74 20 6c 65 6e 2c 20 69 3b 0a 20 20 75 6e 73 69  t len, i;.  unsi
3d80: 67 6e 65 64 20 63 68 61 72 20 72 63 20 3d 20 30  gned char rc = 0
3d90: 3b 0a 0a 20 20 61 73 73 65 72 74 28 20 61 72 67  ;..  assert( arg
3da0: 63 3d 3d 32 20 29 3b 0a 20 20 6c 65 6e 20 3d 20  c==2 );.  len = 
3db0: 73 71 6c 69 74 65 33 5f 76 61 6c 75 65 5f 62 79  sqlite3_value_by
3dc0: 74 65 73 28 61 72 67 76 5b 30 5d 29 3b 0a 20 20  tes(argv[0]);.  
3dd0: 69 66 28 20 6c 65 6e 3d 3d 30 20 7c 7c 20 6c 65  if( len==0 || le
3de0: 6e 21 3d 73 71 6c 69 74 65 33 5f 76 61 6c 75 65  n!=sqlite3_value
3df0: 5f 62 79 74 65 73 28 61 72 67 76 5b 31 5d 29 20  _bytes(argv[1]) 
3e00: 29 7b 0a 20 20 20 20 72 63 20 3d 20 31 3b 0a 20  ){.    rc = 1;. 
3e10: 20 7d 65 6c 73 65 7b 0a 20 20 20 20 62 75 66 31   }else{.    buf1
3e20: 20 3d 20 73 71 6c 69 74 65 33 5f 76 61 6c 75 65   = sqlite3_value
3e30: 5f 74 65 78 74 28 61 72 67 76 5b 30 5d 29 3b 0a  _text(argv[0]);.
3e40: 20 20 20 20 62 75 66 32 20 3d 20 73 71 6c 69 74      buf2 = sqlit
3e50: 65 33 5f 76 61 6c 75 65 5f 74 65 78 74 28 61 72  e3_value_text(ar
3e60: 67 76 5b 31 5d 29 3b 0a 20 20 20 20 66 6f 72 28  gv[1]);.    for(
3e70: 20 69 3d 30 3b 20 69 3c 6c 65 6e 3b 20 69 2b 2b   i=0; i<len; i++
3e80: 20 29 7b 0a 20 20 20 20 20 20 72 63 20 3d 20 72   ){.      rc = r
3e90: 63 20 7c 20 28 62 75 66 31 5b 69 5d 20 5e 20 62  c | (buf1[i] ^ b
3ea0: 75 66 32 5b 69 5d 29 3b 0a 20 20 20 20 7d 0a 20  uf2[i]);.    }. 
3eb0: 20 7d 0a 20 20 73 71 6c 69 74 65 33 5f 72 65 73   }.  sqlite3_res
3ec0: 75 6c 74 5f 69 6e 74 28 63 6f 6e 74 65 78 74 2c  ult_int(context,
3ed0: 20 72 63 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 52   rc);.}../*.** R
3ee0: 65 74 75 72 6e 20 74 72 75 65 20 69 66 20 74 68  eturn true if th
3ef0: 65 20 63 75 72 72 65 6e 74 20 70 61 67 65 20 77  e current page w
3f00: 61 73 20 72 65 61 63 68 65 64 20 62 79 20 61 20  as reached by a 
3f10: 72 65 64 69 72 65 63 74 20 66 72 6f 6d 20 74 68  redirect from th
3f20: 65 20 2f 6c 6f 67 69 6e 0a 2a 2a 20 70 61 67 65  e /login.** page
3f30: 2e 0a 2a 2f 0a 69 6e 74 20 72 65 66 65 72 72 65  ..*/.int referre
3f40: 64 5f 66 72 6f 6d 5f 6c 6f 67 69 6e 28 76 6f 69  d_from_login(voi
3f50: 64 29 7b 0a 20 20 63 6f 6e 73 74 20 63 68 61 72  d){.  const char
3f60: 20 2a 7a 52 65 66 65 72 65 72 20 3d 20 50 28 22   *zReferer = P("
3f70: 48 54 54 50 5f 52 45 46 45 52 45 52 22 29 3b 0a  HTTP_REFERER");.
3f80: 20 20 63 68 61 72 20 2a 7a 50 61 74 74 65 72 6e    char *zPattern
3f90: 3b 0a 20 20 69 6e 74 20 72 63 3b 0a 20 20 69 66  ;.  int rc;.  if
3fa0: 28 20 7a 52 65 66 65 72 65 72 3d 3d 30 20 29 20  ( zReferer==0 ) 
3fb0: 72 65 74 75 72 6e 20 30 3b 0a 20 20 7a 50 61 74  return 0;.  zPat
3fc0: 74 65 72 6e 20 3d 20 6d 70 72 69 6e 74 66 28 22  tern = mprintf("
3fd0: 25 73 2f 6c 6f 67 69 6e 2a 22 2c 20 67 2e 7a 42  %s/login*", g.zB
3fe0: 61 73 65 55 52 4c 29 3b 0a 20 20 72 63 20 3d 20  aseURL);.  rc = 
3ff0: 73 71 6c 69 74 65 33 5f 73 74 72 67 6c 6f 62 28  sqlite3_strglob(
4000: 7a 50 61 74 74 65 72 6e 2c 20 7a 52 65 66 65 72  zPattern, zRefer
4010: 65 72 29 3d 3d 30 3b 0a 20 20 66 6f 73 73 69 6c  er)==0;.  fossil
4020: 5f 66 72 65 65 28 7a 50 61 74 74 65 72 6e 29 3b  _free(zPattern);
4030: 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a  .  return rc;.}.
4040: 0a 2f 2a 0a 2a 2a 20 52 65 74 75 72 6e 20 54 52  ./*.** Return TR
4050: 55 45 20 69 66 20 73 65 6c 66 2d 72 65 67 69 73  UE if self-regis
4060: 74 72 61 74 69 6f 6e 20 69 73 20 61 76 61 69 6c  tration is avail
4070: 61 62 6c 65 2e 20 20 49 66 20 74 68 65 20 7a 4e  able.  If the zN
4080: 65 65 64 65 64 0a 2a 2a 20 61 72 67 75 6d 65 6e  eeded.** argumen
4090: 74 20 69 73 20 6e 6f 74 20 4e 55 4c 4c 2c 20 74  t is not NULL, t
40a0: 68 65 6e 20 6f 6e 6c 79 20 72 65 74 75 72 6e 20  hen only return 
40b0: 74 72 75 65 20 69 66 20 73 65 6c 66 2d 72 65 67  true if self-reg
40c0: 69 73 74 72 61 74 69 6f 6e 20 69 73 0a 2a 2a 20  istration is.** 
40d0: 61 76 61 69 6c 61 62 6c 65 20 61 6e 64 20 61 6e  available and an
40e0: 79 20 6f 66 20 74 68 65 20 63 61 70 61 62 69 6c  y of the capabil
40f0: 69 74 69 65 73 20 6e 61 6d 65 64 20 69 6e 20 7a  ities named in z
4100: 4e 65 65 64 65 64 20 61 72 65 20 61 76 61 69 6c  Needed are avail
4110: 61 62 6c 65 0a 2a 2a 20 74 6f 20 73 65 6c 66 2d  able.** to self-
4120: 72 65 67 69 73 74 65 72 65 64 20 75 73 65 72 73  registered users
4130: 2e 0a 2a 2f 0a 69 6e 74 20 6c 6f 67 69 6e 5f 73  ..*/.int login_s
4140: 65 6c 66 5f 72 65 67 69 73 74 65 72 5f 61 76 61  elf_register_ava
4150: 69 6c 61 62 6c 65 28 63 6f 6e 73 74 20 63 68 61  ilable(const cha
4160: 72 20 2a 7a 4e 65 65 64 65 64 29 7b 0a 20 20 43  r *zNeeded){.  C
4170: 61 70 61 62 69 6c 69 74 79 53 74 72 69 6e 67 20  apabilityString 
4180: 2a 70 43 61 70 3b 0a 20 20 69 6e 74 20 72 63 3b  *pCap;.  int rc;
4190: 0a 20 20 69 66 28 20 21 64 62 5f 67 65 74 5f 62  .  if( !db_get_b
41a0: 6f 6f 6c 65 61 6e 28 22 73 65 6c 66 2d 72 65 67  oolean("self-reg
41b0: 69 73 74 65 72 22 2c 30 29 20 29 20 72 65 74 75  ister",0) ) retu
41c0: 72 6e 20 30 3b 0a 20 20 69 66 28 20 7a 4e 65 65  rn 0;.  if( zNee
41d0: 64 65 64 3d 3d 30 20 29 20 72 65 74 75 72 6e 20  ded==0 ) return 
41e0: 31 3b 0a 20 20 70 43 61 70 20 3d 20 63 61 70 61  1;.  pCap = capa
41f0: 62 69 6c 69 74 79 5f 61 64 64 28 30 2c 20 64 62  bility_add(0, db
4200: 5f 67 65 74 28 22 64 65 66 61 75 6c 74 2d 70 65  _get("default-pe
4210: 72 6d 73 22 2c 22 22 29 29 3b 0a 20 20 63 61 70  rms",""));.  cap
4220: 61 62 69 6c 69 74 79 5f 65 78 70 61 6e 64 28 70  ability_expand(p
4230: 43 61 70 29 3b 0a 20 20 72 63 20 3d 20 63 61 70  Cap);.  rc = cap
4240: 61 62 69 6c 69 74 79 5f 68 61 73 5f 61 6e 79 28  ability_has_any(
4250: 70 43 61 70 2c 20 7a 4e 65 65 64 65 64 29 3b 0a  pCap, zNeeded);.
4260: 20 20 63 61 70 61 62 69 6c 69 74 79 5f 66 72 65    capability_fre
4270: 65 28 70 43 61 70 29 3b 0a 20 20 72 65 74 75 72  e(pCap);.  retur
4280: 6e 20 72 63 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 54  n rc;.}../*.** T
4290: 68 65 72 65 20 75 73 65 64 20 74 6f 20 62 65 20  here used to be 
42a0: 61 20 70 61 67 65 20 6e 61 6d 65 64 20 22 6d 79  a page named "my
42b0: 22 20 74 68 61 74 20 77 61 73 20 64 65 73 69 67  " that was desig
42c0: 6e 65 64 20 74 6f 20 73 68 6f 77 20 69 6e 66 6f  ned to show info
42d0: 72 6d 61 74 69 6f 6e 0a 2a 2a 20 61 62 6f 75 74  rmation.** about
42e0: 20 61 20 73 70 65 63 69 66 69 63 20 75 73 65 72   a specific user
42f0: 2e 20 20 54 68 65 20 22 6d 79 22 20 70 61 67 65  .  The "my" page
4300: 20 77 61 73 20 6c 69 6e 6b 65 64 20 66 72 6f 6d   was linked from
4310: 20 74 68 65 20 22 4c 6f 67 67 65 64 20 69 6e 20   the "Logged in 
4320: 61 73 20 55 53 45 52 22 0a 2a 2a 20 6c 69 6e 65  as USER".** line
4330: 20 6f 6e 20 74 68 65 20 74 69 74 6c 65 20 62 61   on the title ba
4340: 72 2e 20 20 54 68 65 20 22 6d 79 22 20 70 61 67  r.  The "my" pag
4350: 65 20 77 61 73 20 6e 65 76 65 72 20 63 6f 6d 70  e was never comp
4360: 6c 65 74 65 64 20 73 6f 20 69 74 20 69 73 20 6e  leted so it is n
4370: 6f 77 0a 2a 2a 20 72 65 6d 6f 76 65 64 2e 20 20  ow.** removed.  
4380: 55 73 65 20 74 68 69 73 20 70 61 67 65 20 61 73  Use this page as
4390: 20 61 20 70 6c 61 63 65 68 6f 6c 64 65 72 20 69   a placeholder i
43a0: 6e 20 6f 6c 64 65 72 20 69 6e 73 74 61 6c 6c 61  n older installa
43b0: 74 69 6f 6e 73 2e 0a 2a 2a 0a 2a 2a 20 57 45 42  tions..**.** WEB
43c0: 50 41 47 45 3a 20 6c 6f 67 69 6e 0a 2a 2a 20 57  PAGE: login.** W
43d0: 45 42 50 41 47 45 3a 20 6c 6f 67 6f 75 74 0a 2a  EBPAGE: logout.*
43e0: 2a 20 57 45 42 50 41 47 45 3a 20 6d 79 0a 2a 2a  * WEBPAGE: my.**
43f0: 0a 2a 2a 20 54 68 65 20 6c 6f 67 69 6e 2f 6c 6f  .** The login/lo
4400: 67 6f 75 74 20 70 61 67 65 2e 20 20 50 61 72 61  gout page.  Para
4410: 6d 65 74 65 72 73 3a 0a 2a 2a 0a 2a 2a 20 20 20  meters:.**.**   
4420: 20 67 3d 55 52 4c 20 20 20 20 20 20 20 20 20 20   g=URL          
4430: 20 20 20 4a 75 6d 70 20 62 61 63 6b 20 74 6f 20     Jump back to 
4440: 74 68 69 73 20 55 52 4c 20 61 66 74 65 72 20 6c  this URL after l
4450: 6f 67 69 6e 20 63 6f 6d 70 6c 65 74 65 73 0a 2a  ogin completes.*
4460: 2a 20 20 20 20 61 6e 6f 6e 20 20 20 20 20 20 20  *    anon       
4470: 20 20 20 20 20 20 20 54 68 65 20 67 3d 55 52 4c         The g=URL
4480: 20 69 73 20 6e 6f 74 20 61 63 63 65 73 73 69 62   is not accessib
4490: 6c 65 20 62 79 20 22 6e 6f 62 6f 64 79 22 20 62  le by "nobody" b
44a0: 75 74 20 69 73 0a 2a 2a 20 20 20 20 20 20 20 20  ut is.**        
44b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 61 63                ac
44c0: 63 65 73 73 69 62 6c 65 20 62 79 20 22 61 6e 6f  cessible by "ano
44d0: 6e 79 6d 6f 75 73 22 0a 2a 2f 0a 76 6f 69 64 20  nymous".*/.void 
44e0: 6c 6f 67 69 6e 5f 70 61 67 65 28 76 6f 69 64 29  login_page(void)
44f0: 7b 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a  {.  const char *
4500: 7a 55 73 65 72 6e 61 6d 65 2c 20 2a 7a 50 61 73  zUsername, *zPas
4510: 73 77 64 3b 0a 20 20 63 6f 6e 73 74 20 63 68 61  swd;.  const cha
4520: 72 20 2a 7a 4e 65 77 31 2c 20 2a 7a 4e 65 77 32  r *zNew1, *zNew2
4530: 3b 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a  ;.  const char *
4540: 7a 41 6e 6f 6e 50 77 20 3d 20 30 3b 0a 20 20 63  zAnonPw = 0;.  c
4550: 6f 6e 73 74 20 63 68 61 72 20 2a 7a 47 6f 74 6f  onst char *zGoto
4560: 20 3d 20 50 28 22 67 22 29 3b 0a 20 20 69 6e 74   = P("g");.  int
4570: 20 61 6e 6f 6e 46 6c 61 67 3b 20 20 20 20 20 20   anonFlag;      
4580: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4c 6f 67            /* Log
4590: 69 6e 20 61 73 20 22 61 6e 6f 6e 79 6d 6f 75 73  in as "anonymous
45a0: 22 20 77 6f 75 6c 64 20 62 65 20 75 73 65 66 75  " would be usefu
45b0: 6c 20 2a 2f 0a 20 20 63 68 61 72 20 2a 7a 45 72  l */.  char *zEr
45c0: 72 4d 73 67 20 3d 20 22 22 3b 0a 20 20 69 6e 74  rMsg = "";.  int
45d0: 20 75 69 64 3b 20 20 20 20 20 20 20 20 20 20 20   uid;           
45e0: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 55 73 65            /* Use
45f0: 72 20 69 64 20 6c 6f 67 67 65 64 20 69 6e 20 75  r id logged in u
4600: 73 65 72 20 2a 2f 0a 20 20 63 68 61 72 20 2a 7a  ser */.  char *z
4610: 53 68 61 31 50 77 3b 0a 20 20 63 6f 6e 73 74 20  Sha1Pw;.  const 
4620: 63 68 61 72 20 2a 7a 49 70 41 64 64 72 3b 20 20  char *zIpAddr;  
4630: 20 20 20 20 20 20 20 2f 2a 20 49 50 20 61 64 64         /* IP add
4640: 72 65 73 73 20 6f 66 20 72 65 71 75 65 73 74 6f  ress of requesto
4650: 72 20 2a 2f 0a 20 20 63 6f 6e 73 74 20 63 68 61  r */.  const cha
4660: 72 20 2a 7a 52 65 66 65 72 65 72 3b 0a 20 20 69  r *zReferer;.  i
4670: 6e 74 20 6e 6f 41 6e 6f 6e 20 3d 20 50 28 22 6e  nt noAnon = P("n
4680: 6f 61 6e 6f 6e 22 29 21 3d 30 3b 0a 0a 20 20 6c  oanon")!=0;..  l
4690: 6f 67 69 6e 5f 63 68 65 63 6b 5f 63 72 65 64 65  ogin_check_crede
46a0: 6e 74 69 61 6c 73 28 29 3b 0a 20 20 66 6f 73 73  ntials();.  foss
46b0: 69 6c 5f 72 65 64 69 72 65 63 74 5f 74 6f 5f 68  il_redirect_to_h
46c0: 74 74 70 73 5f 69 66 5f 6e 65 65 64 65 64 28 31  ttps_if_needed(1
46d0: 29 3b 0a 20 20 73 71 6c 69 74 65 33 5f 63 72 65  );.  sqlite3_cre
46e0: 61 74 65 5f 66 75 6e 63 74 69 6f 6e 28 67 2e 64  ate_function(g.d
46f0: 62 2c 20 22 63 6f 6e 73 74 61 6e 74 5f 74 69 6d  b, "constant_tim
4700: 65 5f 63 6d 70 22 2c 20 32 2c 20 53 51 4c 49 54  e_cmp", 2, SQLIT
4710: 45 5f 55 54 46 38 2c 20 30 2c 0a 20 20 20 20 20  E_UTF8, 0,.     
4720: 20 20 20 20 20 20 20 20 20 20 20 20 20 63 6f 6e               con
4730: 73 74 61 6e 74 5f 74 69 6d 65 5f 63 6d 70 5f 66  stant_time_cmp_f
4740: 75 6e 63 74 69 6f 6e 2c 20 30 2c 20 30 29 3b 0a  unction, 0, 0);.
4750: 20 20 7a 55 73 65 72 6e 61 6d 65 20 3d 20 50 28    zUsername = P(
4760: 22 75 22 29 3b 0a 20 20 7a 50 61 73 73 77 64 20  "u");.  zPasswd 
4770: 3d 20 50 28 22 70 22 29 3b 0a 20 20 61 6e 6f 6e  = P("p");.  anon
4780: 46 6c 61 67 20 3d 20 67 2e 7a 4c 6f 67 69 6e 3d  Flag = g.zLogin=
4790: 3d 30 20 26 26 20 50 42 28 22 61 6e 6f 6e 22 29  =0 && PB("anon")
47a0: 3b 0a 0a 20 20 2f 2a 20 48 61 6e 64 6c 65 20 6c  ;..  /* Handle l
47b0: 6f 67 2d 6f 75 74 20 72 65 71 75 65 73 74 73 20  og-out requests 
47c0: 2a 2f 0a 20 20 69 66 28 20 50 28 22 6f 75 74 22  */.  if( P("out"
47d0: 29 20 29 7b 0a 20 20 20 20 6c 6f 67 69 6e 5f 63  ) ){.    login_c
47e0: 6c 65 61 72 5f 6c 6f 67 69 6e 5f 64 61 74 61 28  lear_login_data(
47f0: 29 3b 0a 20 20 20 20 72 65 64 69 72 65 63 74 5f  );.    redirect_
4800: 74 6f 5f 67 28 29 3b 0a 20 20 20 20 72 65 74 75  to_g();.    retu
4810: 72 6e 3b 0a 20 20 7d 0a 0a 20 20 2f 2a 20 52 65  rn;.  }..  /* Re
4820: 64 69 72 65 63 74 20 66 6f 72 20 63 72 65 61 74  direct for creat
4830: 65 2d 6e 65 77 2d 61 63 63 6f 75 6e 74 20 72 65  e-new-account re
4840: 71 75 65 73 74 73 20 2a 2f 0a 20 20 69 66 28 20  quests */.  if( 
4850: 50 28 22 73 65 6c 66 22 29 20 29 7b 0a 20 20 20  P("self") ){.   
4860: 20 63 67 69 5f 72 65 64 69 72 65 63 74 66 28 22   cgi_redirectf("
4870: 25 52 2f 72 65 67 69 73 74 65 72 22 29 3b 0a 20  %R/register");. 
4880: 20 20 20 72 65 74 75 72 6e 3b 0a 20 20 7d 0a 0a     return;.  }..
4890: 20 20 2f 2a 20 44 65 61 6c 20 77 69 74 68 20 70    /* Deal with p
48a0: 61 73 73 77 6f 72 64 2d 63 68 61 6e 67 65 20 72  assword-change r
48b0: 65 71 75 65 73 74 73 20 2a 2f 0a 20 20 69 66 28  equests */.  if(
48c0: 20 67 2e 70 65 72 6d 2e 50 61 73 73 77 6f 72 64   g.perm.Password
48d0: 20 26 26 20 7a 50 61 73 73 77 64 0a 20 20 20 26   && zPasswd.   &
48e0: 26 20 28 7a 4e 65 77 31 20 3d 20 50 28 22 6e 31  & (zNew1 = P("n1
48f0: 22 29 29 21 3d 30 20 26 26 20 28 7a 4e 65 77 32  "))!=0 && (zNew2
4900: 20 3d 20 50 28 22 6e 32 22 29 29 21 3d 30 0a 20   = P("n2"))!=0. 
4910: 20 29 7b 0a 20 20 20 20 2f 2a 20 49 66 20 74 68   ){.    /* If th
4920: 65 72 65 20 69 73 20 6e 6f 74 20 61 20 22 72 65  ere is not a "re
4930: 61 6c 22 20 6c 6f 67 69 6e 2c 20 77 65 20 63 61  al" login, we ca
4940: 6e 6e 6f 74 20 63 68 61 6e 67 65 20 61 6e 79 20  nnot change any 
4950: 70 61 73 73 77 6f 72 64 2e 20 2a 2f 0a 20 20 20  password. */.   
4960: 20 69 66 28 20 67 2e 7a 4c 6f 67 69 6e 20 29 7b   if( g.zLogin ){
4970: 0a 20 20 20 20 20 20 2f 2a 20 54 68 65 20 75 73  .      /* The us
4980: 65 72 20 72 65 71 75 65 73 74 73 20 61 20 70 61  er requests a pa
4990: 73 73 77 6f 72 64 20 63 68 61 6e 67 65 20 2a 2f  ssword change */
49a0: 0a 20 20 20 20 20 20 7a 53 68 61 31 50 77 20 3d  .      zSha1Pw =
49b0: 20 73 68 61 31 5f 73 68 61 72 65 64 5f 73 65 63   sha1_shared_sec
49c0: 72 65 74 28 7a 50 61 73 73 77 64 2c 20 67 2e 7a  ret(zPasswd, g.z
49d0: 4c 6f 67 69 6e 2c 20 30 29 3b 0a 20 20 20 20 20  Login, 0);.     
49e0: 20 69 66 28 20 64 62 5f 69 6e 74 28 31 2c 20 22   if( db_int(1, "
49f0: 53 45 4c 45 43 54 20 30 20 46 52 4f 4d 20 75 73  SELECT 0 FROM us
4a00: 65 72 22 0a 20 20 20 20 20 20 20 20 20 20 20 20  er".            
4a10: 20 20 20 20 20 20 20 20 22 20 57 48 45 52 45 20          " WHERE 
4a20: 75 69 64 3d 25 64 22 0a 20 20 20 20 20 20 20 20  uid=%d".        
4a30: 20 20 20 20 20 20 20 20 20 20 20 20 22 20 41 4e              " AN
4a40: 44 20 28 63 6f 6e 73 74 61 6e 74 5f 74 69 6d 65  D (constant_time
4a50: 5f 63 6d 70 28 70 77 2c 25 51 29 3d 30 22 0a 20  _cmp(pw,%Q)=0". 
4a60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
4a70: 20 20 20 22 20 20 20 20 20 20 4f 52 20 63 6f 6e     "      OR con
4a80: 73 74 61 6e 74 5f 74 69 6d 65 5f 63 6d 70 28 70  stant_time_cmp(p
4a90: 77 2c 25 51 29 3d 30 29 22 2c 0a 20 20 20 20 20  w,%Q)=0)",.     
4aa0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 67                 g
4ab0: 2e 75 73 65 72 55 69 64 2c 20 7a 53 68 61 31 50  .userUid, zSha1P
4ac0: 77 2c 20 7a 50 61 73 73 77 64 29 20 29 7b 0a 20  w, zPasswd) ){. 
4ad0: 20 20 20 20 20 20 20 73 6c 65 65 70 28 31 29 3b         sleep(1);
4ae0: 0a 20 20 20 20 20 20 20 20 7a 45 72 72 4d 73 67  .        zErrMsg
4af0: 20 3d 0a 20 20 20 20 20 20 20 20 20 20 20 40 20   =.           @ 
4b00: 3c 70 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22  <p><span class="
4b10: 6c 6f 67 69 6e 45 72 72 6f 72 22 3e 0a 20 20 20  loginError">.   
4b20: 20 20 20 20 20 20 20 20 40 20 59 6f 75 20 65 6e          @ You en
4b30: 74 65 72 65 64 20 61 6e 20 69 6e 63 6f 72 72 65  tered an incorre
4b40: 63 74 20 6f 6c 64 20 70 61 73 73 77 6f 72 64 20  ct old password 
4b50: 77 68 69 6c 65 20 61 74 74 65 6d 70 74 69 6e 67  while attempting
4b60: 20 74 6f 20 63 68 61 6e 67 65 0a 20 20 20 20 20   to change.     
4b70: 20 20 20 20 20 20 40 20 79 6f 75 72 20 70 61 73        @ your pas
4b80: 73 77 6f 72 64 2e 20 20 59 6f 75 72 20 70 61 73  sword.  Your pas
4b90: 73 77 6f 72 64 20 69 73 20 75 6e 63 68 61 6e 67  sword is unchang
4ba0: 65 64 2e 0a 20 20 20 20 20 20 20 20 20 20 20 40  ed..           @
4bb0: 20 3c 2f 73 70 61 6e 3e 3c 2f 70 3e 0a 20 20 20   </span></p>.   
4bc0: 20 20 20 20 20 3b 0a 20 20 20 20 20 20 7d 65 6c       ;.      }el
4bd0: 73 65 20 69 66 28 20 66 6f 73 73 69 6c 5f 73 74  se if( fossil_st
4be0: 72 63 6d 70 28 7a 4e 65 77 31 2c 7a 4e 65 77 32  rcmp(zNew1,zNew2
4bf0: 29 21 3d 30 20 29 7b 0a 20 20 20 20 20 20 20 20  )!=0 ){.        
4c00: 7a 45 72 72 4d 73 67 20 3d 0a 20 20 20 20 20 20  zErrMsg =.      
4c10: 20 20 20 20 20 40 20 3c 70 3e 3c 73 70 61 6e 20       @ <p><span 
4c20: 63 6c 61 73 73 3d 22 6c 6f 67 69 6e 45 72 72 6f  class="loginErro
4c30: 72 22 3e 0a 20 20 20 20 20 20 20 20 20 20 20 40  r">.           @
4c40: 20 54 68 65 20 74 77 6f 20 63 6f 70 69 65 73 20   The two copies 
4c50: 6f 66 20 79 6f 75 72 20 6e 65 77 20 70 61 73 73  of your new pass
4c60: 77 6f 72 64 73 20 64 6f 20 6e 6f 74 20 6d 61 74  words do not mat
4c70: 63 68 2e 0a 20 20 20 20 20 20 20 20 20 20 20 40  ch..           @
4c80: 20 59 6f 75 72 20 70 61 73 73 77 6f 72 64 20 69   Your password i
4c90: 73 20 75 6e 63 68 61 6e 67 65 64 2e 0a 20 20 20  s unchanged..   
4ca0: 20 20 20 20 20 20 20 20 40 20 3c 2f 73 70 61 6e          @ </span
4cb0: 3e 3c 2f 70 3e 0a 20 20 20 20 20 20 20 20 3b 0a  ></p>.        ;.
4cc0: 20 20 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20        }else{.   
4cd0: 20 20 20 20 20 63 68 61 72 20 2a 7a 4e 65 77 50       char *zNewP
4ce0: 77 20 3d 20 73 68 61 31 5f 73 68 61 72 65 64 5f  w = sha1_shared_
4cf0: 73 65 63 72 65 74 28 7a 4e 65 77 31 2c 20 67 2e  secret(zNew1, g.
4d00: 7a 4c 6f 67 69 6e 2c 20 30 29 3b 0a 20 20 20 20  zLogin, 0);.    
4d10: 20 20 20 20 63 68 61 72 20 2a 7a 43 68 6e 67 50      char *zChngP
4d20: 77 3b 0a 20 20 20 20 20 20 20 20 63 68 61 72 20  w;.        char 
4d30: 2a 7a 45 72 72 3b 0a 20 20 20 20 20 20 20 20 64  *zErr;.        d
4d40: 62 5f 6d 75 6c 74 69 5f 65 78 65 63 28 0a 20 20  b_multi_exec(.  
4d50: 20 20 20 20 20 20 20 20 20 22 55 50 44 41 54 45           "UPDATE
4d60: 20 75 73 65 72 20 53 45 54 20 70 77 3d 25 51 20   user SET pw=%Q 
4d70: 57 48 45 52 45 20 75 69 64 3d 25 64 22 2c 20 7a  WHERE uid=%d", z
4d80: 4e 65 77 50 77 2c 20 67 2e 75 73 65 72 55 69 64  NewPw, g.userUid
4d90: 0a 20 20 20 20 20 20 20 20 29 3b 0a 20 20 20 20  .        );.    
4da0: 20 20 20 20 66 6f 73 73 69 6c 5f 66 72 65 65 28      fossil_free(
4db0: 7a 4e 65 77 50 77 29 3b 0a 20 20 20 20 20 20 20  zNewPw);.       
4dc0: 20 7a 43 68 6e 67 50 77 20 3d 20 6d 70 72 69 6e   zChngPw = mprin
4dd0: 74 66 28 0a 20 20 20 20 20 20 20 20 20 20 20 22  tf(.           "
4de0: 55 50 44 41 54 45 20 75 73 65 72 22 0a 20 20 20  UPDATE user".   
4df0: 20 20 20 20 20 20 20 20 22 20 20 20 53 45 54 20          "   SET 
4e00: 70 77 3d 73 68 61 72 65 64 5f 73 65 63 72 65 74  pw=shared_secret
4e10: 28 25 51 2c 25 51 2c 22 0a 20 20 20 20 20 20 20  (%Q,%Q,".       
4e20: 20 20 20 20 22 20 20 20 20 20 20 20 20 28 53 45      "        (SE
4e30: 4c 45 43 54 20 76 61 6c 75 65 20 46 52 4f 4d 20  LECT value FROM 
4e40: 63 6f 6e 66 69 67 20 57 48 45 52 45 20 6e 61 6d  config WHERE nam
4e50: 65 3d 27 70 72 6f 6a 65 63 74 2d 63 6f 64 65 27  e='project-code'
4e60: 29 29 22 0a 20 20 20 20 20 20 20 20 20 20 20 22  ))".           "
4e70: 20 57 48 45 52 45 20 6c 6f 67 69 6e 3d 25 51 22   WHERE login=%Q"
4e80: 2c 0a 20 20 20 20 20 20 20 20 20 20 20 7a 4e 65  ,.           zNe
4e90: 77 31 2c 20 67 2e 7a 4c 6f 67 69 6e 2c 20 67 2e  w1, g.zLogin, g.
4ea0: 7a 4c 6f 67 69 6e 0a 20 20 20 20 20 20 20 20 29  zLogin.        )
4eb0: 3b 0a 20 20 20 20 20 20 20 20 69 66 28 20 6c 6f  ;.        if( lo
4ec0: 67 69 6e 5f 67 72 6f 75 70 5f 73 71 6c 28 7a 43  gin_group_sql(zC
4ed0: 68 6e 67 50 77 2c 20 22 3c 70 3e 22 2c 20 22 3c  hngPw, "<p>", "<
4ee0: 2f 70 3e 5c 6e 22 2c 20 26 7a 45 72 72 29 20 29  /p>\n", &zErr) )
4ef0: 7b 0a 20 20 20 20 20 20 20 20 20 20 7a 45 72 72  {.          zErr
4f00: 4d 73 67 20 3d 20 6d 70 72 69 6e 74 66 28 22 3c  Msg = mprintf("<
4f10: 73 70 61 6e 20 63 6c 61 73 73 3d 5c 22 6c 6f 67  span class=\"log
4f20: 69 6e 45 72 72 6f 72 5c 22 3e 25 73 3c 2f 73 70  inError\">%s</sp
4f30: 61 6e 3e 22 2c 20 7a 45 72 72 29 3b 0a 20 20 20  an>", zErr);.   
4f40: 20 20 20 20 20 20 20 66 6f 73 73 69 6c 5f 66 72         fossil_fr
4f50: 65 65 28 7a 45 72 72 29 3b 0a 20 20 20 20 20 20  ee(zErr);.      
4f60: 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 20    }else{.       
4f70: 20 20 20 72 65 64 69 72 65 63 74 5f 74 6f 5f 67     redirect_to_g
4f80: 28 29 3b 0a 20 20 20 20 20 20 20 20 20 20 72 65  ();.          re
4f90: 74 75 72 6e 3b 0a 20 20 20 20 20 20 20 20 7d 0a  turn;.        }.
4fa0: 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 65 6c 73        }.    }els
4fb0: 65 7b 0a 20 20 20 20 20 20 7a 45 72 72 4d 73 67  e{.      zErrMsg
4fc0: 20 3d 0a 20 20 20 20 20 20 20 20 20 40 20 3c 70   =.         @ <p
4fd0: 3e 3c 73 70 61 6e 20 63 6c 61 73 73 3d 22 6c 6f  ><span class="lo
4fe0: 67 69 6e 45 72 72 6f 72 22 3e 0a 20 20 20 20 20  ginError">.     
4ff0: 20 20 20 20 40 20 54 68 65 20 70 61 73 73 77 6f      @ The passwo
5000: 72 64 20 63 61 6e 6e 6f 74 20 62 65 20 63 68 61  rd cannot be cha
5010: 6e 67 65 64 20 66 6f 72 20 74 68 69 73 20 74 79  nged for this ty
5020: 70 65 20 6f 66 20 6c 6f 67 69 6e 2e 0a 20 20 20  pe of login..   
5030: 20 20 20 20 20 20 40 20 54 68 65 20 70 61 73 73        @ The pass
5040: 77 6f 72 64 20 69 73 20 75 6e 63 68 61 6e 67 65  word is unchange
5050: 64 2e 0a 20 20 20 20 20 20 20 20 20 40 20 3c 2f  d..         @ </
5060: 73 70 61 6e 3e 3c 2f 70 3e 0a 20 20 20 20 20 20  span></p>.      
5070: 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20 7a 49  ;.    }.  }.  zI
5080: 70 41 64 64 72 20 3d 20 50 44 28 22 52 45 4d 4f  pAddr = PD("REMO
5090: 54 45 5f 41 44 44 52 22 2c 22 6e 69 6c 22 29 3b  TE_ADDR","nil");
50a0: 20 20 20 2f 2a 20 43 6f 6d 70 6c 65 74 65 20 49     /* Complete I
50b0: 50 20 61 64 64 72 65 73 73 20 66 6f 72 20 6c 6f  P address for lo
50c0: 67 67 69 6e 67 20 2a 2f 0a 20 20 7a 52 65 66 65  gging */.  zRefe
50d0: 72 65 72 20 3d 20 50 28 22 48 54 54 50 5f 52 45  rer = P("HTTP_RE
50e0: 46 45 52 45 52 22 29 3b 0a 20 20 75 69 64 20 3d  FERER");.  uid =
50f0: 20 6c 6f 67 69 6e 5f 69 73 5f 76 61 6c 69 64 5f   login_is_valid_
5100: 61 6e 6f 6e 79 6d 6f 75 73 28 7a 55 73 65 72 6e  anonymous(zUsern
5110: 61 6d 65 2c 20 7a 50 61 73 73 77 64 2c 20 50 28  ame, zPasswd, P(
5120: 22 63 73 22 29 29 3b 0a 20 20 69 66 28 20 75 69  "cs"));.  if( ui
5130: 64 3e 30 20 29 7b 0a 20 20 20 20 6c 6f 67 69 6e  d>0 ){.    login
5140: 5f 73 65 74 5f 61 6e 6f 6e 5f 63 6f 6f 6b 69 65  _set_anon_cookie
5150: 28 7a 49 70 41 64 64 72 2c 20 4e 55 4c 4c 29 3b  (zIpAddr, NULL);
5160: 0a 20 20 20 20 72 65 63 6f 72 64 5f 6c 6f 67 69  .    record_logi
5170: 6e 5f 61 74 74 65 6d 70 74 28 22 61 6e 6f 6e 79  n_attempt("anony
5180: 6d 6f 75 73 22 2c 20 7a 49 70 41 64 64 72 2c 20  mous", zIpAddr, 
5190: 31 29 3b 0a 20 20 20 20 72 65 64 69 72 65 63 74  1);.    redirect
51a0: 5f 74 6f 5f 67 28 29 3b 0a 20 20 7d 0a 20 20 69  _to_g();.  }.  i
51b0: 66 28 20 7a 55 73 65 72 6e 61 6d 65 21 3d 30 20  f( zUsername!=0 
51c0: 26 26 20 7a 50 61 73 73 77 64 21 3d 30 20 26 26  && zPasswd!=0 &&
51d0: 20 7a 50 61 73 73 77 64 5b 30 5d 21 3d 30 20 29   zPasswd[0]!=0 )
51e0: 7b 0a 20 20 20 20 2f 2a 20 41 74 74 65 6d 70 74  {.    /* Attempt
51f0: 69 6e 67 20 74 6f 20 6c 6f 67 20 69 6e 20 61 73  ing to log in as
5200: 20 61 20 75 73 65 72 20 6f 74 68 65 72 20 74 68   a user other th
5210: 61 6e 20 61 6e 6f 6e 79 6d 6f 75 73 2e 0a 20 20  an anonymous..  
5220: 20 20 2a 2f 0a 20 20 20 20 75 69 64 20 3d 20 6c    */.    uid = l
5230: 6f 67 69 6e 5f 73 65 61 72 63 68 5f 75 69 64 28  ogin_search_uid(
5240: 26 7a 55 73 65 72 6e 61 6d 65 2c 20 7a 50 61 73  &zUsername, zPas
5250: 73 77 64 29 3b 0a 20 20 20 20 69 66 28 20 75 69  swd);.    if( ui
5260: 64 3c 3d 30 20 29 7b 0a 20 20 20 20 20 20 73 6c  d<=0 ){.      sl
5270: 65 65 70 28 31 29 3b 0a 20 20 20 20 20 20 7a 45  eep(1);.      zE
5280: 72 72 4d 73 67 20 3d 0a 20 20 20 20 20 20 20 20  rrMsg =.        
5290: 20 40 20 3c 70 3e 3c 73 70 61 6e 20 63 6c 61 73   @ <p><span clas
52a0: 73 3d 22 6c 6f 67 69 6e 45 72 72 6f 72 22 3e 0a  s="loginError">.
52b0: 20 20 20 20 20 20 20 20 20 40 20 59 6f 75 20 65           @ You e
52c0: 6e 74 65 72 65 64 20 61 6e 20 75 6e 6b 6e 6f 77  ntered an unknow
52d0: 6e 20 75 73 65 72 20 6f 72 20 61 6e 20 69 6e 63  n user or an inc
52e0: 6f 72 72 65 63 74 20 70 61 73 73 77 6f 72 64 2e  orrect password.
52f0: 0a 20 20 20 20 20 20 20 20 20 40 20 3c 2f 73 70  .         @ </sp
5300: 61 6e 3e 3c 2f 70 3e 0a 20 20 20 20 20 20 3b 0a  an></p>.      ;.
5310: 20 20 20 20 20 20 72 65 63 6f 72 64 5f 6c 6f 67        record_log
5320: 69 6e 5f 61 74 74 65 6d 70 74 28 7a 55 73 65 72  in_attempt(zUser
5330: 6e 61 6d 65 2c 20 7a 49 70 41 64 64 72 2c 20 30  name, zIpAddr, 0
5340: 29 3b 0a 20 20 20 20 7d 65 6c 73 65 7b 0a 20 20  );.    }else{.  
5350: 20 20 20 20 2f 2a 20 4e 6f 6e 2d 61 6e 6f 6e 79      /* Non-anony
5360: 6d 6f 75 73 20 6c 6f 67 69 6e 20 69 73 20 73 75  mous login is su
5370: 63 63 65 73 73 66 75 6c 2e 20 20 53 65 74 20 61  ccessful.  Set a
5380: 20 63 6f 6f 6b 69 65 20 6f 66 20 74 68 65 20 66   cookie of the f
5390: 6f 72 6d 3a 0a 20 20 20 20 20 20 2a 2a 0a 20 20  orm:.      **.  
53a0: 20 20 20 20 2a 2a 20 20 20 20 48 41 53 48 2f 50      **    HASH/P
53b0: 52 4f 4a 45 43 54 2f 4c 4f 47 49 4e 0a 20 20 20  ROJECT/LOGIN.   
53c0: 20 20 20 2a 2a 0a 20 20 20 20 20 20 2a 2a 20 77     **.      ** w
53d0: 68 65 72 65 20 48 41 53 48 20 69 73 20 61 20 72  here HASH is a r
53e0: 61 6e 64 6f 6d 20 68 65 78 20 6e 75 6d 62 65 72  andom hex number
53f0: 2c 20 50 52 4f 4a 45 43 54 20 69 73 20 65 69 74  , PROJECT is eit
5400: 68 65 72 20 70 72 6f 6a 65 63 74 0a 20 20 20 20  her project.    
5410: 20 20 2a 2a 20 63 6f 64 65 20 70 72 65 66 69 78    ** code prefix
5420: 2c 20 61 6e 64 20 4c 4f 47 49 4e 20 69 73 20 74  , and LOGIN is t
5430: 68 65 20 75 73 65 72 20 6e 61 6d 65 2e 0a 20 20  he user name..  
5440: 20 20 20 20 2a 2f 0a 20 20 20 20 20 20 6c 6f 67      */.      log
5450: 69 6e 5f 73 65 74 5f 75 73 65 72 5f 63 6f 6f 6b  in_set_user_cook
5460: 69 65 28 7a 55 73 65 72 6e 61 6d 65 2c 20 75 69  ie(zUsername, ui
5470: 64 2c 20 4e 55 4c 4c 29 3b 0a 20 20 20 20 20 20  d, NULL);.      
5480: 72 65 64 69 72 65 63 74 5f 74 6f 5f 67 28 29 3b  redirect_to_g();
5490: 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20 73 74 79  .    }.  }.  sty
54a0: 6c 65 5f 68 65 61 64 65 72 28 22 4c 6f 67 69 6e  le_header("Login
54b0: 2f 4c 6f 67 6f 75 74 22 29 3b 0a 20 20 73 74 79  /Logout");.  sty
54c0: 6c 65 5f 61 64 75 6e 69 74 5f 63 6f 6e 66 69 67  le_adunit_config
54d0: 28 41 44 55 4e 49 54 5f 4f 46 46 29 3b 0a 20 20  (ADUNIT_OFF);.  
54e0: 40 20 25 73 28 7a 45 72 72 4d 73 67 29 0a 20 20  @ %s(zErrMsg).  
54f0: 69 66 28 20 7a 47 6f 74 6f 20 26 26 20 21 6e 6f  if( zGoto && !no
5500: 41 6e 6f 6e 20 29 7b 0a 20 20 20 20 63 68 61 72  Anon ){.    char
5510: 20 2a 7a 41 62 62 72 65 76 20 3d 20 66 6f 73 73   *zAbbrev = foss
5520: 69 6c 5f 73 74 72 64 75 70 28 7a 47 6f 74 6f 29  il_strdup(zGoto)
5530: 3b 0a 20 20 20 20 69 6e 74 20 69 3b 0a 20 20 20  ;.    int i;.   
5540: 20 66 6f 72 28 69 3d 30 3b 20 7a 41 62 62 72 65   for(i=0; zAbbre
5550: 76 5b 69 5d 20 26 26 20 7a 41 62 62 72 65 76 5b  v[i] && zAbbrev[
5560: 69 5d 21 3d 27 3f 27 3b 20 69 2b 2b 29 7b 7d 0a  i]!='?'; i++){}.
5570: 20 20 20 20 7a 41 62 62 72 65 76 5b 69 5d 20 3d      zAbbrev[i] =
5580: 20 30 3b 0a 20 20 20 20 69 66 28 20 67 2e 7a 4c   0;.    if( g.zL
5590: 6f 67 69 6e 20 29 7b 0a 20 20 20 20 20 20 40 20  ogin ){.      @ 
55a0: 3c 70 3e 55 73 65 20 61 20 64 69 66 66 65 72 65  <p>Use a differe
55b0: 6e 74 20 6c 6f 67 69 6e 20 77 69 74 68 20 67 72  nt login with gr
55c0: 65 61 74 65 72 20 70 72 69 76 69 6c 65 67 65 20  eater privilege 
55d0: 74 68 61 6e 20 3c 62 3e 25 68 28 67 2e 7a 4c 6f  than <b>%h(g.zLo
55e0: 67 69 6e 29 3c 2f 62 3e 0a 20 20 20 20 20 20 40  gin)</b>.      @
55f0: 20 74 6f 20 61 63 63 65 73 73 20 3c 62 3e 25 68   to access <b>%h
5600: 28 7a 41 62 62 72 65 76 29 3c 2f 62 3e 2e 0a 20  (zAbbrev)</b>.. 
5610: 20 20 20 7d 65 6c 73 65 20 69 66 28 20 61 6e 6f     }else if( ano
5620: 6e 46 6c 61 67 20 29 7b 0a 20 20 20 20 20 20 40  nFlag ){.      @
5630: 20 3c 70 3e 4c 6f 67 69 6e 20 61 73 20 3c 62 3e   <p>Login as <b>
5640: 61 6e 6f 6e 79 6d 6f 75 73 3c 2f 62 3e 20 6f 72  anonymous</b> or
5650: 20 61 6e 79 20 6e 61 6d 65 64 20 75 73 65 72 0a   any named user.
5660: 20 20 20 20 20 20 40 20 74 6f 20 61 63 63 65 73        @ to acces
5670: 73 20 70 61 67 65 20 3c 62 3e 25 68 28 7a 41 62  s page <b>%h(zAb
5680: 62 72 65 76 29 3c 2f 62 3e 2e 0a 20 20 20 20 7d  brev)</b>..    }
5690: 65 6c 73 65 7b 0a 20 20 20 20 20 20 40 20 3c 70  else{.      @ <p
56a0: 3e 4c 6f 67 69 6e 20 61 73 20 61 20 6e 61 6d 65  >Login as a name
56b0: 64 20 75 73 65 72 20 74 6f 20 61 63 63 65 73 73  d user to access
56c0: 20 70 61 67 65 20 3c 62 3e 25 68 28 7a 41 62 62   page <b>%h(zAbb
56d0: 72 65 76 29 3c 2f 62 3e 2e 0a 20 20 20 20 7d 0a  rev)</b>..    }.
56e0: 20 20 7d 0a 20 20 69 66 28 20 67 2e 73 73 6c 4e    }.  if( g.sslN
56f0: 6f 74 41 76 61 69 6c 61 62 6c 65 3d 3d 30 0a 20  otAvailable==0. 
5700: 20 20 26 26 20 73 74 72 6e 63 6d 70 28 67 2e 7a    && strncmp(g.z
5710: 42 61 73 65 55 52 4c 2c 22 68 74 74 70 73 3a 22  BaseURL,"https:"
5720: 2c 36 29 21 3d 30 0a 20 20 20 26 26 20 64 62 5f  ,6)!=0.   && db_
5730: 67 65 74 5f 62 6f 6f 6c 65 61 6e 28 22 68 74 74  get_boolean("htt
5740: 70 73 2d 6c 6f 67 69 6e 22 2c 30 29 0a 20 20 29  ps-login",0).  )
5750: 7b 0a 20 20 20 20 66 6f 72 6d 5f 62 65 67 69 6e  {.    form_begin
5760: 28 30 2c 20 22 68 74 74 70 73 3a 25 73 2f 6c 6f  (0, "https:%s/lo
5770: 67 69 6e 22 2c 20 67 2e 7a 42 61 73 65 55 52 4c  gin", g.zBaseURL
5780: 2b 35 29 3b 0a 20 20 7d 65 6c 73 65 7b 0a 20 20  +5);.  }else{.  
5790: 20 20 66 6f 72 6d 5f 62 65 67 69 6e 28 30 2c 20    form_begin(0, 
57a0: 22 25 52 2f 6c 6f 67 69 6e 22 29 3b 0a 20 20 7d  "%R/login");.  }
57b0: 0a 20 20 69 66 28 20 7a 47 6f 74 6f 20 29 7b 0a  .  if( zGoto ){.
57c0: 20 20 20 20 40 20 3c 69 6e 70 75 74 20 74 79 70      @ <input typ
57d0: 65 3d 22 68 69 64 64 65 6e 22 20 6e 61 6d 65 3d  e="hidden" name=
57e0: 22 67 22 20 76 61 6c 75 65 3d 22 25 68 28 7a 47  "g" value="%h(zG
57f0: 6f 74 6f 29 22 20 2f 3e 0a 20 20 7d 65 6c 73 65  oto)" />.  }else
5800: 20 69 66 28 20 7a 52 65 66 65 72 65 72 20 26 26   if( zReferer &&
5810: 20 73 74 72 6e 63 6d 70 28 67 2e 7a 42 61 73 65   strncmp(g.zBase
5820: 55 52 4c 2c 20 7a 52 65 66 65 72 65 72 2c 20 73  URL, zReferer, s
5830: 74 72 6c 65 6e 28 67 2e 7a 42 61 73 65 55 52 4c  trlen(g.zBaseURL
5840: 29 29 3d 3d 30 20 29 7b 0a 20 20 20 20 40 20 3c  ))==0 ){.    @ <
5850: 69 6e 70 75 74 20 74 79 70 65 3d 22 68 69 64 64  input type="hidd
5860: 65 6e 22 20 6e 61 6d 65 3d 22 67 22 20 76 61 6c  en" name="g" val
5870: 75 65 3d 22 25 68 28 7a 52 65 66 65 72 65 72 29  ue="%h(zReferer)
5880: 22 20 2f 3e 0a 20 20 7d 0a 20 20 69 66 28 20 61  " />.  }.  if( a
5890: 6e 6f 6e 46 6c 61 67 20 29 7b 0a 20 20 20 20 40  nonFlag ){.    @
58a0: 20 3c 69 6e 70 75 74 20 74 79 70 65 3d 22 68 69   <input type="hi
58b0: 64 64 65 6e 22 20 6e 61 6d 65 3d 22 61 6e 6f 6e  dden" name="anon
58c0: 22 20 76 61 6c 75 65 3d 22 31 22 20 2f 3e 0a 20  " value="1" />. 
58d0: 20 7d 0a 20 20 69 66 28 20 67 2e 7a 4c 6f 67 69   }.  if( g.zLogi
58e0: 6e 20 29 7b 0a 20 20 20 20 40 20 3c 70 3e 43 75  n ){.    @ <p>Cu
58f0: 72 72 65 6e 74 6c 79 20 6c 6f 67 67 65 64 20 69  rrently logged i
5900: 6e 20 61 73 20 3c 62 3e 25 68 28 67 2e 7a 4c 6f  n as <b>%h(g.zLo
5910: 67 69 6e 29 3c 2f 62 3e 2e 0a 20 20 20 20 40 20  gin)</b>..    @ 
5920: 3c 69 6e 70 75 74 20 74 79 70 65 3d 22 73 75 62  <input type="sub
5930: 6d 69 74 22 20 6e 61 6d 65 3d 22 6f 75 74 22 20  mit" name="out" 
5940: 76 61 6c 75 65 3d 22 4c 6f 67 6f 75 74 22 3e 3c  value="Logout"><
5950: 2f 70 3e 0a 20 20 20 20 40 20 3c 2f 66 6f 72 6d  /p>.    @ </form
5960: 3e 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 40  >.  }else{.    @
5970: 20 3c 74 61 62 6c 65 20 63 6c 61 73 73 3d 22 6c   <table class="l
5980: 6f 67 69 6e 5f 6f 75 74 22 3e 0a 20 20 20 20 40  ogin_out">.    @
5990: 20 3c 74 72 3e 0a 20 20 20 20 40 20 20 20 3c 74   <tr>.    @   <t
59a0: 64 20 63 6c 61 73 73 3d 22 66 6f 72 6d 5f 6c 61  d class="form_la
59b0: 62 65 6c 22 3e 55 73 65 72 20 49 44 3a 3c 2f 74  bel">User ID:</t
59c0: 64 3e 0a 20 20 20 20 69 66 28 20 61 6e 6f 6e 46  d>.    if( anonF
59d0: 6c 61 67 20 29 7b 0a 20 20 20 20 20 20 40 20 3c  lag ){.      @ <
59e0: 74 64 3e 3c 69 6e 70 75 74 20 74 79 70 65 3d 22  td><input type="
59f0: 74 65 78 74 22 20 69 64 3d 22 75 22 20 6e 61 6d  text" id="u" nam
5a00: 65 3d 22 75 22 20 76 61 6c 75 65 3d 22 61 6e 6f  e="u" value="ano
5a10: 6e 79 6d 6f 75 73 22 20 73 69 7a 65 3d 22 33 30  nymous" size="30
5a20: 22 3e 3c 2f 74 64 3e 0a 20 20 20 20 7d 65 6c 73  "></td>.    }els
5a30: 65 7b 0a 20 20 20 20 20 20 40 20 3c 74 64 3e 3c  e{.      @ <td><
5a40: 69 6e 70 75 74 20 74 79 70 65 3d 22 74 65 78 74  input type="text
5a50: 22 20 69 64 3d 22 75 22 20 6e 61 6d 65 3d 22 75  " id="u" name="u
5a60: 22 20 76 61 6c 75 65 3d 22 22 20 73 69 7a 65 3d  " value="" size=
5a70: 22 33 30 22 20 2f 3e 3c 2f 74 64 3e 0a 20 20 20  "30" /></td>.   
5a80: 20 7d 0a 20 20 20 20 40 20 3c 2f 74 72 3e 0a 20   }.    @ </tr>. 
5a90: 20 20 20 40 20 3c 74 72 3e 0a 20 20 20 20 40 20     @ <tr>.    @ 
5aa0: 20 3c 74 64 20 63 6c 61 73 73 3d 22 66 6f 72 6d   <td class="form
5ab0: 5f 6c 61 62 65 6c 22 3e 50 61 73 73 77 6f 72 64  _label">Password
5ac0: 3a 3c 2f 74 64 3e 0a 20 20 20 20 40 20 20 3c 74  :</td>.    @  <t
5ad0: 64 3e 3c 69 6e 70 75 74 20 74 79 70 65 3d 22 70  d><input type="p
5ae0: 61 73 73 77 6f 72 64 22 20 69 64 3d 22 70 22 20  assword" id="p" 
5af0: 6e 61 6d 65 3d 22 70 22 20 76 61 6c 75 65 3d 22  name="p" value="
5b00: 22 20 73 69 7a 65 3d 22 33 30 22 20 2f 3e 3c 2f  " size="30" /></
5b10: 74 64 3e 0a 20 20 20 20 40 20 3c 2f 74 72 3e 0a  td>.    @ </tr>.
5b20: 20 20 20 20 69 66 28 20 50 28 22 48 54 54 50 53      if( P("HTTPS
5b30: 22 29 3d 3d 30 20 29 7b 0a 20 20 20 20 20 20 40  ")==0 ){.      @
5b40: 20 3c 74 72 3e 3c 74 64 20 63 6c 61 73 73 3d 22   <tr><td class="
5b50: 66 6f 72 6d 5f 6c 61 62 65 6c 22 3e 57 61 72 6e  form_label">Warn
5b60: 69 6e 67 3a 3c 2f 74 64 3e 0a 20 20 20 20 20 20  ing:</td>.      
5b70: 40 20 3c 74 64 3e 3c 73 70 61 6e 20 63 6c 61 73  @ <td><span clas
5b80: 73 3d 27 73 65 63 75 72 69 74 79 57 61 72 6e 69  s='securityWarni
5b90: 6e 67 27 3e 0a 20 20 20 20 20 20 40 20 59 6f 75  ng'>.      @ You
5ba0: 72 20 70 61 73 73 77 6f 72 64 20 77 69 6c 6c 20  r password will 
5bb0: 62 65 20 73 65 6e 74 20 69 6e 20 74 68 65 20 63  be sent in the c
5bc0: 6c 65 61 72 20 6f 76 65 72 20 61 6e 0a 20 20 20  lear over an.   
5bd0: 20 20 20 40 20 75 6e 65 6e 63 72 79 70 74 65 64     @ unencrypted
5be0: 20 63 6f 6e 6e 65 63 74 69 6f 6e 2e 0a 20 20 20   connection..   
5bf0: 20 20 20 69 66 28 20 67 2e 73 73 6c 4e 6f 74 41     if( g.sslNotA
5c00: 76 61 69 6c 61 62 6c 65 20 29 7b 0a 20 20 20 20  vailable ){.    
5c10: 20 20 20 20 40 20 4e 6f 20 65 6e 63 72 79 70 74      @ No encrypt
5c20: 65 64 20 63 6f 6e 6e 65 63 74 69 6f 6e 20 69 73  ed connection is
5c30: 20 61 76 61 69 6c 61 62 6c 65 20 6f 6e 20 74 68   available on th
5c40: 69 73 20 73 65 72 76 65 72 2e 0a 20 20 20 20 20  is server..     
5c50: 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 20 20   }else{.        
5c60: 40 20 43 6f 6e 73 69 64 65 72 20 6c 6f 67 67 69  @ Consider loggi
5c70: 6e 67 20 69 6e 20 61 74 0a 20 20 20 20 20 20 20  ng in at.       
5c80: 20 40 20 3c 61 20 68 72 65 66 3d 27 25 73 28 67   @ <a href='%s(g
5c90: 2e 7a 48 74 74 70 73 55 52 4c 29 27 3e 25 68 28  .zHttpsURL)'>%h(
5ca0: 67 2e 7a 48 74 74 70 73 55 52 4c 29 3c 2f 61 3e  g.zHttpsURL)</a>
5cb0: 20 69 6e 73 74 65 61 64 2e 0a 20 20 20 20 20 20   instead..      
5cc0: 7d 0a 20 20 20 20 20 20 40 20 3c 2f 73 70 61 6e  }.      @ </span
5cd0: 3e 3c 2f 74 64 3e 3c 2f 74 72 3e 0a 20 20 20 20  ></td></tr>.    
5ce0: 7d 0a 20 20 20 20 69 66 28 20 67 2e 7a 4c 6f 67  }.    if( g.zLog
5cf0: 69 6e 3d 3d 30 20 26 26 20 28 61 6e 6f 6e 46 6c  in==0 && (anonFl
5d00: 61 67 20 7c 7c 20 7a 47 6f 74 6f 3d 3d 30 29 20  ag || zGoto==0) 
5d10: 29 7b 0a 20 20 20 20 20 20 7a 41 6e 6f 6e 50 77  ){.      zAnonPw
5d20: 20 3d 20 64 62 5f 74 65 78 74 28 30 2c 20 22 53   = db_text(0, "S
5d30: 45 4c 45 43 54 20 70 77 20 46 52 4f 4d 20 75 73  ELECT pw FROM us
5d40: 65 72 22 0a 20 20 20 20 20 20 20 20 20 20 20 20  er".            
5d50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 22                 "
5d60: 20 57 48 45 52 45 20 6c 6f 67 69 6e 3d 27 61 6e   WHERE login='an
5d70: 6f 6e 79 6d 6f 75 73 27 22 0a 20 20 20 20 20 20  onymous'".      
5d80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
5d90: 20 20 20 20 20 22 20 20 20 41 4e 44 20 63 61 70       "   AND cap
5da0: 21 3d 27 27 22 29 3b 0a 20 20 20 20 7d 0a 20 20  !=''");.    }.  
5db0: 20 20 40 20 3c 74 72 3e 0a 20 20 20 20 40 20 20    @ <tr>.    @  
5dc0: 20 3c 74 64 3e 3c 2f 74 64 3e 0a 20 20 20 20 40   <td></td>.    @
5dd0: 20 20 20 3c 74 64 3e 3c 69 6e 70 75 74 20 74 79     <td><input ty
5de0: 70 65 3d 22 73 75 62 6d 69 74 22 20 6e 61 6d 65  pe="submit" name
5df0: 3d 22 69 6e 22 20 76 61 6c 75 65 3d 22 4c 6f 67  ="in" value="Log
5e00: 69 6e 22 3e 3c 2f 74 64 3e 0a 20 20 20 20 40 20  in"></td>.    @ 
5e10: 3c 2f 74 72 3e 0a 20 20 20 20 69 66 28 20 21 6e  </tr>.    if( !n
5e20: 6f 41 6e 6f 6e 20 26 26 20 6c 6f 67 69 6e 5f 73  oAnon && login_s
5e30: 65 6c 66 5f 72 65 67 69 73 74 65 72 5f 61 76 61  elf_register_ava
5e40: 69 6c 61 62 6c 65 28 30 29 20 29 7b 0a 20 20 20  ilable(0) ){.   
5e50: 20 20 20 40 20 3c 74 72 3e 0a 20 20 20 20 20 20     @ <tr>.      
5e60: 40 20 20 20 3c 74 64 3e 3c 2f 74 64 3e 0a 20 20  @   <td></td>.  
5e70: 20 20 20 20 40 20 20 20 3c 74 64 3e 3c 69 6e 70      @   <td><inp
5e80: 75 74 20 74 79 70 65 3d 22 73 75 62 6d 69 74 22  ut type="submit"
5e90: 20 6e 61 6d 65 3d 22 73 65 6c 66 22 20 76 61 6c   name="self" val
5ea0: 75 65 3d 22 43 72 65 61 74 65 20 41 20 4e 65 77  ue="Create A New
5eb0: 20 41 63 63 6f 75 6e 74 22 3e 0a 20 20 20 20 20   Account">.     
5ec0: 20 40 20 3c 2f 74 72 3e 0a 20 20 20 20 7d 0a 20   @ </tr>.    }. 
5ed0: 20 20 20 40 20 3c 2f 74 61 62 6c 65 3e 0a 20 20     @ </table>.  
5ee0: 20 20 69 66 28 20 7a 41 6e 6f 6e 50 77 20 26 26    if( zAnonPw &&
5ef0: 20 21 6e 6f 41 6e 6f 6e 20 29 7b 0a 20 20 20 20   !noAnon ){.    
5f00: 20 20 75 6e 73 69 67 6e 65 64 20 69 6e 74 20 75    unsigned int u
5f10: 53 65 65 64 20 3d 20 63 61 70 74 63 68 61 5f 73  Seed = captcha_s
5f20: 65 65 64 28 29 3b 0a 20 20 20 20 20 20 63 6f 6e  eed();.      con
5f30: 73 74 20 63 68 61 72 20 2a 7a 44 65 63 6f 64 65  st char *zDecode
5f40: 64 20 3d 20 63 61 70 74 63 68 61 5f 64 65 63 6f  d = captcha_deco
5f50: 64 65 28 75 53 65 65 64 29 3b 0a 20 20 20 20 20  de(uSeed);.     
5f60: 20 69 6e 74 20 62 41 75 74 6f 43 61 70 74 63 68   int bAutoCaptch
5f70: 61 20 3d 20 64 62 5f 67 65 74 5f 62 6f 6f 6c 65  a = db_get_boole
5f80: 61 6e 28 22 61 75 74 6f 2d 63 61 70 74 63 68 61  an("auto-captcha
5f90: 22 2c 20 30 29 3b 0a 20 20 20 20 20 20 63 68 61  ", 0);.      cha
5fa0: 72 20 2a 7a 43 61 70 74 63 68 61 20 3d 20 63 61  r *zCaptcha = ca
5fb0: 70 74 63 68 61 5f 72 65 6e 64 65 72 28 7a 44 65  ptcha_render(zDe
5fc0: 63 6f 64 65 64 29 3b 0a 20 20 0a 20 20 20 20 20  coded);.  .     
5fd0: 20 40 20 3c 70 3e 3c 69 6e 70 75 74 20 74 79 70   @ <p><input typ
5fe0: 65 3d 22 68 69 64 64 65 6e 22 20 6e 61 6d 65 3d  e="hidden" name=
5ff0: 22 63 73 22 20 76 61 6c 75 65 3d 22 25 75 28 75  "cs" value="%u(u
6000: 53 65 65 64 29 22 20 2f 3e 0a 20 20 20 20 20 20  Seed)" />.      
6010: 40 20 56 69 73 69 74 6f 72 73 20 6d 61 79 20 65  @ Visitors may e
6020: 6e 74 65 72 20 3c 62 3e 61 6e 6f 6e 79 6d 6f 75  nter <b>anonymou
6030: 73 3c 2f 62 3e 20 61 73 20 74 68 65 20 75 73 65  s</b> as the use
6040: 72 2d 49 44 20 77 69 74 68 0a 20 20 20 20 20 20  r-ID with.      
6050: 40 20 74 68 65 20 38 2d 63 68 61 72 61 63 74 65  @ the 8-characte
6060: 72 20 68 65 78 61 64 65 63 69 6d 61 6c 20 70 61  r hexadecimal pa
6070: 73 73 77 6f 72 64 20 73 68 6f 77 6e 20 62 65 6c  ssword shown bel
6080: 6f 77 3a 3c 2f 70 3e 0a 20 20 20 20 20 20 40 20  ow:</p>.      @ 
6090: 3c 64 69 76 20 63 6c 61 73 73 3d 22 63 61 70 74  <div class="capt
60a0: 63 68 61 22 3e 3c 74 61 62 6c 65 20 63 6c 61 73  cha"><table clas
60b0: 73 3d 22 63 61 70 74 63 68 61 22 3e 3c 74 72 3e  s="captcha"><tr>
60c0: 3c 74 64 3e 5c 0a 20 20 20 20 20 20 40 20 3c 70  <td>\.      @ <p
60d0: 72 65 20 63 6c 61 73 73 3d 22 63 61 70 74 63 68  re class="captch
60e0: 61 22 3e 0a 20 20 20 20 20 20 40 20 25 68 28 7a  a">.      @ %h(z
60f0: 43 61 70 74 63 68 61 29 0a 20 20 20 20 20 20 40  Captcha).      @
6100: 20 3c 2f 70 72 65 3e 3c 2f 74 64 3e 3c 2f 74 72   </pre></td></tr
6110: 3e 3c 2f 74 61 62 6c 65 3e 0a 20 20 20 20 20 20  ></table>.      
6120: 69 66 28 20 62 41 75 74 6f 43 61 70 74 63 68 61  if( bAutoCaptcha
6130: 20 29 20 7b 0a 20 20 20 20 20 20 20 20 20 40 20   ) {.         @ 
6140: 3c 69 6e 70 75 74 20 74 79 70 65 3d 22 62 75 74  <input type="but
6150: 74 6f 6e 22 20 76 61 6c 75 65 3d 22 46 69 6c 6c  ton" value="Fill
6160: 20 6f 75 74 20 63 61 70 74 63 68 61 22 20 69 64   out captcha" id
6170: 3d 27 61 75 74 6f 66 69 6c 6c 42 75 74 74 6f 6e  ='autofillButton
6180: 27 20 5c 0a 20 20 20 20 20 20 20 20 20 40 20 64  ' \.         @ d
6190: 61 74 61 2d 61 66 3d 27 25 73 28 7a 44 65 63 6f  ata-af='%s(zDeco
61a0: 64 65 64 29 27 20 2f 3e 0a 20 20 20 20 20 20 20  ded)' />.       
61b0: 20 20 73 74 79 6c 65 5f 6c 6f 61 64 5f 6f 6e 65    style_load_one
61c0: 5f 6a 73 5f 66 69 6c 65 28 22 6c 6f 67 69 6e 2e  _js_file("login.
61d0: 6a 73 22 29 3b 0a 20 20 20 20 20 20 7d 0a 20 20  js");.      }.  
61e0: 20 20 20 20 40 20 3c 2f 64 69 76 3e 0a 20 20 20      @ </div>.   
61f0: 20 20 20 66 72 65 65 28 7a 43 61 70 74 63 68 61     free(zCaptcha
6200: 29 3b 0a 20 20 20 20 7d 0a 20 20 20 20 40 20 3c  );.    }.    @ <
6210: 2f 66 6f 72 6d 3e 0a 20 20 7d 0a 20 20 69 66 28  /form>.  }.  if(
6220: 20 6c 6f 67 69 6e 5f 69 73 5f 69 6e 64 69 76 69   login_is_indivi
6230: 64 75 61 6c 28 29 20 29 7b 0a 20 20 20 20 69 66  dual() ){.    if
6240: 28 20 67 2e 70 65 72 6d 2e 45 6d 61 69 6c 41 6c  ( g.perm.EmailAl
6250: 65 72 74 20 26 26 20 61 6c 65 72 74 5f 65 6e 61  ert && alert_ena
6260: 62 6c 65 64 28 29 20 29 7b 0a 20 20 20 20 20 20  bled() ){.      
6270: 40 20 3c 68 72 3e 0a 20 20 20 20 20 20 40 20 3c  @ <hr>.      @ <
6280: 70 3e 43 6f 6e 66 69 67 75 72 65 20 3c 61 20 68  p>Configure <a h
6290: 72 65 66 3d 22 25 52 2f 61 6c 65 72 74 73 22 3e  ref="%R/alerts">
62a0: 45 6d 61 69 6c 20 41 6c 65 72 74 73 3c 2f 61 3e  Email Alerts</a>
62b0: 0a 20 20 20 20 20 20 40 20 66 6f 72 20 75 73 65  .      @ for use
62c0: 72 20 3c 62 3e 25 68 28 67 2e 7a 4c 6f 67 69 6e  r <b>%h(g.zLogin
62d0: 29 3c 2f 62 3e 3c 2f 70 3e 0a 20 20 20 20 7d 0a  )</b></p>.    }.
62e0: 20 20 20 20 69 66 28 20 67 2e 70 65 72 6d 2e 50      if( g.perm.P
62f0: 61 73 73 77 6f 72 64 20 29 7b 0a 20 20 20 20 20  assword ){.     
6300: 20 40 20 3c 68 72 3e 0a 20 20 20 20 20 20 40 20   @ <hr>.      @ 
6310: 3c 70 3e 43 68 61 6e 67 65 20 50 61 73 73 77 6f  <p>Change Passwo
6320: 72 64 20 66 6f 72 20 75 73 65 72 20 3c 62 3e 25  rd for user <b>%
6330: 68 28 67 2e 7a 4c 6f 67 69 6e 29 3c 2f 62 3e 3a  h(g.zLogin)</b>:
6340: 3c 2f 70 3e 0a 20 20 20 20 20 20 66 6f 72 6d 5f  </p>.      form_
6350: 62 65 67 69 6e 28 30 2c 20 22 25 52 2f 6c 6f 67  begin(0, "%R/log
6360: 69 6e 22 29 3b 0a 20 20 20 20 20 20 40 20 3c 74  in");.      @ <t
6370: 61 62 6c 65 3e 0a 20 20 20 20 20 20 40 20 3c 74  able>.      @ <t
6380: 72 3e 3c 74 64 20 63 6c 61 73 73 3d 22 66 6f 72  r><td class="for
6390: 6d 5f 6c 61 62 65 6c 22 3e 4f 6c 64 20 50 61 73  m_label">Old Pas
63a0: 73 77 6f 72 64 3a 3c 2f 74 64 3e 0a 20 20 20 20  sword:</td>.    
63b0: 20 20 40 20 3c 74 64 3e 3c 69 6e 70 75 74 20 74    @ <td><input t
63c0: 79 70 65 3d 22 70 61 73 73 77 6f 72 64 22 20 6e  ype="password" n
63d0: 61 6d 65 3d 22 70 22 20 73 69 7a 65 3d 22 33 30  ame="p" size="30
63e0: 22 20 2f 3e 3c 2f 74 64 3e 3c 2f 74 72 3e 0a 20  " /></td></tr>. 
63f0: 20 20 20 20 20 40 20 3c 74 72 3e 3c 74 64 20 63       @ <tr><td c
6400: 6c 61 73 73 3d 22 66 6f 72 6d 5f 6c 61 62 65 6c  lass="form_label
6410: 22 3e 4e 65 77 20 50 61 73 73 77 6f 72 64 3a 3c  ">New Password:<
6420: 2f 74 64 3e 0a 20 20 20 20 20 20 40 20 3c 74 64  /td>.      @ <td
6430: 3e 3c 69 6e 70 75 74 20 74 79 70 65 3d 22 70 61  ><input type="pa
6440: 73 73 77 6f 72 64 22 20 6e 61 6d 65 3d 22 6e 31  ssword" name="n1
6450: 22 20 73 69 7a 65 3d 22 33 30 22 20 2f 3e 3c 2f  " size="30" /></
6460: 74 64 3e 3c 2f 74 72 3e 0a 20 20 20 20 20 20 40  td></tr>.      @
6470: 20 3c 74 72 3e 3c 74 64 20 63 6c 61 73 73 3d 22   <tr><td class="
6480: 66 6f 72 6d 5f 6c 61 62 65 6c 22 3e 52 65 70 65  form_label">Repe
6490: 61 74 20 4e 65 77 20 50 61 73 73 77 6f 72 64 3a  at New Password:
64a0: 3c 2f 74 64 3e 0a 20 20 20 20 20 20 40 20 3c 74  </td>.      @ <t
64b0: 64 3e 3c 69 6e 70 75 74 20 74 79 70 65 3d 22 70  d><input type="p
64c0: 61 73 73 77 6f 72 64 22 20 6e 61 6d 65 3d 22 6e  assword" name="n
64d0: 32 22 20 73 69 7a 65 3d 22 33 30 22 20 2f 3e 3c  2" size="30" /><
64e0: 2f 74 64 3e 3c 2f 74 72 3e 0a 20 20 20 20 20 20  /td></tr>.      
64f0: 40 20 3c 74 72 3e 3c 74 64 3e 3c 2f 74 64 3e 0a  @ <tr><td></td>.
6500: 20 20 20 20 20 20 40 20 3c 74 64 3e 3c 69 6e 70        @ <td><inp
6510: 75 74 20 74 79 70 65 3d 22 73 75 62 6d 69 74 22  ut type="submit"
6520: 20 76 61 6c 75 65 3d 22 43 68 61 6e 67 65 20 50   value="Change P
6530: 61 73 73 77 6f 72 64 22 20 2f 3e 3c 2f 74 64 3e  assword" /></td>
6540: 3c 2f 74 72 3e 0a 20 20 20 20 20 20 40 20 3c 2f  </tr>.      @ </
6550: 74 61 62 6c 65 3e 0a 20 20 20 20 20 20 40 20 3c  table>.      @ <
6560: 2f 66 6f 72 6d 3e 0a 20 20 20 20 7d 0a 20 20 7d  /form>.    }.  }
6570: 0a 20 20 73 74 79 6c 65 5f 66 6f 6f 74 65 72 28  .  style_footer(
6580: 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 41 74 74 65  );.}../*.** Atte
6590: 6d 70 74 20 74 6f 20 66 69 6e 64 20 6c 6f 67 69  mpt to find logi
65a0: 6e 20 63 72 65 64 65 6e 74 69 61 6c 73 20 66 6f  n credentials fo
65b0: 72 20 75 73 65 72 20 7a 4c 6f 67 69 6e 20 6f 6e  r user zLogin on
65c0: 20 61 20 70 65 65 72 20 72 65 70 6f 73 69 74 6f   a peer reposito
65d0: 72 79 0a 2a 2a 20 77 69 74 68 20 70 72 6f 6a 65  ry.** with proje
65e0: 63 74 20 63 6f 64 65 20 7a 43 6f 64 65 2e 20 20  ct code zCode.  
65f0: 54 72 61 6e 73 66 65 72 20 74 68 6f 73 65 20 63  Transfer those c
6600: 72 65 64 65 6e 74 69 61 6c 73 20 74 6f 20 74 68  redentials to th
6610: 65 20 6c 6f 63 61 6c 0a 2a 2a 20 72 65 70 6f 73  e local.** repos
6620: 69 74 6f 72 79 2e 0a 2a 2a 0a 2a 2a 20 52 65 74  itory..**.** Ret
6630: 75 72 6e 20 74 72 75 65 20 69 66 20 61 20 74 72  urn true if a tr
6640: 61 6e 73 66 65 72 20 77 61 73 20 6d 61 64 65 20  ansfer was made 
6650: 61 6e 64 20 66 61 6c 73 65 20 69 66 20 6e 6f 74  and false if not
6660: 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20  ..*/.static int 
6670: 6c 6f 67 69 6e 5f 74 72 61 6e 73 66 65 72 5f 63  login_transfer_c
6680: 72 65 64 65 6e 74 69 61 6c 73 28 0a 20 20 63 6f  redentials(.  co
6690: 6e 73 74 20 63 68 61 72 20 2a 7a 4c 6f 67 69 6e  nst char *zLogin
66a0: 2c 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4c 6f  ,          /* Lo
66b0: 67 69 6e 20 77 65 20 61 72 65 20 6c 6f 6f 6b 69  gin we are looki
66c0: 6e 67 20 66 6f 72 20 2a 2f 0a 20 20 63 6f 6e 73  ng for */.  cons
66d0: 74 20 63 68 61 72 20 2a 7a 43 6f 64 65 2c 20 20  t char *zCode,  
66e0: 20 20 20 20 20 20 20 20 20 2f 2a 20 50 72 6f 6a           /* Proj
66f0: 65 63 74 20 63 6f 64 65 20 6f 66 20 70 65 65 72  ect code of peer
6700: 20 72 65 70 6f 73 69 74 6f 72 79 20 2a 2f 0a 20   repository */. 
6710: 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 48 61   const char *zHa
6720: 73 68 2c 20 20 20 20 20 20 20 20 20 20 20 2f 2a  sh,           /*
6730: 20 48 41 53 48 20 66 72 6f 6d 20 6c 6f 67 69 6e   HASH from login
6740: 20 63 6f 6f 6b 69 65 20 48 41 53 48 2f 43 4f 44   cookie HASH/COD
6750: 45 2f 4c 4f 47 49 4e 20 2a 2f 0a 20 20 63 6f 6e  E/LOGIN */.  con
6760: 73 74 20 63 68 61 72 20 2a 7a 52 65 6d 6f 74 65  st char *zRemote
6770: 41 64 64 72 20 20 20 20 20 20 2f 2a 20 52 65 71  Addr      /* Req
6780: 75 65 73 74 20 63 6f 6d 65 73 20 66 72 6f 6d 20  uest comes from 
6790: 68 65 72 65 20 2a 2f 0a 29 7b 0a 20 20 73 71 6c  here */.){.  sql
67a0: 69 74 65 33 20 2a 70 4f 74 68 65 72 20 3d 20 30  ite3 *pOther = 0
67b0: 3b 20 20 20 20 20 20 20 20 20 2f 2a 20 54 68 65  ;         /* The
67c0: 20 6f 74 68 65 72 20 72 65 70 6f 73 69 74 6f 72   other repositor
67d0: 79 20 2a 2f 0a 20 20 73 71 6c 69 74 65 33 5f 73  y */.  sqlite3_s
67e0: 74 6d 74 20 2a 70 53 74 6d 74 3b 20 20 20 20 20  tmt *pStmt;     
67f0: 20 20 20 20 2f 2a 20 51 75 65 72 79 20 61 67 61      /* Query aga
6800: 69 6e 73 74 20 74 68 65 20 6f 74 68 65 72 20 72  inst the other r
6810: 65 70 6f 73 69 74 6f 72 79 20 2a 2f 0a 20 20 63  epository */.  c
6820: 68 61 72 20 2a 7a 53 51 4c 3b 20 20 20 20 20 20  har *zSQL;      
6830: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 53              /* S
6840: 51 4c 20 6f 66 20 74 68 65 20 71 75 65 72 79 20  QL of the query 
6850: 61 67 61 69 6e 73 74 20 6f 74 68 65 72 20 72 65  against other re
6860: 70 6f 20 2a 2f 0a 20 20 63 68 61 72 20 2a 7a 4f  po */.  char *zO
6870: 74 68 65 72 52 65 70 6f 3b 20 20 20 20 20 20 20  therRepo;       
6880: 20 20 20 20 20 2f 2a 20 46 69 6c 65 6e 61 6d 65       /* Filename
6890: 20 6f 66 20 74 68 65 20 6f 74 68 65 72 20 72 65   of the other re
68a0: 70 6f 73 69 74 6f 72 79 20 2a 2f 0a 20 20 69 6e  pository */.  in
68b0: 74 20 72 63 3b 20 20 20 20 20 20 20 20 20 20 20  t rc;           
68c0: 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 52 65             /* Re
68d0: 73 75 6c 74 20 63 6f 64 65 20 66 72 6f 6d 20 53  sult code from S
68e0: 51 4c 69 74 65 20 6c 69 62 72 61 72 79 20 66 75  QLite library fu
68f0: 6e 63 74 69 6f 6e 73 20 2a 2f 0a 20 20 69 6e 74  nctions */.  int
6900: 20 6e 58 66 65 72 20 3d 20 30 3b 20 20 20 20 20   nXfer = 0;     
6910: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4e 75 6d            /* Num
6920: 62 65 72 20 6f 66 20 63 72 65 64 65 6e 74 69 61  ber of credentia
6930: 6c 73 20 74 72 61 6e 73 66 65 72 72 65 64 20 2a  ls transferred *
6940: 2f 0a 0a 20 20 7a 4f 74 68 65 72 52 65 70 6f 20  /..  zOtherRepo 
6950: 3d 20 64 62 5f 74 65 78 74 28 30 2c 0a 20 20 20  = db_text(0,.   
6960: 20 20 20 20 22 53 45 4c 45 43 54 20 76 61 6c 75      "SELECT valu
6970: 65 20 46 52 4f 4d 20 63 6f 6e 66 69 67 20 57 48  e FROM config WH
6980: 45 52 45 20 6e 61 6d 65 3d 27 70 65 65 72 2d 72  ERE name='peer-r
6990: 65 70 6f 2d 25 71 27 22 2c 0a 20 20 20 20 20 20  epo-%q'",.      
69a0: 20 7a 43 6f 64 65 0a 20 20 29 3b 0a 20 20 69 66   zCode.  );.  if
69b0: 28 20 7a 4f 74 68 65 72 52 65 70 6f 3d 3d 30 20  ( zOtherRepo==0 
69c0: 29 20 72 65 74 75 72 6e 20 30 3b 20 20 2f 2a 20  ) return 0;  /* 
69d0: 4e 6f 20 73 75 63 68 20 70 65 65 72 20 72 65 70  No such peer rep
69e0: 6f 73 69 74 6f 72 79 20 2a 2f 0a 0a 20 20 72 63  ository */..  rc
69f0: 20 3d 20 73 71 6c 69 74 65 33 5f 6f 70 65 6e 5f   = sqlite3_open_
6a00: 76 32 28 0a 20 20 20 20 20 20 20 7a 4f 74 68 65  v2(.       zOthe
6a10: 72 52 65 70 6f 2c 20 26 70 4f 74 68 65 72 2c 0a  rRepo, &pOther,.
6a20: 20 20 20 20 20 20 20 53 51 4c 49 54 45 5f 4f 50         SQLITE_OP
6a30: 45 4e 5f 52 45 41 44 57 52 49 54 45 20 7c 20 53  EN_READWRITE | S
6a40: 51 4c 49 54 45 5f 4f 50 45 4e 5f 43 52 45 41 54  QLITE_OPEN_CREAT
6a50: 45 2c 0a 20 20 20 20 20 20 20 67 2e 7a 56 66 73  E,.       g.zVfs
6a60: 4e 61 6d 65 0a 20 20 29 3b 0a 20 20 69 66 28 20  Name.  );.  if( 
6a70: 72 63 3d 3d 53 51 4c 49 54 45 5f 4f 4b 20 29 7b  rc==SQLITE_OK ){
6a80: 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 63 72 65  .    sqlite3_cre
6a90: 61 74 65 5f 66 75 6e 63 74 69 6f 6e 28 70 4f 74  ate_function(pOt
6aa0: 68 65 72 2c 22 6e 6f 77 22 2c 30 2c 53 51 4c 49  her,"now",0,SQLI
6ab0: 54 45 5f 55 54 46 38 2c 30 2c 64 62 5f 6e 6f 77  TE_UTF8,0,db_now
6ac0: 5f 66 75 6e 63 74 69 6f 6e 2c 30 2c 30 29 3b 0a  _function,0,0);.
6ad0: 20 20 20 20 73 71 6c 69 74 65 33 5f 63 72 65 61      sqlite3_crea
6ae0: 74 65 5f 66 75 6e 63 74 69 6f 6e 28 70 4f 74 68  te_function(pOth
6af0: 65 72 2c 20 22 63 6f 6e 73 74 61 6e 74 5f 74 69  er, "constant_ti
6b00: 6d 65 5f 63 6d 70 22 2c 20 32 2c 20 53 51 4c 49  me_cmp", 2, SQLI
6b10: 54 45 5f 55 54 46 38 2c 20 30 2c 0a 20 20 20 20  TE_UTF8, 0,.    
6b20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 63 6f                co
6b30: 6e 73 74 61 6e 74 5f 74 69 6d 65 5f 63 6d 70 5f  nstant_time_cmp_
6b40: 66 75 6e 63 74 69 6f 6e 2c 20 30 2c 20 30 29 3b  function, 0, 0);
6b50: 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 62 75 73  .    sqlite3_bus
6b60: 79 5f 74 69 6d 65 6f 75 74 28 70 4f 74 68 65 72  y_timeout(pOther
6b70: 2c 20 35 30 30 30 29 3b 0a 20 20 20 20 7a 53 51  , 5000);.    zSQ
6b80: 4c 20 3d 20 6d 70 72 69 6e 74 66 28 0a 20 20 20  L = mprintf(.   
6b90: 20 20 20 22 53 45 4c 45 43 54 20 63 65 78 70 69     "SELECT cexpi
6ba0: 72 65 20 46 52 4f 4d 20 75 73 65 72 22 0a 20 20  re FROM user".  
6bb0: 20 20 20 20 22 20 57 48 45 52 45 20 6c 6f 67 69      " WHERE logi
6bc0: 6e 3d 25 51 22 0a 20 20 20 20 20 20 22 20 20 20  n=%Q".      "   
6bd0: 41 4e 44 20 69 70 61 64 64 72 3d 25 51 22 0a 20  AND ipaddr=%Q". 
6be0: 20 20 20 20 20 22 20 20 20 41 4e 44 20 6c 65 6e       "   AND len
6bf0: 67 74 68 28 63 61 70 29 3e 30 22 0a 20 20 20 20  gth(cap)>0".    
6c00: 20 20 22 20 20 20 41 4e 44 20 6c 65 6e 67 74 68    "   AND length
6c10: 28 70 77 29 3e 30 22 0a 20 20 20 20 20 20 22 20  (pw)>0".      " 
6c20: 20 20 41 4e 44 20 63 65 78 70 69 72 65 3e 6a 75    AND cexpire>ju
6c30: 6c 69 61 6e 64 61 79 28 27 6e 6f 77 27 29 22 0a  lianday('now')".
6c40: 20 20 20 20 20 20 22 20 20 20 41 4e 44 20 63 6f        "   AND co
6c50: 6e 73 74 61 6e 74 5f 74 69 6d 65 5f 63 6d 70 28  nstant_time_cmp(
6c60: 63 6f 6f 6b 69 65 2c 25 51 29 3d 30 22 2c 0a 20  cookie,%Q)=0",. 
6c70: 20 20 20 20 20 7a 4c 6f 67 69 6e 2c 20 7a 52 65       zLogin, zRe
6c80: 6d 6f 74 65 41 64 64 72 2c 20 7a 48 61 73 68 0a  moteAddr, zHash.
6c90: 20 20 20 20 29 3b 0a 20 20 20 20 70 53 74 6d 74      );.    pStmt
6ca0: 20 3d 20 30 3b 0a 20 20 20 20 72 63 20 3d 20 73   = 0;.    rc = s
6cb0: 71 6c 69 74 65 33 5f 70 72 65 70 61 72 65 5f 76  qlite3_prepare_v
6cc0: 32 28 70 4f 74 68 65 72 2c 20 7a 53 51 4c 2c 20  2(pOther, zSQL, 
6cd0: 2d 31 2c 20 26 70 53 74 6d 74 2c 20 30 29 3b 0a  -1, &pStmt, 0);.
6ce0: 20 20 20 20 69 66 28 20 72 63 3d 3d 53 51 4c 49      if( rc==SQLI
6cf0: 54 45 5f 4f 4b 20 26 26 20 73 71 6c 69 74 65 33  TE_OK && sqlite3
6d00: 5f 73 74 65 70 28 70 53 74 6d 74 29 3d 3d 53 51  _step(pStmt)==SQ
6d10: 4c 49 54 45 5f 52 4f 57 20 29 7b 0a 20 20 20 20  LITE_ROW ){.    
6d20: 20 20 64 62 5f 6d 75 6c 74 69 5f 65 78 65 63 28    db_multi_exec(
6d30: 0a 20 20 20 20 20 20 20 20 22 55 50 44 41 54 45  .        "UPDATE
6d40: 20 75 73 65 72 20 53 45 54 20 63 6f 6f 6b 69 65   user SET cookie
6d50: 3d 25 51 2c 20 69 70 61 64 64 72 3d 25 51 2c 20  =%Q, ipaddr=%Q, 
6d60: 63 65 78 70 69 72 65 3d 25 2e 31 37 67 22 0a 20  cexpire=%.17g". 
6d70: 20 20 20 20 20 20 20 22 20 57 48 45 52 45 20 6c         " WHERE l
6d80: 6f 67 69 6e 3d 25 51 22 2c 0a 20 20 20 20 20 20  ogin=%Q",.      
6d90: 20 20 7a 48 61 73 68 2c 20 7a 52 65 6d 6f 74 65    zHash, zRemote
6da0: 41 64 64 72 2c 0a 20 20 20 20 20 20 20 20 73 71  Addr,.        sq
6db0: 6c 69 74 65 33 5f 63 6f 6c 75 6d 6e 5f 64 6f 75  lite3_column_dou
6dc0: 62 6c 65 28 70 53 74 6d 74 2c 20 30 29 2c 20 7a  ble(pStmt, 0), z
6dd0: 4c 6f 67 69 6e 0a 20 20 20 20 20 20 29 3b 0a 20  Login.      );. 
6de0: 20 20 20 20 20 6e 58 66 65 72 2b 2b 3b 0a 20 20       nXfer++;.  
6df0: 20 20 7d 0a 20 20 20 20 73 71 6c 69 74 65 33 5f    }.    sqlite3_
6e00: 66 69 6e 61 6c 69 7a 65 28 70 53 74 6d 74 29 3b  finalize(pStmt);
6e10: 0a 20 20 7d 0a 20 20 73 71 6c 69 74 65 33 5f 63  .  }.  sqlite3_c
6e20: 6c 6f 73 65 28 70 4f 74 68 65 72 29 3b 0a 20 20  lose(pOther);.  
6e30: 66 6f 73 73 69 6c 5f 66 72 65 65 28 7a 4f 74 68  fossil_free(zOth
6e40: 65 72 52 65 70 6f 29 3b 0a 20 20 72 65 74 75 72  erRepo);.  retur
6e50: 6e 20 6e 58 66 65 72 3b 0a 7d 0a 0a 2f 2a 0a 2a  n nXfer;.}../*.*
6e60: 2a 20 52 65 74 75 72 6e 20 54 52 55 45 20 69 66  * Return TRUE if
6e70: 20 7a 4c 6f 67 69 6e 20 69 73 20 6f 6e 65 20 6f   zLogin is one o
6e80: 66 20 74 68 65 20 73 70 65 63 69 61 6c 20 75 73  f the special us
6e90: 65 72 6e 61 6d 65 73 0a 2a 2f 0a 69 6e 74 20 6c  ernames.*/.int l
6ea0: 6f 67 69 6e 5f 69 73 5f 73 70 65 63 69 61 6c 28  ogin_is_special(
6eb0: 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 4c 6f 67  const char *zLog
6ec0: 69 6e 29 7b 0a 20 20 69 66 28 20 66 6f 73 73 69  in){.  if( fossi
6ed0: 6c 5f 73 74 72 63 6d 70 28 7a 4c 6f 67 69 6e 2c  l_strcmp(zLogin,
6ee0: 20 22 61 6e 6f 6e 79 6d 6f 75 73 22 29 3d 3d 30   "anonymous")==0
6ef0: 20 29 20 72 65 74 75 72 6e 20 31 3b 0a 20 20 69   ) return 1;.  i
6f00: 66 28 20 66 6f 73 73 69 6c 5f 73 74 72 63 6d 70  f( fossil_strcmp
6f10: 28 7a 4c 6f 67 69 6e 2c 20 22 6e 6f 62 6f 64 79  (zLogin, "nobody
6f20: 22 29 3d 3d 30 20 29 20 72 65 74 75 72 6e 20 31  ")==0 ) return 1
6f30: 3b 0a 20 20 69 66 28 20 66 6f 73 73 69 6c 5f 73  ;.  if( fossil_s
6f40: 74 72 63 6d 70 28 7a 4c 6f 67 69 6e 2c 20 22 64  trcmp(zLogin, "d
6f50: 65 76 65 6c 6f 70 65 72 22 29 3d 3d 30 20 29 20  eveloper")==0 ) 
6f60: 72 65 74 75 72 6e 20 31 3b 0a 20 20 69 66 28 20  return 1;.  if( 
6f70: 66 6f 73 73 69 6c 5f 73 74 72 63 6d 70 28 7a 4c  fossil_strcmp(zL
6f80: 6f 67 69 6e 2c 20 22 72 65 61 64 65 72 22 29 3d  ogin, "reader")=
6f90: 3d 30 20 29 20 72 65 74 75 72 6e 20 31 3b 0a 20  =0 ) return 1;. 
6fa0: 20 72 65 74 75 72 6e 20 30 3b 0a 7d 0a 0a 2f 2a   return 0;.}../*
6fb0: 0a 2a 2a 20 4c 6f 6f 6b 75 70 20 74 68 65 20 75  .** Lookup the u
6fc0: 69 64 20 66 6f 72 20 61 20 6e 6f 6e 2d 62 75 69  id for a non-bui
6fd0: 6c 74 2d 69 6e 20 75 73 65 72 20 77 69 74 68 20  lt-in user with 
6fe0: 7a 4c 6f 67 69 6e 20 61 6e 64 20 7a 43 6f 6f 6b  zLogin and zCook
6ff0: 69 65 20 61 6e 64 0a 2a 2a 20 7a 52 65 6d 6f 74  ie and.** zRemot
7000: 65 41 64 64 72 2e 20 20 52 65 74 75 72 6e 20 30  eAddr.  Return 0
7010: 20 69 66 20 6e 6f 74 20 66 6f 75 6e 64 2e 0a 2a   if not found..*
7020: 2a 0a 2a 2a 20 4e 6f 74 65 20 74 68 61 74 20 74  *.** Note that t
7030: 68 69 73 20 6f 6e 6c 79 20 73 65 61 72 63 68 65  his only searche
7040: 73 20 66 6f 72 20 6c 6f 67 67 65 64 2d 69 6e 20  s for logged-in 
7050: 65 6e 74 72 69 65 73 20 77 69 74 68 20 6d 61 74  entries with mat
7060: 63 68 69 6e 67 0a 2a 2a 20 7a 43 6f 6f 6b 69 65  ching.** zCookie
7070: 20 28 64 62 3a 20 75 73 65 72 2e 63 6f 6f 6b 69   (db: user.cooki
7080: 65 29 20 61 6e 64 20 7a 52 65 6d 6f 74 65 41 64  e) and zRemoteAd
7090: 64 72 20 28 64 62 3a 20 75 73 65 72 2e 69 70 61  dr (db: user.ipa
70a0: 64 64 72 29 0a 2a 2a 20 65 6e 74 72 69 65 73 2e  ddr).** entries.
70b0: 0a 2a 2f 0a 73 74 61 74 69 63 20 69 6e 74 20 6c  .*/.static int l
70c0: 6f 67 69 6e 5f 66 69 6e 64 5f 75 73 65 72 28 0a  ogin_find_user(.
70d0: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 4c    const char *zL
70e0: 6f 67 69 6e 2c 20 20 20 20 20 20 20 20 20 20 20  ogin,           
70f0: 20 2f 2a 20 55 73 65 72 20 6e 61 6d 65 20 2a 2f   /* User name */
7100: 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a  .  const char *z
7110: 43 6f 6f 6b 69 65 2c 20 20 20 20 20 20 20 20 20  Cookie,         
7120: 20 20 2f 2a 20 4c 6f 67 69 6e 20 63 6f 6f 6b 69    /* Login cooki
7130: 65 20 76 61 6c 75 65 20 2a 2f 0a 20 20 63 6f 6e  e value */.  con
7140: 73 74 20 63 68 61 72 20 2a 7a 52 65 6d 6f 74 65  st char *zRemote
7150: 41 64 64 72 20 20 20 20 20 20 20 20 2f 2a 20 41  Addr        /* A
7160: 62 62 72 65 76 69 61 74 65 64 20 49 50 20 61 64  bbreviated IP ad
7170: 64 72 65 73 73 20 66 6f 72 20 76 61 6c 69 64 20  dress for valid 
7180: 6c 6f 67 69 6e 20 2a 2f 0a 29 7b 0a 20 20 69 6e  login */.){.  in
7190: 74 20 75 69 64 3b 0a 20 20 69 66 28 20 6c 6f 67  t uid;.  if( log
71a0: 69 6e 5f 69 73 5f 73 70 65 63 69 61 6c 28 7a 4c  in_is_special(zL
71b0: 6f 67 69 6e 29 20 29 20 72 65 74 75 72 6e 20 30  ogin) ) return 0
71c0: 3b 0a 20 20 75 69 64 20 3d 20 64 62 5f 69 6e 74  ;.  uid = db_int
71d0: 28 30 2c 0a 20 20 20 20 22 53 45 4c 45 43 54 20  (0,.    "SELECT 
71e0: 75 69 64 20 46 52 4f 4d 20 75 73 65 72 22 0a 20  uid FROM user". 
71f0: 20 20 20 22 20 57 48 45 52 45 20 6c 6f 67 69 6e     " WHERE login
7200: 3d 25 51 22 0a 20 20 20 20 22 20 20 20 41 4e 44  =%Q".    "   AND
7210: 20 69 70 61 64 64 72 3d 25 51 22 0a 20 20 20 20   ipaddr=%Q".    
7220: 22 20 20 20 41 4e 44 20 63 65 78 70 69 72 65 3e  "   AND cexpire>
7230: 6a 75 6c 69 61 6e 64 61 79 28 27 6e 6f 77 27 29  julianday('now')
7240: 22 0a 20 20 20 20 22 20 20 20 41 4e 44 20 6c 65  ".    "   AND le
7250: 6e 67 74 68 28 63 61 70 29 3e 30 22 0a 20 20 20  ngth(cap)>0".   
7260: 20 22 20 20 20 41 4e 44 20 6c 65 6e 67 74 68 28   "   AND length(
7270: 70 77 29 3e 30 22 0a 20 20 20 20 22 20 20 20 41  pw)>0".    "   A
7280: 4e 44 20 63 6f 6e 73 74 61 6e 74 5f 74 69 6d 65  ND constant_time
7290: 5f 63 6d 70 28 63 6f 6f 6b 69 65 2c 25 51 29 3d  _cmp(cookie,%Q)=
72a0: 30 22 2c 0a 20 20 20 20 7a 4c 6f 67 69 6e 2c 20  0",.    zLogin, 
72b0: 7a 52 65 6d 6f 74 65 41 64 64 72 2c 20 7a 43 6f  zRemoteAddr, zCo
72c0: 6f 6b 69 65 0a 20 20 29 3b 0a 20 20 72 65 74 75  okie.  );.  retu
72d0: 72 6e 20 75 69 64 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a  rn uid;.}../*.**
72e0: 20 41 74 74 65 6d 70 74 20 74 6f 20 75 73 65 20   Attempt to use 
72f0: 42 61 73 69 63 20 41 75 74 68 65 6e 74 69 63 61  Basic Authentica
7300: 74 69 6f 6e 20 74 6f 20 65 73 74 61 62 6c 69 73  tion to establis
7310: 68 20 74 68 65 20 75 73 65 72 2e 20 20 52 65 74  h the user.  Ret
7320: 75 72 6e 20 74 68 65 0a 2a 2a 20 28 6e 6f 6e 2d  urn the.** (non-
7330: 7a 65 72 6f 29 20 75 69 64 20 69 66 20 73 75 63  zero) uid if suc
7340: 63 65 73 73 66 75 6c 2e 20 20 52 65 74 75 72 6e  cessful.  Return
7350: 20 30 20 69 66 20 69 74 20 64 6f 65 73 20 6e 6f   0 if it does no
7360: 74 20 77 6f 72 6b 2e 0a 2a 2f 0a 73 74 61 74 69  t work..*/.stati
7370: 63 20 69 6e 74 20 6c 6f 67 69 63 5f 62 61 73 69  c int logic_basi
7380: 63 5f 61 75 74 68 65 6e 74 69 63 61 74 69 6f 6e  c_authentication
7390: 28 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 49 70  (const char *zIp
73a0: 41 64 64 72 29 7b 0a 20 20 63 6f 6e 73 74 20 63  Addr){.  const c
73b0: 68 61 72 20 2a 7a 41 75 74 68 20 3d 20 50 44 28  har *zAuth = PD(
73c0: 22 48 54 54 50 5f 41 55 54 48 4f 52 49 5a 41 54  "HTTP_AUTHORIZAT
73d0: 49 4f 4e 22 2c 20 30 29 3b 0a 20 20 69 6e 74 20  ION", 0);.  int 
73e0: 69 3b 0a 20 20 69 6e 74 20 75 69 64 20 3d 20 30  i;.  int uid = 0
73f0: 3b 0a 20 20 69 6e 74 20 6e 44 65 63 6f 64 65 20  ;.  int nDecode 
7400: 3d 20 30 3b 0a 20 20 63 68 61 72 20 2a 7a 44 65  = 0;.  char *zDe
7410: 63 6f 64 65 20 3d 20 30 3b 0a 20 20 63 6f 6e 73  code = 0;.  cons
7420: 74 20 63 68 61 72 20 2a 7a 55 73 65 72 6e 61 6d  t char *zUsernam
7430: 65 20 3d 20 30 3b 0a 20 20 63 6f 6e 73 74 20 63  e = 0;.  const c
7440: 68 61 72 20 2a 7a 50 61 73 73 77 64 20 3d 20 30  har *zPasswd = 0
7450: 3b 0a 0a 20 20 69 66 28 20 7a 41 75 74 68 3d 3d  ;..  if( zAuth==
7460: 30 20 29 20 72 65 74 75 72 6e 20 30 3b 20 20 20  0 ) return 0;   
7470: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
7480: 20 2f 2a 20 46 61 69 6c 3a 20 4e 6f 20 41 75 74   /* Fail: No Aut
7490: 68 65 6e 74 69 63 61 74 69 6f 6e 3a 20 68 65 61  hentication: hea
74a0: 64 65 72 20 2a 2f 0a 20 20 77 68 69 6c 65 28 20  der */.  while( 
74b0: 66 6f 73 73 69 6c 5f 69 73 73 70 61 63 65 28 7a  fossil_isspace(z
74c0: 41 75 74 68 5b 30 5d 29 20 29 20 7a 41 75 74 68  Auth[0]) ) zAuth
74d0: 2b 2b 3b 20 20 2f 2a 20 53 6b 69 70 20 6c 65 61  ++;  /* Skip lea
74e0: 64 69 6e 67 20 77 68 69 74 65 73 70 61 63 65 20  ding whitespace 
74f0: 2a 2f 0a 20 20 69 66 28 20 73 74 72 6e 63 6d 70  */.  if( strncmp
7500: 28 7a 41 75 74 68 2c 20 22 42 61 73 69 63 20 22  (zAuth, "Basic "
7510: 2c 20 36 29 21 3d 30 20 29 20 72 65 74 75 72 6e  , 6)!=0 ) return
7520: 20 30 3b 20 20 2f 2a 20 46 61 69 6c 3a 20 4e 6f   0;  /* Fail: No
7530: 74 20 42 61 73 69 63 20 41 75 74 68 65 6e 74 69  t Basic Authenti
7540: 63 61 74 69 6f 6e 20 2a 2f 0a 0a 20 20 2f 2a 20  cation */..  /* 
7550: 50 61 72 73 65 20 6f 75 74 20 74 68 65 20 75 73  Parse out the us
7560: 65 72 6e 61 6d 65 20 61 6e 64 20 70 61 73 73 77  ername and passw
7570: 6f 72 64 2c 20 73 65 70 61 72 61 74 65 64 20 62  ord, separated b
7580: 79 20 61 20 22 3a 22 20 2a 2f 0a 20 20 7a 41 75  y a ":" */.  zAu
7590: 74 68 20 2b 3d 20 36 3b 0a 20 20 77 68 69 6c 65  th += 6;.  while
75a0: 28 20 66 6f 73 73 69 6c 5f 69 73 73 70 61 63 65  ( fossil_isspace
75b0: 28 7a 41 75 74 68 5b 30 5d 29 20 29 20 7a 41 75  (zAuth[0]) ) zAu
75c0: 74 68 2b 2b 3b 0a 20 20 7a 44 65 63 6f 64 65 20  th++;.  zDecode 
75d0: 3d 20 64 65 63 6f 64 65 36 34 28 7a 41 75 74 68  = decode64(zAuth
75e0: 2c 20 26 6e 44 65 63 6f 64 65 29 3b 0a 0a 20 20  , &nDecode);..  
75f0: 66 6f 72 28 69 3d 30 3b 20 7a 44 65 63 6f 64 65  for(i=0; zDecode
7600: 5b 69 5d 20 26 26 20 7a 44 65 63 6f 64 65 5b 69  [i] && zDecode[i
7610: 5d 21 3d 27 3a 27 3b 20 69 2b 2b 29 7b 7d 0a 20  ]!=':'; i++){}. 
7620: 20 69 66 28 20 7a 44 65 63 6f 64 65 5b 69 5d 20   if( zDecode[i] 
7630: 29 7b 0a 20 20 20 20 7a 44 65 63 6f 64 65 5b 69  ){.    zDecode[i
7640: 5d 20 3d 20 30 3b 0a 20 20 20 20 7a 55 73 65 72  ] = 0;.    zUser
7650: 6e 61 6d 65 20 3d 20 7a 44 65 63 6f 64 65 3b 0a  name = zDecode;.
7660: 20 20 20 20 7a 50 61 73 73 77 64 20 3d 20 26 7a      zPasswd = &z
7670: 44 65 63 6f 64 65 5b 69 2b 31 5d 3b 0a 0a 20 20  Decode[i+1];..  
7680: 20 20 2f 2a 20 41 74 74 65 6d 70 74 69 6e 67 20    /* Attempting 
7690: 74 6f 20 6c 6f 67 20 69 6e 20 61 73 20 74 68 65  to log in as the
76a0: 20 75 73 65 72 20 70 72 6f 76 69 64 65 64 20 62   user provided b
76b0: 79 20 48 54 54 50 0a 20 20 20 20 2a 2a 20 62 61  y HTTP.    ** ba
76c0: 73 69 63 20 61 75 74 68 0a 20 20 20 20 2a 2f 0a  sic auth.    */.
76d0: 20 20 20 20 75 69 64 20 3d 20 6c 6f 67 69 6e 5f      uid = login_
76e0: 73 65 61 72 63 68 5f 75 69 64 28 26 7a 55 73 65  search_uid(&zUse
76f0: 72 6e 61 6d 65 2c 20 7a 50 61 73 73 77 64 29 3b  rname, zPasswd);
7700: 0a 20 20 20 20 69 66 28 20 75 69 64 3e 30 20 29  .    if( uid>0 )
7710: 7b 0a 20 20 20 20 20 20 72 65 63 6f 72 64 5f 6c  {.      record_l
7720: 6f 67 69 6e 5f 61 74 74 65 6d 70 74 28 7a 55 73  ogin_attempt(zUs
7730: 65 72 6e 61 6d 65 2c 20 7a 49 70 41 64 64 72 2c  ername, zIpAddr,
7740: 20 31 29 3b 0a 20 20 20 20 7d 65 6c 73 65 7b 0a   1);.    }else{.
7750: 20 20 20 20 20 20 72 65 63 6f 72 64 5f 6c 6f 67        record_log
7760: 69 6e 5f 61 74 74 65 6d 70 74 28 7a 55 73 65 72  in_attempt(zUser
7770: 6e 61 6d 65 2c 20 7a 49 70 41 64 64 72 2c 20 30  name, zIpAddr, 0
7780: 29 3b 0a 0a 20 20 20 20 20 20 2f 2a 20 54 68 65  );..      /* The
7790: 20 75 73 65 72 20 61 74 74 65 6d 70 74 65 64 20   user attempted 
77a0: 74 6f 20 6c 6f 67 69 6e 20 73 70 65 63 69 66 69  to login specifi
77b0: 63 61 6c 6c 79 20 77 69 74 68 20 48 54 54 50 20  cally with HTTP 
77c0: 62 61 73 69 63 0a 20 20 20 20 20 20 2a 2a 20 61  basic.      ** a
77d0: 75 74 68 2c 20 62 75 74 20 70 72 6f 76 69 64 65  uth, but provide
77e0: 64 20 69 6e 76 61 6c 69 64 20 63 72 65 64 65 6e  d invalid creden
77f0: 74 69 61 6c 73 2e 20 49 6e 66 6f 72 6d 20 74 68  tials. Inform th
7800: 65 6d 20 6f 66 0a 20 20 20 20 20 20 2a 2a 20 74  em of.      ** t
7810: 68 65 20 66 61 69 6c 65 64 20 6c 6f 67 69 6e 20  he failed login 
7820: 61 74 74 65 6d 70 74 20 76 69 61 20 34 30 31 2e  attempt via 401.
7830: 0a 20 20 20 20 20 20 2a 2f 0a 20 20 20 20 20 20  .      */.      
7840: 63 67 69 5f 73 65 74 5f 73 74 61 74 75 73 28 34  cgi_set_status(4
7850: 30 31 2c 20 22 55 6e 61 75 74 68 6f 72 69 7a 65  01, "Unauthorize
7860: 64 22 29 3b 0a 20 20 20 20 20 20 63 67 69 5f 72  d");.      cgi_r
7870: 65 70 6c 79 28 29 3b 0a 20 20 20 20 20 20 66 6f  eply();.      fo
7880: 73 73 69 6c 5f 65 78 69 74 28 30 29 3b 0a 20 20  ssil_exit(0);.  
7890: 20 20 7d 0a 20 20 7d 0a 20 20 66 6f 73 73 69 6c    }.  }.  fossil
78a0: 5f 66 72 65 65 28 7a 44 65 63 6f 64 65 29 3b 0a  _free(zDecode);.
78b0: 20 20 72 65 74 75 72 6e 20 75 69 64 3b 0a 7d 0a    return uid;.}.
78c0: 0a 2f 2a 0a 2a 2a 20 54 68 69 73 20 72 6f 75 74  ./*.** This rout
78d0: 69 6e 65 20 65 78 61 6d 69 6e 65 73 20 74 68 65  ine examines the
78e0: 20 6c 6f 67 69 6e 20 63 6f 6f 6b 69 65 20 74 6f   login cookie to
78f0: 20 73 65 65 20 69 66 20 69 74 20 65 78 69 73 74   see if it exist
7900: 73 20 61 6e 64 0a 2a 2a 20 69 73 20 76 61 6c 69  s and.** is vali
7910: 64 2e 20 20 49 66 20 74 68 65 20 6c 6f 67 69 6e  d.  If the login
7920: 20 63 6f 6f 6b 69 65 20 63 68 65 63 6b 73 20 6f   cookie checks o
7930: 75 74 2c 20 69 74 20 74 68 65 6e 20 73 65 74 73  ut, it then sets
7940: 20 67 6c 6f 62 61 6c 0a 2a 2a 20 76 61 72 69 61   global.** varia
7950: 62 6c 65 73 20 61 70 70 72 6f 70 72 69 61 74 65  bles appropriate
7960: 6c 79 2e 0a 2a 2a 0a 2a 2a 20 20 20 20 67 2e 75  ly..**.**    g.u
7970: 73 65 72 55 69 64 20 20 20 20 20 20 44 61 74 61  serUid      Data
7980: 62 61 73 65 20 55 53 45 52 2e 55 49 44 20 76 61  base USER.UID va
7990: 6c 75 65 2e 20 20 4d 69 67 68 74 20 62 65 20 2d  lue.  Might be -
79a0: 31 20 66 6f 72 20 22 6e 6f 62 6f 64 79 22 0a 2a  1 for "nobody".*
79b0: 2a 20 20 20 20 67 2e 7a 4c 6f 67 69 6e 20 20 20  *    g.zLogin   
79c0: 20 20 20 20 44 61 74 61 62 61 73 65 20 55 53 45      Database USE
79d0: 52 2e 4c 4f 47 49 4e 20 76 61 6c 75 65 2e 20 20  R.LOGIN value.  
79e0: 4e 55 4c 4c 20 66 6f 72 20 75 73 65 72 20 22 6e  NULL for user "n
79f0: 6f 62 6f 64 79 22 0a 2a 2a 20 20 20 20 67 2e 70  obody".**    g.p
7a00: 65 72 6d 20 20 20 20 20 20 20 20 20 50 65 72 6d  erm         Perm
7a10: 69 73 73 69 6f 6e 73 20 67 72 61 6e 74 65 64 20  issions granted 
7a20: 74 6f 20 74 68 69 73 20 75 73 65 72 0a 2a 2a 20  to this user.** 
7a30: 20 20 20 67 2e 61 6e 6f 6e 20 20 20 20 20 20 20     g.anon       
7a40: 20 20 50 65 72 6d 69 73 73 69 6f 6e 73 20 74 68    Permissions th
7a50: 61 74 20 77 6f 75 6c 64 20 62 65 20 61 76 61 69  at would be avai
7a60: 6c 61 62 6c 65 20 74 6f 20 61 6e 6f 6e 79 6d 6f  lable to anonymo
7a70: 75 73 0a 2a 2a 20 20 20 20 67 2e 69 73 48 75 6d  us.**    g.isHum
7a80: 61 6e 20 20 20 20 20 20 54 72 75 65 20 69 66 20  an      True if 
7a90: 74 68 65 20 75 73 65 72 20 69 73 20 68 75 6d 61  the user is huma
7aa0: 6e 2c 20 6e 6f 74 20 61 20 73 70 69 64 65 72 20  n, not a spider 
7ab0: 6f 72 20 72 6f 62 6f 74 0a 2a 2a 0a 2a 2f 0a 76  or robot.**.*/.v
7ac0: 6f 69 64 20 6c 6f 67 69 6e 5f 63 68 65 63 6b 5f  oid login_check_
7ad0: 63 72 65 64 65 6e 74 69 61 6c 73 28 76 6f 69 64  credentials(void
7ae0: 29 7b 0a 20 20 69 6e 74 20 75 69 64 20 3d 20 30  ){.  int uid = 0
7af0: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ;               
7b00: 20 20 20 2f 2a 20 55 73 65 72 20 69 64 20 2a 2f     /* User id */
7b10: 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a  .  const char *z
7b20: 43 6f 6f 6b 69 65 3b 20 20 20 20 20 20 20 20 20  Cookie;         
7b30: 20 2f 2a 20 54 65 78 74 20 6f 66 20 74 68 65 20   /* Text of the 
7b40: 6c 6f 67 69 6e 20 63 6f 6f 6b 69 65 20 2a 2f 0a  login cookie */.
7b50: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 49    const char *zI
7b60: 70 41 64 64 72 3b 20 20 20 20 20 20 20 20 20 20  pAddr;          
7b70: 2f 2a 20 52 61 77 20 49 50 20 61 64 64 72 65 73  /* Raw IP addres
7b80: 73 20 6f 66 20 74 68 65 20 72 65 71 75 65 73 74  s of the request
7b90: 6f 72 20 2a 2f 0a 20 20 63 68 61 72 20 2a 7a 52  or */.  char *zR
7ba0: 65 6d 6f 74 65 41 64 64 72 3b 20 20 20 20 20 20  emoteAddr;      
7bb0: 20 20 20 20 20 20 2f 2a 20 41 62 62 72 65 76 69        /* Abbrevi
7bc0: 61 74 65 64 20 49 50 20 61 64 64 72 65 73 73 20  ated IP address 
7bd0: 6f 66 20 74 68 65 20 72 65 71 75 65 73 74 6f 72  of the requestor
7be0: 20 2a 2f 0a 20 20 63 6f 6e 73 74 20 63 68 61 72   */.  const char
7bf0: 20 2a 7a 43 61 70 20 3d 20 30 3b 20 20 20 20 20   *zCap = 0;     
7c00: 20 20 20 20 2f 2a 20 43 61 70 61 62 69 6c 69 74      /* Capabilit
7c10: 79 20 73 74 72 69 6e 67 20 2a 2f 0a 20 20 63 6f  y string */.  co
7c20: 6e 73 74 20 63 68 61 72 20 2a 7a 50 75 62 6c 69  nst char *zPubli
7c30: 63 50 61 67 65 73 20 3d 20 30 3b 20 2f 2a 20 47  cPages = 0; /* G
7c40: 4c 4f 42 20 70 61 74 74 65 72 6e 73 20 6f 66 20  LOB patterns of 
7c50: 70 75 62 6c 69 63 20 70 61 67 65 73 20 2a 2f 0a  public pages */.
7c60: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 4c    const char *zL
7c70: 6f 67 69 6e 20 3d 20 30 3b 20 20 20 20 20 20 20  ogin = 0;       
7c80: 2f 2a 20 4c 6f 67 69 6e 20 75 73 65 72 20 66 6f  /* Login user fo
7c90: 72 20 63 72 65 64 65 6e 74 69 61 6c 73 20 2a 2f  r credentials */
7ca0: 0a 0a 20 20 2f 2a 20 4f 6e 6c 79 20 72 75 6e 20  ..  /* Only run 
7cb0: 74 68 69 73 20 63 68 65 63 6b 20 6f 6e 63 65 2e  this check once.
7cc0: 20 20 2a 2f 0a 20 20 69 66 28 20 67 2e 75 73 65    */.  if( g.use
7cd0: 72 55 69 64 21 3d 30 20 29 20 72 65 74 75 72 6e  rUid!=0 ) return
7ce0: 3b 0a 0a 20 20 73 71 6c 69 74 65 33 5f 63 72 65  ;..  sqlite3_cre
7cf0: 61 74 65 5f 66 75 6e 63 74 69 6f 6e 28 67 2e 64  ate_function(g.d
7d00: 62 2c 20 22 63 6f 6e 73 74 61 6e 74 5f 74 69 6d  b, "constant_tim
7d10: 65 5f 63 6d 70 22 2c 20 32 2c 20 53 51 4c 49 54  e_cmp", 2, SQLIT
7d20: 45 5f 55 54 46 38 2c 20 30 2c 0a 20 20 20 20 20  E_UTF8, 0,.     
7d30: 20 20 20 20 20 20 20 20 20 20 20 20 20 63 6f 6e               con
7d40: 73 74 61 6e 74 5f 74 69 6d 65 5f 63 6d 70 5f 66  stant_time_cmp_f
7d50: 75 6e 63 74 69 6f 6e 2c 20 30 2c 20 30 29 3b 0a  unction, 0, 0);.
7d60: 0a 20 20 2f 2a 20 49 66 20 74 68 65 20 48 54 54  .  /* If the HTT
7d70: 50 20 63 6f 6e 6e 65 63 74 69 6f 6e 20 69 73 20  P connection is 
7d80: 63 6f 6d 69 6e 67 20 6f 76 65 72 20 31 32 37 2e  coming over 127.
7d90: 30 2e 30 2e 31 20 61 6e 64 20 69 66 0a 20 20 2a  0.0.1 and if.  *
7da0: 2a 20 6c 6f 63 61 6c 20 6c 6f 67 69 6e 20 69 73  * local login is
7db0: 20 64 69 73 61 62 6c 65 64 20 61 6e 64 20 69 66   disabled and if
7dc0: 20 77 65 20 61 72 65 20 75 73 69 6e 67 20 48 54   we are using HT
7dd0: 54 50 20 61 6e 64 20 6e 6f 74 20 48 54 54 50 53  TP and not HTTPS
7de0: 2c 0a 20 20 2a 2a 20 74 68 65 6e 20 74 68 65 72  ,.  ** then ther
7df0: 65 20 69 73 20 6e 6f 20 6e 65 65 64 20 74 6f 20  e is no need to 
7e00: 63 68 65 63 6b 20 75 73 65 72 20 63 72 65 64 65  check user crede
7e10: 6e 74 69 61 6c 73 2e 0a 20 20 2a 2a 0a 20 20 2a  ntials..  **.  *
7e20: 2a 20 54 68 69 73 20 66 65 61 74 75 72 65 20 61  * This feature a
7e30: 6c 6c 6f 77 73 20 74 68 65 20 22 66 6f 73 73 69  llows the "fossi
7e40: 6c 20 75 69 22 20 63 6f 6d 6d 61 6e 64 20 74 6f  l ui" command to
7e50: 20 67 69 76 65 20 74 68 65 20 75 73 65 72 0a 20   give the user. 
7e60: 20 2a 2a 20 66 75 6c 6c 20 61 63 63 65 73 73 20   ** full access 
7e70: 72 69 67 68 74 73 20 77 69 74 68 6f 75 74 20 68  rights without h
7e80: 61 76 69 6e 67 20 74 6f 20 6c 6f 67 20 69 6e 2e  aving to log in.
7e90: 0a 20 20 2a 2f 0a 20 20 7a 52 65 6d 6f 74 65 41  .  */.  zRemoteA
7ea0: 64 64 72 20 3d 20 69 70 50 72 65 66 69 78 28 7a  ddr = ipPrefix(z
7eb0: 49 70 41 64 64 72 20 3d 20 50 44 28 22 52 45 4d  IpAddr = PD("REM
7ec0: 4f 54 45 5f 41 44 44 52 22 2c 22 6e 69 6c 22 29  OTE_ADDR","nil")
7ed0: 29 3b 0a 20 20 69 66 28 20 28 20 63 67 69 5f 69  );.  if( ( cgi_i
7ee0: 73 5f 6c 6f 6f 70 62 61 63 6b 28 7a 49 70 41 64  s_loopback(zIpAd
7ef0: 64 72 29 0a 20 20 20 20 20 20 20 7c 7c 20 28 67  dr).       || (g
7f00: 2e 66 53 73 68 43 6c 69 65 6e 74 20 26 20 43 47  .fSshClient & CG
7f10: 49 5f 53 53 48 5f 43 4c 49 45 4e 54 29 21 3d 30  I_SSH_CLIENT)!=0
7f20: 20 29 0a 20 20 20 26 26 20 67 2e 75 73 65 4c 6f   ).   && g.useLo
7f30: 63 61 6c 61 75 74 68 0a 20 20 20 26 26 20 64 62  calauth.   && db
7f40: 5f 67 65 74 5f 69 6e 74 28 22 6c 6f 63 61 6c 61  _get_int("locala
7f50: 75 74 68 22 2c 30 29 3d 3d 30 0a 20 20 20 26 26  uth",0)==0.   &&
7f60: 20 50 28 22 48 54 54 50 53 22 29 3d 3d 30 0a 20   P("HTTPS")==0. 
7f70: 20 29 7b 0a 20 20 20 20 69 66 28 20 67 2e 6c 6f   ){.    if( g.lo
7f80: 63 61 6c 4f 70 65 6e 20 29 20 7a 4c 6f 67 69 6e  calOpen ) zLogin
7f90: 20 3d 20 64 62 5f 6c 67 65 74 28 22 64 65 66 61   = db_lget("defa
7fa0: 75 6c 74 2d 75 73 65 72 22 2c 30 29 3b 0a 20 20  ult-user",0);.  
7fb0: 20 20 69 66 28 20 7a 4c 6f 67 69 6e 21 3d 30 20    if( zLogin!=0 
7fc0: 29 7b 0a 20 20 20 20 20 20 75 69 64 20 3d 20 64  ){.      uid = d
7fd0: 62 5f 69 6e 74 28 30 2c 20 22 53 45 4c 45 43 54  b_int(0, "SELECT
7fe0: 20 75 69 64 20 46 52 4f 4d 20 75 73 65 72 20 57   uid FROM user W
7ff0: 48 45 52 45 20 6c 6f 67 69 6e 3d 25 51 22 2c 20  HERE login=%Q", 
8000: 7a 4c 6f 67 69 6e 29 3b 0a 20 20 20 20 7d 65 6c  zLogin);.    }el
8010: 73 65 7b 0a 20 20 20 20 20 20 75 69 64 20 3d 20  se{.      uid = 
8020: 64 62 5f 69 6e 74 28 30 2c 20 22 53 45 4c 45 43  db_int(0, "SELEC
8030: 54 20 75 69 64 20 46 52 4f 4d 20 75 73 65 72 20  T uid FROM user 
8040: 57 48 45 52 45 20 63 61 70 20 4c 49 4b 45 20 27  WHERE cap LIKE '
8050: 25 25 73 25 25 27 22 29 3b 0a 20 20 20 20 7d 0a  %%s%%'");.    }.
8060: 20 20 20 20 67 2e 7a 4c 6f 67 69 6e 20 3d 20 64      g.zLogin = d
8070: 62 5f 74 65 78 74 28 22 3f 22 2c 20 22 53 45 4c  b_text("?", "SEL
8080: 45 43 54 20 6c 6f 67 69 6e 20 46 52 4f 4d 20 75  ECT login FROM u
8090: 73 65 72 20 57 48 45 52 45 20 75 69 64 3d 25 64  ser WHERE uid=%d
80a0: 22 2c 20 75 69 64 29 3b 0a 20 20 20 20 7a 43 61  ", uid);.    zCa
80b0: 70 20 3d 20 22 73 78 22 3b 0a 20 20 20 20 67 2e  p = "sx";.    g.
80c0: 6e 6f 50 73 77 64 20 3d 20 31 3b 0a 20 20 20 20  noPswd = 1;.    
80d0: 67 2e 69 73 48 75 6d 61 6e 20 3d 20 31 3b 0a 20  g.isHuman = 1;. 
80e0: 20 20 20 73 71 6c 69 74 65 33 5f 73 6e 70 72 69     sqlite3_snpri
80f0: 6e 74 66 28 73 69 7a 65 6f 66 28 67 2e 7a 43 73  ntf(sizeof(g.zCs
8100: 72 66 54 6f 6b 65 6e 29 2c 20 67 2e 7a 43 73 72  rfToken), g.zCsr
8110: 66 54 6f 6b 65 6e 2c 20 22 6c 6f 63 61 6c 68 6f  fToken, "localho
8120: 73 74 22 29 3b 0a 20 20 7d 0a 0a 20 20 2f 2a 20  st");.  }..  /* 
8130: 43 68 65 63 6b 20 74 68 65 20 6c 6f 67 69 6e 20  Check the login 
8140: 63 6f 6f 6b 69 65 20 74 6f 20 73 65 65 20 69 66  cookie to see if
8150: 20 69 74 20 6d 61 74 63 68 65 73 20 61 20 6b 6e   it matches a kn
8160: 6f 77 6e 20 76 61 6c 69 64 20 75 73 65 72 2e 0a  own valid user..
8170: 20 20 2a 2f 0a 20 20 69 66 28 20 75 69 64 3d 3d    */.  if( uid==
8180: 30 20 26 26 20 28 7a 43 6f 6f 6b 69 65 20 3d 20  0 && (zCookie = 
8190: 50 28 6c 6f 67 69 6e 5f 63 6f 6f 6b 69 65 5f 6e  P(login_cookie_n
81a0: 61 6d 65 28 29 29 29 21 3d 30 20 29 7b 0a 20 20  ame()))!=0 ){.  
81b0: 20 20 2f 2a 20 50 61 72 73 65 20 74 68 65 20 63    /* Parse the c
81c0: 6f 6f 6b 69 65 20 76 61 6c 75 65 20 75 70 20 69  ookie value up i
81d0: 6e 74 6f 20 48 41 53 48 2f 41 52 47 2f 55 53 45  nto HASH/ARG/USE
81e0: 52 20 2a 2f 0a 20 20 20 20 63 68 61 72 20 2a 7a  R */.    char *z
81f0: 48 61 73 68 20 3d 20 66 6f 73 73 69 6c 5f 73 74  Hash = fossil_st
8200: 72 64 75 70 28 7a 43 6f 6f 6b 69 65 29 3b 0a 20  rdup(zCookie);. 
8210: 20 20 20 63 68 61 72 20 2a 7a 41 72 67 20 3d 20     char *zArg = 
8220: 30 3b 0a 20 20 20 20 63 68 61 72 20 2a 7a 55 73  0;.    char *zUs
8230: 65 72 20 3d 20 30 3b 0a 20 20 20 20 69 6e 74 20  er = 0;.    int 
8240: 69 2c 20 63 3b 0a 20 20 20 20 66 6f 72 28 69 3d  i, c;.    for(i=
8250: 30 3b 20 28 63 20 3d 20 7a 48 61 73 68 5b 69 5d  0; (c = zHash[i]
8260: 29 21 3d 30 3b 20 69 2b 2b 29 7b 0a 20 20 20 20  )!=0; i++){.    
8270: 20 20 69 66 28 20 63 3d 3d 27 2f 27 20 29 7b 0a    if( c=='/' ){.
8280: 20 20 20 20 20 20 20 20 7a 48 61 73 68 5b 69 2b          zHash[i+
8290: 2b 5d 20 3d 20 30 3b 0a 20 20 20 20 20 20 20 20  +] = 0;.        
82a0: 69 66 28 20 7a 41 72 67 3d 3d 30 20 29 7b 0a 20  if( zArg==0 ){. 
82b0: 20 20 20 20 20 20 20 20 20 7a 41 72 67 20 3d 20           zArg = 
82c0: 26 7a 48 61 73 68 5b 69 5d 3b 0a 20 20 20 20 20  &zHash[i];.     
82d0: 20 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20     }else{.      
82e0: 20 20 20 20 7a 55 73 65 72 20 3d 20 26 7a 48 61      zUser = &zHa
82f0: 73 68 5b 69 5d 3b 0a 20 20 20 20 20 20 20 20 20  sh[i];.         
8300: 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 20 20   break;.        
8310: 7d 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a  }.      }.    }.
8320: 20 20 20 20 69 66 28 20 7a 55 73 65 72 3d 3d 30      if( zUser==0
8330: 20 29 7b 0a 20 20 20 20 20 20 2f 2a 20 49 6e 76   ){.      /* Inv
8340: 61 6c 69 64 20 63 6f 6f 6b 69 65 20 2a 2f 0a 20  alid cookie */. 
8350: 20 20 20 7d 65 6c 73 65 20 69 66 28 20 66 6f 73     }else if( fos
8360: 73 69 6c 5f 73 74 72 63 6d 70 28 7a 55 73 65 72  sil_strcmp(zUser
8370: 2c 20 22 61 6e 6f 6e 79 6d 6f 75 73 22 29 3d 3d  , "anonymous")==
8380: 30 20 29 7b 0a 20 20 20 20 20 20 2f 2a 20 43 6f  0 ){.      /* Co
8390: 6f 6b 69 65 73 20 6f 66 20 74 68 65 20 66 6f 72  okies of the for
83a0: 6d 20 22 48 41 53 48 2f 54 49 4d 45 2f 61 6e 6f  m "HASH/TIME/ano
83b0: 6e 79 6d 6f 75 73 22 2e 20 20 54 68 65 20 54 49  nymous".  The TI
83c0: 4d 45 20 6d 75 73 74 20 6e 6f 74 20 62 65 0a 20  ME must not be. 
83d0: 20 20 20 20 20 2a 2a 20 74 6f 6f 20 6f 6c 64 20       ** too old 
83e0: 61 6e 64 20 74 68 65 20 73 68 61 31 20 68 61 73  and the sha1 has
83f0: 68 20 6f 66 20 54 49 4d 45 2f 49 50 41 44 44 52  h of TIME/IPADDR
8400: 2f 53 45 43 52 45 54 20 6d 75 73 74 20 6d 61 74  /SECRET must mat
8410: 63 68 20 48 41 53 48 2e 0a 20 20 20 20 20 20 2a  ch HASH..      *
8420: 2a 20 53 45 43 52 45 54 20 69 73 20 74 68 65 20  * SECRET is the 
8430: 22 63 61 70 74 63 68 61 2d 73 65 63 72 65 74 22  "captcha-secret"
8440: 20 76 61 6c 75 65 20 69 6e 20 74 68 65 20 72 65   value in the re
8450: 70 6f 73 69 74 6f 72 79 2e 0a 20 20 20 20 20 20  pository..      
8460: 2a 2f 0a 20 20 20 20 20 20 64 6f 75 62 6c 65 20  */.      double 
8470: 72 54 69 6d 65 20 3d 20 61 74 6f 66 28 7a 41 72  rTime = atof(zAr
8480: 67 29 3b 0a 20 20 20 20 20 20 42 6c 6f 62 20 62  g);.      Blob b
8490: 3b 0a 20 20 20 20 20 20 62 6c 6f 62 5f 7a 65 72  ;.      blob_zer
84a0: 6f 28 26 62 29 3b 0a 20 20 20 20 20 20 62 6c 6f  o(&b);.      blo
84b0: 62 5f 61 70 70 65 6e 64 66 28 26 62 2c 20 22 25  b_appendf(&b, "%
84c0: 73 2f 25 73 2f 25 73 22 2c 0a 20 20 20 20 20 20  s/%s/%s",.      
84d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 7a 41 72               zAr
84e0: 67 2c 20 7a 52 65 6d 6f 74 65 41 64 64 72 2c 20  g, zRemoteAddr, 
84f0: 64 62 5f 67 65 74 28 22 63 61 70 74 63 68 61 2d  db_get("captcha-
8500: 73 65 63 72 65 74 22 2c 22 22 29 29 3b 0a 20 20  secret",""));.  
8510: 20 20 20 20 73 68 61 31 73 75 6d 5f 62 6c 6f 62      sha1sum_blob
8520: 28 26 62 2c 20 26 62 29 3b 0a 20 20 20 20 20 20  (&b, &b);.      
8530: 69 66 28 20 66 6f 73 73 69 6c 5f 73 74 72 63 6d  if( fossil_strcm
8540: 70 28 7a 48 61 73 68 2c 20 62 6c 6f 62 5f 73 74  p(zHash, blob_st
8550: 72 28 26 62 29 29 3d 3d 30 20 29 7b 0a 20 20 20  r(&b))==0 ){.   
8560: 20 20 20 20 20 75 69 64 20 3d 20 64 62 5f 69 6e       uid = db_in
8570: 74 28 30 2c 0a 20 20 20 20 20 20 20 20 20 20 20  t(0,.           
8580: 20 22 53 45 4c 45 43 54 20 75 69 64 20 46 52 4f   "SELECT uid FRO
8590: 4d 20 75 73 65 72 20 57 48 45 52 45 20 6c 6f 67  M user WHERE log
85a0: 69 6e 3d 27 61 6e 6f 6e 79 6d 6f 75 73 27 22 0a  in='anonymous'".
85b0: 20 20 20 20 20 20 20 20 20 20 20 20 22 20 41 4e              " AN
85c0: 44 20 6c 65 6e 67 74 68 28 63 61 70 29 3e 30 22  D length(cap)>0"
85d0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 22 20 41  .            " A
85e0: 4e 44 20 6c 65 6e 67 74 68 28 70 77 29 3e 30 22  ND length(pw)>0"
85f0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 22 20 41  .            " A
8600: 4e 44 20 25 2e 31 37 67 2b 30 2e 32 35 3e 6a 75  ND %.17g+0.25>ju
8610: 6c 69 61 6e 64 61 79 28 27 6e 6f 77 27 29 22 2c  lianday('now')",
8620: 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 54 69  .            rTi
8630: 6d 65 0a 20 20 20 20 20 20 20 20 29 3b 0a 20 20  me.        );.  
8640: 20 20 20 20 7d 0a 20 20 20 20 20 20 62 6c 6f 62      }.      blob
8650: 5f 72 65 73 65 74 28 26 62 29 3b 0a 20 20 20 20  _reset(&b);.    
8660: 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 2f 2a 20  }else{.      /* 
8670: 43 6f 6f 6b 69 65 73 20 6f 66 20 74 68 65 20 66  Cookies of the f
8680: 6f 72 6d 20 22 48 41 53 48 2f 43 4f 44 45 2f 55  orm "HASH/CODE/U
8690: 53 45 52 22 2e 20 20 53 65 61 72 63 68 20 66 69  SER".  Search fi
86a0: 72 73 74 20 69 6e 20 74 68 65 0a 20 20 20 20 20  rst in the.     
86b0: 20 2a 2a 20 6c 6f 63 61 6c 20 75 73 65 72 20 74   ** local user t
86c0: 61 62 6c 65 2c 20 74 68 65 6e 20 74 68 65 20 75  able, then the u
86d0: 73 65 72 20 74 61 62 6c 65 20 66 6f 72 20 70 72  ser table for pr
86e0: 6f 6a 65 63 74 20 43 4f 44 45 20 69 66 20 77 65  oject CODE if we
86f0: 0a 20 20 20 20 20 20 2a 2a 20 61 72 65 20 70 61  .      ** are pa
8700: 72 74 20 6f 66 20 61 20 6c 6f 67 69 6e 2d 67 72  rt of a login-gr
8710: 6f 75 70 2e 0a 20 20 20 20 20 20 2a 2f 0a 20 20  oup..      */.  
8720: 20 20 20 20 75 69 64 20 3d 20 6c 6f 67 69 6e 5f      uid = login_
8730: 66 69 6e 64 5f 75 73 65 72 28 7a 55 73 65 72 2c  find_user(zUser,
8740: 20 7a 48 61 73 68 2c 20 7a 52 65 6d 6f 74 65 41   zHash, zRemoteA
8750: 64 64 72 29 3b 0a 20 20 20 20 20 20 69 66 28 20  ddr);.      if( 
8760: 75 69 64 3d 3d 30 20 26 26 20 6c 6f 67 69 6e 5f  uid==0 && login_
8770: 74 72 61 6e 73 66 65 72 5f 63 72 65 64 65 6e 74  transfer_credent
8780: 69 61 6c 73 28 7a 55 73 65 72 2c 7a 41 72 67 2c  ials(zUser,zArg,
8790: 7a 48 61 73 68 2c 7a 52 65 6d 6f 74 65 41 64 64  zHash,zRemoteAdd
87a0: 72 29 20 29 7b 0a 20 20 20 20 20 20 20 20 75 69  r) ){.        ui
87b0: 64 20 3d 20 6c 6f 67 69 6e 5f 66 69 6e 64 5f 75  d = login_find_u
87c0: 73 65 72 28 7a 55 73 65 72 2c 20 7a 48 61 73 68  ser(zUser, zHash
87d0: 2c 20 7a 52 65 6d 6f 74 65 41 64 64 72 29 3b 0a  , zRemoteAddr);.
87e0: 20 20 20 20 20 20 20 20 69 66 28 20 75 69 64 20          if( uid 
87f0: 29 20 72 65 63 6f 72 64 5f 6c 6f 67 69 6e 5f 61  ) record_login_a
8800: 74 74 65 6d 70 74 28 7a 55 73 65 72 2c 20 7a 49  ttempt(zUser, zI
8810: 70 41 64 64 72 2c 20 31 29 3b 0a 20 20 20 20 20  pAddr, 1);.     
8820: 20 7d 0a 20 20 20 20 7d 0a 20 20 20 20 73 71 6c   }.    }.    sql
8830: 69 74 65 33 5f 73 6e 70 72 69 6e 74 66 28 73 69  ite3_snprintf(si
8840: 7a 65 6f 66 28 67 2e 7a 43 73 72 66 54 6f 6b 65  zeof(g.zCsrfToke
8850: 6e 29 2c 20 67 2e 7a 43 73 72 66 54 6f 6b 65 6e  n), g.zCsrfToken
8860: 2c 20 22 25 2e 31 30 73 22 2c 20 7a 48 61 73 68  , "%.10s", zHash
8870: 29 3b 0a 20 20 7d 0a 0a 20 20 2f 2a 20 49 66 20  );.  }..  /* If 
8880: 6e 6f 20 75 73 65 72 20 66 6f 75 6e 64 20 61 6e  no user found an
8890: 64 20 74 68 65 20 52 45 4d 4f 54 45 5f 55 53 45  d the REMOTE_USE
88a0: 52 20 65 6e 76 69 72 6f 6e 6d 65 6e 74 20 76 61  R environment va
88b0: 72 69 61 62 6c 65 20 69 73 20 73 65 74 2c 0a 20  riable is set,. 
88c0: 20 2a 2a 20 74 68 65 6e 20 61 63 63 65 70 74 20   ** then accept 
88d0: 74 68 65 20 76 61 6c 75 65 20 6f 66 20 52 45 4d  the value of REM
88e0: 4f 54 45 5f 55 53 45 52 20 61 73 20 74 68 65 20  OTE_USER as the 
88f0: 75 73 65 72 2e 0a 20 20 2a 2f 0a 20 20 69 66 28  user..  */.  if(
8900: 20 75 69 64 3d 3d 30 20 29 7b 0a 20 20 20 20 63   uid==0 ){.    c
8910: 6f 6e 73 74 20 63 68 61 72 20 2a 7a 52 65 6d 6f  onst char *zRemo
8920: 74 65 55 73 65 72 20 3d 20 50 28 22 52 45 4d 4f  teUser = P("REMO
8930: 54 45 5f 55 53 45 52 22 29 3b 0a 20 20 20 20 69  TE_USER");.    i
8940: 66 28 20 7a 52 65 6d 6f 74 65 55 73 65 72 20 26  f( zRemoteUser &
8950: 26 20 64 62 5f 67 65 74 5f 62 6f 6f 6c 65 61 6e  & db_get_boolean
8960: 28 22 72 65 6d 6f 74 65 5f 75 73 65 72 5f 6f 6b  ("remote_user_ok
8970: 22 2c 30 29 20 29 7b 0a 20 20 20 20 20 20 75 69  ",0) ){.      ui
8980: 64 20 3d 20 64 62 5f 69 6e 74 28 30 2c 20 22 53  d = db_int(0, "S
8990: 45 4c 45 43 54 20 75 69 64 20 46 52 4f 4d 20 75  ELECT uid FROM u
89a0: 73 65 72 20 57 48 45 52 45 20 6c 6f 67 69 6e 3d  ser WHERE login=
89b0: 25 51 22 0a 20 20 20 20 20 20 20 20 20 20 20 20  %Q".            
89c0: 20 20 20 20 20 20 20 20 20 20 22 20 41 4e 44 20            " AND 
89d0: 6c 65 6e 67 74 68 28 63 61 70 29 3e 30 20 41 4e  length(cap)>0 AN
89e0: 44 20 6c 65 6e 67 74 68 28 70 77 29 3e 30 22 2c  D length(pw)>0",
89f0: 20 7a 52 65 6d 6f 74 65 55 73 65 72 29 3b 0a 20   zRemoteUser);. 
8a00: 20 20 20 7d 0a 20 20 7d 0a 0a 20 20 2f 2a 20 49     }.  }..  /* I
8a10: 66 20 74 68 65 20 72 65 71 75 65 73 74 20 64 69  f the request di
8a20: 64 6e 27 74 20 70 72 6f 76 69 64 65 20 61 20 6c  dn't provide a l
8a30: 6f 67 69 6e 20 63 6f 6f 6b 69 65 20 6f 72 20 74  ogin cookie or t
8a40: 68 65 20 6c 6f 67 69 6e 20 63 6f 6f 6b 69 65 20  he login cookie 
8a50: 64 69 64 6e 27 74 0a 20 20 2a 2a 20 6d 61 74 63  didn't.  ** matc
8a60: 68 20 61 20 6b 6e 6f 77 6e 20 76 61 6c 69 64 20  h a known valid 
8a70: 75 73 65 72 2c 20 63 68 65 63 6b 20 74 68 65 20  user, check the 
8a80: 48 54 54 50 20 22 41 75 74 68 6f 72 69 7a 61 74  HTTP "Authorizat
8a90: 69 6f 6e 22 20 68 65 61 64 65 72 20 61 6e 64 0a  ion" header and.
8aa0: 20 20 2a 2a 20 73 65 65 20 69 66 20 74 68 6f 73    ** see if thos
8ab0: 65 20 63 72 65 64 65 6e 74 69 61 6c 73 20 61 72  e credentials ar
8ac0: 65 20 76 61 6c 69 64 20 66 6f 72 20 61 20 6b 6e  e valid for a kn
8ad0: 6f 77 6e 20 75 73 65 72 2e 0a 20 20 2a 2f 0a 20  own user..  */. 
8ae0: 20 69 66 28 20 75 69 64 3d 3d 30 20 26 26 20 64   if( uid==0 && d
8af0: 62 5f 67 65 74 5f 62 6f 6f 6c 65 61 6e 28 22 68  b_get_boolean("h
8b00: 74 74 70 5f 61 75 74 68 65 6e 74 69 63 61 74 69  ttp_authenticati
8b10: 6f 6e 5f 6f 6b 22 2c 30 29 20 29 7b 0a 20 20 20  on_ok",0) ){.   
8b20: 20 75 69 64 20 3d 20 6c 6f 67 69 63 5f 62 61 73   uid = logic_bas
8b30: 69 63 5f 61 75 74 68 65 6e 74 69 63 61 74 69 6f  ic_authenticatio
8b40: 6e 28 7a 49 70 41 64 64 72 29 3b 0a 20 20 7d 0a  n(zIpAddr);.  }.
8b50: 0a 20 20 2f 2a 20 49 66 20 6e 6f 20 75 73 65 72  .  /* If no user
8b60: 20 66 6f 75 6e 64 20 79 65 74 2c 20 74 72 79 20   found yet, try 
8b70: 74 6f 20 6c 6f 67 20 69 6e 20 61 73 20 22 6e 6f  to log in as "no
8b80: 62 6f 64 79 22 20 2a 2f 0a 20 20 69 66 28 20 75  body" */.  if( u
8b90: 69 64 3d 3d 30 20 29 7b 0a 20 20 20 20 75 69 64  id==0 ){.    uid
8ba0: 20 3d 20 64 62 5f 69 6e 74 28 30 2c 20 22 53 45   = db_int(0, "SE
8bb0: 4c 45 43 54 20 75 69 64 20 46 52 4f 4d 20 75 73  LECT uid FROM us
8bc0: 65 72 20 57 48 45 52 45 20 6c 6f 67 69 6e 3d 27  er WHERE login='
8bd0: 6e 6f 62 6f 64 79 27 22 29 3b 0a 20 20 20 20 69  nobody'");.    i
8be0: 66 28 20 75 69 64 3d 3d 30 20 29 7b 0a 20 20 20  f( uid==0 ){.   
8bf0: 20 20 20 2f 2a 20 49 66 20 74 68 65 72 65 20 69     /* If there i
8c00: 73 20 6e 6f 20 75 73 65 72 20 22 6e 6f 62 6f 64  s no user "nobod
8c10: 79 22 2c 20 74 68 65 6e 20 6d 61 6b 65 20 6f 6e  y", then make on
8c20: 65 20 75 70 20 2d 20 77 69 74 68 20 6e 6f 20 70  e up - with no p
8c30: 72 69 76 69 6c 65 67 65 73 20 2a 2f 0a 20 20 20  rivileges */.   
8c40: 20 20 20 75 69 64 20 3d 20 2d 31 3b 0a 20 20 20     uid = -1;.   
8c50: 20 20 20 7a 43 61 70 20 3d 20 22 22 3b 0a 20 20     zCap = "";.  
8c60: 20 20 7d 0a 20 20 20 20 73 71 6c 69 74 65 33 5f    }.    sqlite3_
8c70: 73 6e 70 72 69 6e 74 66 28 73 69 7a 65 6f 66 28  snprintf(sizeof(
8c80: 67 2e 7a 43 73 72 66 54 6f 6b 65 6e 29 2c 20 67  g.zCsrfToken), g
8c90: 2e 7a 43 73 72 66 54 6f 6b 65 6e 2c 20 22 6e 6f  .zCsrfToken, "no
8ca0: 6e 65 22 29 3b 0a 20 20 7d 0a 0a 20 20 2f 2a 20  ne");.  }..  /* 
8cb0: 41 74 20 74 68 69 73 20 70 6f 69 6e 74 2c 20 77  At this point, w
8cc0: 65 20 6b 6e 6f 77 20 74 68 61 74 20 75 69 64 21  e know that uid!
8cd0: 3d 30 2e 20 20 46 69 6e 64 20 74 68 65 20 70 72  =0.  Find the pr
8ce0: 69 76 69 6c 65 67 65 73 20 61 73 73 6f 63 69 61  ivileges associa
8cf0: 74 65 64 0a 20 20 2a 2a 20 77 69 74 68 20 75 73  ted.  ** with us
8d00: 65 72 20 75 69 64 2e 0a 20 20 2a 2f 0a 20 20 61  er uid..  */.  a
8d10: 73 73 65 72 74 28 20 75 69 64 21 3d 30 20 29 3b  ssert( uid!=0 );
8d20: 0a 20 20 69 66 28 20 7a 43 61 70 3d 3d 30 20 29  .  if( zCap==0 )
8d30: 7b 0a 20 20 20 20 53 74 6d 74 20 73 3b 0a 20 20  {.    Stmt s;.  
8d40: 20 20 64 62 5f 70 72 65 70 61 72 65 28 26 73 2c    db_prepare(&s,
8d50: 20 22 53 45 4c 45 43 54 20 6c 6f 67 69 6e 2c 20   "SELECT login, 
8d60: 63 61 70 20 46 52 4f 4d 20 75 73 65 72 20 57 48  cap FROM user WH
8d70: 45 52 45 20 75 69 64 3d 25 64 22 2c 20 75 69 64  ERE uid=%d", uid
8d80: 29 3b 0a 20 20 20 20 69 66 28 20 64 62 5f 73 74  );.    if( db_st
8d90: 65 70 28 26 73 29 3d 3d 53 51 4c 49 54 45 5f 52  ep(&s)==SQLITE_R
8da0: 4f 57 20 29 7b 0a 20 20 20 20 20 20 67 2e 7a 4c  OW ){.      g.zL
8db0: 6f 67 69 6e 20 3d 20 64 62 5f 63 6f 6c 75 6d 6e  ogin = db_column
8dc0: 5f 6d 61 6c 6c 6f 63 28 26 73 2c 20 30 29 3b 0a  _malloc(&s, 0);.
8dd0: 20 20 20 20 20 20 7a 43 61 70 20 3d 20 64 62 5f        zCap = db_
8de0: 63 6f 6c 75 6d 6e 5f 6d 61 6c 6c 6f 63 28 26 73  column_malloc(&s
8df0: 2c 20 31 29 3b 0a 20 20 20 20 7d 0a 20 20 20 20  , 1);.    }.    
8e00: 64 62 5f 66 69 6e 61 6c 69 7a 65 28 26 73 29 3b  db_finalize(&s);
8e10: 0a 20 20 20 20 69 66 28 20 7a 43 61 70 3d 3d 30  .    if( zCap==0
8e20: 20 29 7b 0a 20 20 20 20 20 20 7a 43 61 70 20 3d   ){.      zCap =
8e30: 20 22 22 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 20   "";.    }.  }. 
8e40: 20 69 66 28 20 67 2e 66 48 74 74 70 54 72 61 63   if( g.fHttpTrac
8e50: 65 20 26 26 20 67 2e 7a 4c 6f 67 69 6e 20 29 7b  e && g.zLogin ){
8e60: 0a 20 20 20 20 66 70 72 69 6e 74 66 28 73 74 64  .    fprintf(std
8e70: 65 72 72 2c 20 22 23 20 6c 6f 67 69 6e 3a 20 5b  err, "# login: [
8e80: 25 73 5d 20 77 69 74 68 20 63 61 70 61 62 69 6c  %s] with capabil
8e90: 69 74 69 65 73 20 5b 25 73 5d 5c 6e 22 2c 20 67  ities [%s]\n", g
8ea0: 2e 7a 4c 6f 67 69 6e 2c 20 7a 43 61 70 29 3b 0a  .zLogin, zCap);.
8eb0: 20 20 7d 0a 0a 20 20 2f 2a 20 53 65 74 20 74 68    }..  /* Set th
8ec0: 65 20 67 6c 6f 62 61 6c 20 76 61 72 69 61 62 6c  e global variabl
8ed0: 65 73 20 72 65 63 6f 72 64 69 6e 67 20 74 68 65  es recording the
8ee0: 20 75 73 65 72 69 64 20 61 6e 64 20 6c 6f 67 69   userid and logi
8ef0: 6e 2e 20 20 54 68 65 0a 20 20 2a 2a 20 22 6e 6f  n.  The.  ** "no
8f00: 62 6f 64 79 22 20 75 73 65 72 20 69 73 20 61 20  body" user is a 
8f10: 73 70 65 63 69 61 6c 20 63 61 73 65 20 69 6e 20  special case in 
8f20: 74 68 61 74 20 67 2e 7a 4c 6f 67 69 6e 3d 3d 30  that g.zLogin==0
8f30: 2e 0a 20 20 2a 2f 0a 20 20 67 2e 75 73 65 72 55  ..  */.  g.userU
8f40: 69 64 20 3d 20 75 69 64 3b 0a 20 20 69 66 28 20  id = uid;.  if( 
8f50: 66 6f 73 73 69 6c 5f 73 74 72 63 6d 70 28 67 2e  fossil_strcmp(g.
8f60: 7a 4c 6f 67 69 6e 2c 22 6e 6f 62 6f 64 79 22 29  zLogin,"nobody")
8f70: 3d 3d 30 20 29 7b 0a 20 20 20 20 67 2e 7a 4c 6f  ==0 ){.    g.zLo
8f80: 67 69 6e 20 3d 20 30 3b 0a 20 20 7d 0a 20 20 69  gin = 0;.  }.  i
8f90: 66 28 20 50 42 28 22 69 73 72 6f 62 6f 74 22 29  f( PB("isrobot")
8fa0: 20 29 7b 0a 20 20 20 20 67 2e 69 73 48 75 6d 61   ){.    g.isHuma
8fb0: 6e 20 3d 20 30 3b 0a 20 20 7d 65 6c 73 65 20 69  n = 0;.  }else i
8fc0: 66 28 20 67 2e 7a 4c 6f 67 69 6e 3d 3d 30 20 29  f( g.zLogin==0 )
8fd0: 7b 0a 20 20 20 20 67 2e 69 73 48 75 6d 61 6e 20  {.    g.isHuman 
8fe0: 3d 20 69 73 48 75 6d 61 6e 28 50 28 22 48 54 54  = isHuman(P("HTT
8ff0: 50 5f 55 53 45 52 5f 41 47 45 4e 54 22 29 29 3b  P_USER_AGENT"));
9000: 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 67 2e  .  }else{.    g.
9010: 69 73 48 75 6d 61 6e 20 3d 20 31 3b 0a 20 20 7d  isHuman = 1;.  }
9020: 0a 0a 20 20 2f 2a 20 53 65 74 20 74 68 65 20 63  ..  /* Set the c
9030: 61 70 61 62 69 6c 69 74 69 65 73 20 2a 2f 0a 20  apabilities */. 
9040: 20 6c 6f 67 69 6e 5f 72 65 70 6c 61 63 65 5f 63   login_replace_c
9050: 61 70 61 62 69 6c 69 74 69 65 73 28 7a 43 61 70  apabilities(zCap
9060: 2c 20 30 29 3b 0a 0a 20 20 2f 2a 20 54 68 65 20  , 0);..  /* The 
9070: 61 75 74 6f 2d 68 79 70 65 72 6c 69 6e 6b 20 73  auto-hyperlink s
9080: 65 74 74 69 6e 67 20 61 6c 6c 6f 77 73 20 68 79  etting allows hy
9090: 70 65 72 6c 69 6e 6b 73 20 74 6f 20 62 65 20 64  perlinks to be d
90a0: 69 73 70 6c 61 79 65 64 20 66 6f 72 20 75 73 65  isplayed for use
90b0: 72 73 0a 20 20 2a 2a 20 77 68 6f 20 64 6f 20 6e  rs.  ** who do n
90c0: 6f 74 20 68 61 76 65 20 74 68 65 20 22 68 22 20  ot have the "h" 
90d0: 70 65 72 6d 69 73 73 69 6f 6e 20 61 73 20 6c 6f  permission as lo
90e0: 6e 67 20 61 73 20 74 68 65 69 72 20 55 73 65 72  ng as their User
90f0: 41 67 65 6e 74 20 73 74 72 69 6e 67 0a 20 20 2a  Agent string.  *
9100: 2a 20 6d 61 6b 65 73 20 69 74 20 61 70 70 65 61  * makes it appea
9110: 72 20 74 68 61 74 20 74 68 65 79 20 61 72 65 20  r that they are 
9120: 68 75 6d 61 6e 2e 20 20 43 68 65 63 6b 20 74 6f  human.  Check to
9130: 20 73 65 65 20 69 66 20 61 75 74 6f 2d 68 79 70   see if auto-hyp
9140: 65 72 6c 69 6e 6b 20 69 73 0a 20 20 2a 2a 20 65  erlink is.  ** e
9150: 6e 61 62 6c 65 64 20 66 6f 72 20 74 68 69 73 20  nabled for this 
9160: 72 65 70 6f 73 69 74 6f 72 79 20 61 6e 64 20 6d  repository and m
9170: 61 6b 65 20 61 70 70 72 6f 70 72 69 61 74 65 20  ake appropriate 
9180: 61 64 6a 75 73 74 6d 65 6e 74 73 20 74 6f 20 74  adjustments to t
9190: 68 65 0a 20 20 2a 2a 20 70 65 72 6d 69 73 73 69  he.  ** permissi
91a0: 6f 6e 20 66 6c 61 67 73 20 69 66 20 69 74 20 69  on flags if it i
91b0: 73 2e 20 20 54 68 69 73 20 73 68 6f 75 6c 64 20  s.  This should 
91c0: 62 65 20 64 6f 6e 65 20 62 65 66 6f 72 65 20 74  be done before t
91d0: 68 65 20 70 65 72 6d 69 73 73 69 6f 6e 73 0a 20  he permissions. 
91e0: 20 2a 2a 20 61 72 65 20 28 70 6f 74 65 6e 74 69   ** are (potenti
91f0: 61 6c 6c 79 29 20 63 6f 70 69 65 64 20 74 6f 20  ally) copied to 
9200: 74 68 65 20 61 6e 6f 6e 79 6d 6f 75 73 20 70 65  the anonymous pe
9210: 72 6d 69 73 73 69 6f 6e 20 73 65 74 3b 20 6f 74  rmission set; ot
9220: 68 65 72 77 69 73 65 2c 0a 20 20 2a 2a 20 74 68  herwise,.  ** th
9230: 6f 73 65 20 77 69 6c 6c 20 62 65 20 6f 75 74 2d  ose will be out-
9240: 6f 66 2d 73 79 6e 63 2e 0a 20 20 2a 2f 0a 20 20  of-sync..  */.  
9250: 69 66 28 20 7a 43 61 70 5b 30 5d 0a 20 20 20 26  if( zCap[0].   &
9260: 26 20 21 67 2e 70 65 72 6d 2e 48 79 70 65 72 6c  & !g.perm.Hyperl
9270: 69 6e 6b 0a 20 20 20 26 26 20 67 2e 69 73 48 75  ink.   && g.isHu
9280: 6d 61 6e 0a 20 20 20 26 26 20 64 62 5f 67 65 74  man.   && db_get
9290: 5f 62 6f 6f 6c 65 61 6e 28 22 61 75 74 6f 2d 68  _boolean("auto-h
92a0: 79 70 65 72 6c 69 6e 6b 22 2c 31 29 0a 20 20 29  yperlink",1).  )
92b0: 7b 0a 20 20 20 20 67 2e 70 65 72 6d 2e 48 79 70  {.    g.perm.Hyp
92c0: 65 72 6c 69 6e 6b 20 3d 20 31 3b 0a 20 20 20 20  erlink = 1;.    
92d0: 67 2e 6a 61 76 61 73 63 72 69 70 74 48 79 70 65  g.javascriptHype
92e0: 72 6c 69 6e 6b 20 3d 20 31 3b 0a 20 20 7d 0a 0a  rlink = 1;.  }..
92f0: 20 20 2f 2a 0a 20 20 2a 2a 20 41 74 20 74 68 69    /*.  ** At thi
9300: 73 20 70 6f 69 6e 74 2c 20 74 68 65 20 63 61 70  s point, the cap
9310: 61 62 69 6c 69 74 69 65 73 20 66 6f 72 20 74 68  abilities for th
9320: 65 20 6c 6f 67 67 65 64 20 69 6e 20 75 73 65 72  e logged in user
9330: 20 61 72 65 20 6e 6f 74 20 67 6f 69 6e 67 0a 20   are not going. 
9340: 20 2a 2a 20 74 6f 20 62 65 20 6d 6f 64 69 66 69   ** to be modifi
9350: 65 64 20 61 6e 79 6d 6f 72 65 3b 20 74 68 65 72  ed anymore; ther
9360: 65 66 6f 72 65 2c 20 77 65 20 63 61 6e 20 63 6f  efore, we can co
9370: 70 79 20 74 68 65 6d 20 6f 76 65 72 20 74 6f 20  py them over to 
9380: 74 68 65 20 6f 6e 65 73 0a 20 20 2a 2a 20 66 6f  the ones.  ** fo
9390: 72 20 74 68 65 20 61 6e 6f 6e 79 6d 6f 75 73 20  r the anonymous 
93a0: 75 73 65 72 2e 0a 20 20 2a 2a 0a 20 20 2a 2a 20  user..  **.  ** 
93b0: 57 41 52 4e 49 4e 47 3a 20 49 6e 20 74 68 65 20  WARNING: In the 
93c0: 66 75 74 75 72 65 2c 20 70 6c 65 61 73 65 20 64  future, please d
93d0: 6f 20 6e 6f 74 20 61 64 64 20 63 6f 64 65 20 61  o not add code a
93e0: 66 74 65 72 20 74 68 69 73 20 70 6f 69 6e 74 20  fter this point 
93f0: 74 68 61 74 0a 20 20 2a 2a 20 20 20 20 20 20 20  that.  **       
9400: 20 20 20 6d 6f 64 69 66 69 65 73 20 74 68 65 20     modifies the 
9410: 63 61 70 61 62 69 6c 69 74 69 65 73 20 66 6f 72  capabilities for
9420: 20 74 68 65 20 6c 6f 67 67 65 64 20 69 6e 20 75   the logged in u
9430: 73 65 72 2e 0a 20 20 2a 2f 0a 20 20 6c 6f 67 69  ser..  */.  logi
9440: 6e 5f 73 65 74 5f 61 6e 6f 6e 5f 6e 6f 62 6f 64  n_set_anon_nobod
9450: 79 5f 63 61 70 61 62 69 6c 69 74 69 65 73 28 29  y_capabilities()
9460: 3b 0a 0a 20 20 2f 2a 20 49 66 20 74 68 65 20 70  ;..  /* If the p
9470: 75 62 6c 69 63 2d 70 61 67 65 73 20 67 6c 6f 62  ublic-pages glob
9480: 20 70 61 74 74 65 72 6e 20 69 73 20 64 65 66 69   pattern is defi
9490: 6e 65 64 20 61 6e 64 20 52 45 51 55 45 53 54 5f  ned and REQUEST_
94a0: 55 52 49 20 6d 61 74 63 68 65 73 0a 20 20 2a 2a  URI matches.  **
94b0: 20 6f 6e 65 20 6f 66 20 74 68 65 20 67 6c 6f 62   one of the glob
94c0: 73 20 69 6e 20 70 75 62 6c 69 63 2d 70 61 67 65  s in public-page
94d0: 73 2c 20 74 68 65 6e 20 61 6c 73 6f 20 61 64 64  s, then also add
94e0: 20 69 6e 20 61 6c 6c 20 64 65 66 61 75 6c 74 2d   in all default-
94f0: 70 65 72 6d 73 0a 20 20 2a 2a 20 70 65 72 6d 69  perms.  ** permi
9500: 73 73 69 6f 6e 73 2e 0a 20 20 2a 2f 0a 20 20 7a  ssions..  */.  z
9510: 50 75 62 6c 69 63 50 61 67 65 73 20 3d 20 64 62  PublicPages = db
9520: 5f 67 65 74 28 22 70 75 62 6c 69 63 2d 70 61 67  _get("public-pag
9530: 65 73 22 2c 30 29 3b 0a 20 20 69 66 28 20 7a 50  es",0);.  if( zP
9540: 75 62 6c 69 63 50 61 67 65 73 21 3d 30 20 29 7b  ublicPages!=0 ){
9550: 0a 20 20 20 20 47 6c 6f 62 20 2a 70 47 6c 6f 62  .    Glob *pGlob
9560: 20 3d 20 67 6c 6f 62 5f 63 72 65 61 74 65 28 7a   = glob_create(z
9570: 50 75 62 6c 69 63 50 61 67 65 73 29 3b 0a 20 20  PublicPages);.  
9580: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 55    const char *zU
9590: 72 69 20 3d 20 50 44 28 22 52 45 51 55 45 53 54  ri = PD("REQUEST
95a0: 5f 55 52 49 22 2c 22 22 29 3b 0a 20 20 20 20 7a  _URI","");.    z
95b0: 55 72 69 20 2b 3d 20 28 69 6e 74 29 73 74 72 6c  Uri += (int)strl
95c0: 65 6e 28 67 2e 7a 54 6f 70 29 3b 0a 20 20 20 20  en(g.zTop);.    
95d0: 69 66 28 20 67 6c 6f 62 5f 6d 61 74 63 68 28 70  if( glob_match(p
95e0: 47 6c 6f 62 2c 20 7a 55 72 69 29 20 29 7b 0a 20  Glob, zUri) ){. 
95f0: 20 20 20 20 20 6c 6f 67 69 6e 5f 73 65 74 5f 63       login_set_c
9600: 61 70 61 62 69 6c 69 74 69 65 73 28 64 62 5f 67  apabilities(db_g
9610: 65 74 28 22 64 65 66 61 75 6c 74 2d 70 65 72 6d  et("default-perm
9620: 73 22 2c 22 75 22 29 2c 20 30 29 3b 0a 20 20 20  s","u"), 0);.   
9630: 20 7d 0a 20 20 20 20 67 6c 6f 62 5f 66 72 65 65   }.    glob_free
9640: 28 70 47 6c 6f 62 29 3b 0a 20 20 7d 0a 7d 0a 0a  (pGlob);.  }.}..
9650: 2f 2a 0a 2a 2a 20 4d 65 6d 6f 72 79 20 6f 66 20  /*.** Memory of 
9660: 73 65 74 74 69 6e 67 73 0a 2a 2f 0a 73 74 61 74  settings.*/.stat
9670: 69 63 20 69 6e 74 20 6c 6f 67 69 6e 5f 61 6e 6f  ic int login_ano
9680: 6e 5f 6f 6e 63 65 20 3d 20 31 3b 0a 0a 2f 2a 0a  n_once = 1;../*.
9690: 2a 2a 20 41 64 64 20 74 6f 20 67 2e 70 65 72 6d  ** Add to g.perm
96a0: 20 74 68 65 20 64 65 66 61 75 6c 74 20 70 72 69   the default pri
96b0: 76 69 6c 65 67 65 73 20 6f 66 20 75 73 65 72 73  vileges of users
96c0: 20 22 6e 6f 62 6f 64 79 22 20 61 6e 64 2f 6f 72   "nobody" and/or
96d0: 20 22 61 6e 6f 6e 79 6d 6f 75 73 22 0a 2a 2a 20   "anonymous".** 
96e0: 61 73 20 61 70 70 72 6f 70 72 69 61 74 65 20 66  as appropriate f
96f0: 6f 72 20 74 68 65 20 75 73 65 72 20 67 2e 7a 4c  or the user g.zL
9700: 6f 67 69 6e 2e 0a 2a 2a 0a 2a 2a 20 54 68 69 73  ogin..**.** This
9710: 20 72 6f 75 74 69 6e 65 20 61 6c 73 6f 20 73 65   routine also se
9720: 74 73 20 75 70 20 67 2e 61 6e 6f 6e 20 74 6f 20  ts up g.anon to 
9730: 62 65 20 65 69 74 68 65 72 20 61 20 63 6f 70 79  be either a copy
9740: 20 6f 66 20 67 2e 70 65 72 6d 20 66 6f 72 0a 2a   of g.perm for.*
9750: 2a 20 61 6c 6c 20 6c 6f 67 67 65 64 20 69 6e 20  * all logged in 
9760: 75 73 65 73 2c 20 6f 72 20 74 68 65 20 70 72 69  uses, or the pri
9770: 76 69 6c 65 67 65 73 20 74 68 61 74 20 77 6f 75  vileges that wou
9780: 6c 64 20 62 65 20 61 76 61 69 6c 61 62 6c 65 20  ld be available 
9790: 74 6f 20 22 61 6e 6f 6e 79 6d 6f 75 73 22 0a 2a  to "anonymous".*
97a0: 2a 20 69 66 20 67 2e 7a 4c 6f 67 69 6e 3d 3d 30  * if g.zLogin==0
97b0: 20 28 6d 65 61 6e 69 6e 67 20 74 68 61 74 20 74   (meaning that t
97c0: 68 65 20 75 73 65 72 20 69 73 20 22 6e 6f 62 6f  he user is "nobo
97d0: 64 79 22 29 2e 0a 2a 2f 0a 76 6f 69 64 20 6c 6f  dy")..*/.void lo
97e0: 67 69 6e 5f 73 65 74 5f 61 6e 6f 6e 5f 6e 6f 62  gin_set_anon_nob
97f0: 6f 64 79 5f 63 61 70 61 62 69 6c 69 74 69 65 73  ody_capabilities
9800: 28 76 6f 69 64 29 7b 0a 20 20 69 66 28 20 6c 6f  (void){.  if( lo
9810: 67 69 6e 5f 61 6e 6f 6e 5f 6f 6e 63 65 20 29 7b  gin_anon_once ){
9820: 0a 20 20 20 20 63 6f 6e 73 74 20 63 68 61 72 20  .    const char 
9830: 2a 7a 43 61 70 3b 0a 20 20 20 20 2f 2a 20 41 6c  *zCap;.    /* Al
9840: 6c 20 75 73 65 72 73 20 67 65 74 20 70 72 69 76  l users get priv
9850: 69 6c 65 67 65 73 20 66 72 6f 6d 20 22 6e 6f 62  ileges from "nob
9860: 6f 64 79 22 20 2a 2f 0a 20 20 20 20 7a 43 61 70  ody" */.    zCap
9870: 20 3d 20 64 62 5f 74 65 78 74 28 22 22 2c 20 22   = db_text("", "
9880: 53 45 4c 45 43 54 20 63 61 70 20 46 52 4f 4d 20  SELECT cap FROM 
9890: 75 73 65 72 20 57 48 45 52 45 20 6c 6f 67 69 6e  user WHERE login
98a0: 20 3d 20 27 6e 6f 62 6f 64 79 27 22 29 3b 0a 20   = 'nobody'");. 
98b0: 20 20 20 6c 6f 67 69 6e 5f 73 65 74 5f 63 61 70     login_set_cap
98c0: 61 62 69 6c 69 74 69 65 73 28 7a 43 61 70 2c 20  abilities(zCap, 
98d0: 30 29 3b 0a 20 20 20 20 7a 43 61 70 20 3d 20 64  0);.    zCap = d
98e0: 62 5f 74 65 78 74 28 22 22 2c 20 22 53 45 4c 45  b_text("", "SELE
98f0: 43 54 20 63 61 70 20 46 52 4f 4d 20 75 73 65 72  CT cap FROM user
9900: 20 57 48 45 52 45 20 6c 6f 67 69 6e 20 3d 20 27   WHERE login = '
9910: 61 6e 6f 6e 79 6d 6f 75 73 27 22 29 3b 0a 20 20  anonymous'");.  
9920: 20 20 69 66 28 20 67 2e 7a 4c 6f 67 69 6e 20 26    if( g.zLogin &
9930: 26 20 66 6f 73 73 69 6c 5f 73 74 72 63 6d 70 28  & fossil_strcmp(
9940: 67 2e 7a 4c 6f 67 69 6e 2c 20 22 6e 6f 62 6f 64  g.zLogin, "nobod
9950: 79 22 29 21 3d 30 20 29 7b 0a 20 20 20 20 20 20  y")!=0 ){.      
9960: 2f 2a 20 41 6c 6c 20 6c 6f 67 67 65 64 2d 69 6e  /* All logged-in
9970: 20 75 73 65 72 73 20 69 6e 68 65 72 69 74 20 70   users inherit p
9980: 72 69 76 69 6c 65 67 65 73 20 66 72 6f 6d 20 22  rivileges from "
9990: 61 6e 6f 6e 79 6d 6f 75 73 22 20 2a 2f 0a 20 20  anonymous" */.  
99a0: 20 20 20 20 6c 6f 67 69 6e 5f 73 65 74 5f 63 61      login_set_ca
99b0: 70 61 62 69 6c 69 74 69 65 73 28 7a 43 61 70 2c  pabilities(zCap,
99c0: 20 30 29 3b 0a 20 20 20 20 20 20 67 2e 61 6e 6f   0);.      g.ano
99d0: 6e 20 3d 20 67 2e 70 65 72 6d 3b 0a 20 20 20 20  n = g.perm;.    
99e0: 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 2f 2a 20  }else{.      /* 
99f0: 52 65 63 6f 72 64 20 74 68 65 20 70 72 69 76 69  Record the privi
9a00: 6c 65 67 65 73 20 6f 66 20 61 6e 6f 6e 79 6d 6f  leges of anonymo
9a10: 75 73 20 69 6e 20 67 2e 61 6e 6f 6e 20 2a 2f 0a  us in g.anon */.
9a20: 20 20 20 20 20 20 67 2e 61 6e 6f 6e 20 3d 20 67        g.anon = g
9a30: 2e 70 65 72 6d 3b 0a 20 20 20 20 20 20 6c 6f 67  .perm;.      log
9a40: 69 6e 5f 73 65 74 5f 63 61 70 61 62 69 6c 69 74  in_set_capabilit
9a50: 69 65 73 28 7a 43 61 70 2c 20 4c 4f 47 49 4e 5f  ies(zCap, LOGIN_
9a60: 41 4e 4f 4e 29 3b 0a 20 20 20 20 7d 0a 20 20 20  ANON);.    }.   
9a70: 20 6c 6f 67 69 6e 5f 61 6e 6f 6e 5f 6f 6e 63 65   login_anon_once
9a80: 20 3d 20 30 3b 0a 20 20 7d 0a 7d 0a 0a 2f 2a 0a   = 0;.  }.}../*.
9a90: 2a 2a 20 46 6c 61 67 73 20 70 61 73 73 65 64 20  ** Flags passed 
9aa0: 69 6e 74 6f 20 74 68 65 20 32 6e 64 20 61 72 67  into the 2nd arg
9ab0: 75 6d 65 6e 74 20 6f 66 20 6c 6f 67 69 6e 5f 73  ument of login_s
9ac0: 65 74 2f 72 65 70 6c 61 63 65 5f 63 61 70 61 62  et/replace_capab
9ad0: 69 6c 69 74 69 65 73 28 29 2e 0a 2a 2f 0a 23 69  ilities()..*/.#i
9ae0: 66 20 49 4e 54 45 52 46 41 43 45 0a 23 64 65 66  f INTERFACE.#def
9af0: 69 6e 65 20 4c 4f 47 49 4e 5f 49 47 4e 4f 52 45  ine LOGIN_IGNORE
9b00: 5f 55 56 20 20 30 78 30 31 20 20 20 20 20 20 20  _UV  0x01       
9b10: 20 20 2f 2a 20 49 67 6e 6f 72 65 20 22 75 22 20    /* Ignore "u" 
9b20: 61 6e 64 20 22 76 22 20 2a 2f 0a 23 64 65 66 69  and "v" */.#defi
9b30: 6e 65 20 4c 4f 47 49 4e 5f 41 4e 4f 4e 20 20 20  ne LOGIN_ANON   
9b40: 20 20 20 20 30 78 30 32 20 20 20 20 20 20 20 20      0x02        
9b50: 20 2f 2a 20 55 73 65 20 67 2e 61 6e 6f 6e 20 69   /* Use g.anon i
9b60: 6e 73 74 65 61 64 20 6f 66 20 67 2e 70 65 72 6d  nstead of g.perm
9b70: 20 2a 2f 0a 23 65 6e 64 69 66 0a 0a 2f 2a 0a 2a   */.#endif../*.*
9b80: 2a 20 41 64 64 73 20 61 6c 6c 20 63 61 70 61 62  * Adds all capab
9b90: 69 6c 69 74 79 20 66 6c 61 67 73 20 69 6e 20 7a  ility flags in z
9ba0: 43 61 70 20 74 6f 20 67 2e 70 65 72 6d 20 6f 72  Cap to g.perm or
9bb0: 20 67 2e 61 6e 6f 6e 2e 0a 2a 2f 0a 76 6f 69 64   g.anon..*/.void
9bc0: 20 6c 6f 67 69 6e 5f 73 65 74 5f 63 61 70 61 62   login_set_capab
9bd0: 69 6c 69 74 69 65 73 28 63 6f 6e 73 74 20 63 68  ilities(const ch
9be0: 61 72 20 2a 7a 43 61 70 2c 20 75 6e 73 69 67 6e  ar *zCap, unsign
9bf0: 65 64 20 66 6c 61 67 73 29 7b 0a 20 20 69 6e 74  ed flags){.  int
9c00: 20 69 3b 0a 20 20 46 6f 73 73 69 6c 55 73 65 72   i;.  FossilUser
9c10: 50 65 72 6d 73 20 2a 70 20 3d 20 28 66 6c 61 67  Perms *p = (flag
9c20: 73 20 26 20 4c 4f 47 49 4e 5f 41 4e 4f 4e 29 20  s & LOGIN_ANON) 
9c30: 3f 20 26 67 2e 61 6e 6f 6e 20 3a 20 26 67 2e 70  ? &g.anon : &g.p
9c40: 65 72 6d 3b 0a 20 20 69 66 28 4e 55 4c 4c 3d 3d  erm;.  if(NULL==
9c50: 7a 43 61 70 29 7b 0a 20 20 20 20 72 65 74 75 72  zCap){.    retur
9c60: 6e 3b 0a 20 20 7d 0a 20 20 66 6f 72 28 69 3d 30  n;.  }.  for(i=0
9c70: 3b 20 7a 43 61 70 5b 69 5d 3b 20 69 2b 2b 29 7b  ; zCap[i]; i++){
9c80: 0a 20 20 20 20 73 77 69 74 63 68 28 20 7a 43 61  .    switch( zCa
9c90: 70 5b 69 5d 20 29 7b 0a 20 20 20 20 20 20 63 61  p[i] ){.      ca
9ca0: 73 65 20 27 73 27 3a 20 20 20 70 2d 3e 53 65 74  se 's':   p->Set
9cb0: 75 70 20 3d 20 31 3b 20 2f 2a 20 46 61 6c 6c 20  up = 1; /* Fall 
9cc0: 74 68 72 75 20 69 6e 74 6f 20 41 64 6d 69 6e 20  thru into Admin 
9cd0: 2a 2f 0a 20 20 20 20 20 20 63 61 73 65 20 27 61  */.      case 'a
9ce0: 27 3a 20 20 20 70 2d 3e 41 64 6d 69 6e 20 3d 20  ':   p->Admin = 
9cf0: 70 2d 3e 52 64 54 6b 74 20 3d 20 70 2d 3e 57 72  p->RdTkt = p->Wr
9d00: 54 6b 74 20 3d 20 70 2d 3e 5a 69 70 20 3d 0a 20  Tkt = p->Zip =. 
9d10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9d20: 20 20 20 20 20 20 20 20 20 20 20 20 70 2d 3e 52              p->R
9d30: 64 57 69 6b 69 20 3d 20 70 2d 3e 57 72 57 69 6b  dWiki = p->WrWik
9d40: 69 20 3d 20 70 2d 3e 4e 65 77 57 69 6b 69 20 3d  i = p->NewWiki =
9d50: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
9d60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 70 2d                p-
9d70: 3e 41 70 6e 64 57 69 6b 69 20 3d 20 70 2d 3e 48  >ApndWiki = p->H
9d80: 79 70 65 72 6c 69 6e 6b 20 3d 20 70 2d 3e 43 6c  yperlink = p->Cl
9d90: 6f 6e 65 20 3d 0a 20 20 20 20 20 20 20 20 20 20  one =.          
9da0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9db0: 20 20 20 70 2d 3e 4e 65 77 54 6b 74 20 3d 20 70     p->NewTkt = p
9dc0: 2d 3e 50 61 73 73 77 6f 72 64 20 3d 20 70 2d 3e  ->Password = p->
9dd0: 52 64 41 64 64 72 20 3d 0a 20 20 20 20 20 20 20  RdAddr =.       
9de0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9df0: 20 20 20 20 20 20 70 2d 3e 54 6b 74 46 6d 74 20        p->TktFmt 
9e00: 3d 20 70 2d 3e 41 74 74 61 63 68 20 3d 20 70 2d  = p->Attach = p-
9e10: 3e 41 70 6e 64 54 6b 74 20 3d 0a 20 20 20 20 20  >ApndTkt =.     
9e20: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9e30: 20 20 20 20 20 20 20 20 70 2d 3e 4d 6f 64 57 69          p->ModWi
9e40: 6b 69 20 3d 20 70 2d 3e 4d 6f 64 54 6b 74 20 3d  ki = p->ModTkt =
9e50: 20 70 2d 3e 44 65 6c 65 74 65 20 3d 0a 20 20 20   p->Delete =.   
9e60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9e70: 20 20 20 20 20 20 20 20 20 20 70 2d 3e 52 64 46            p->RdF
9e80: 6f 72 75 6d 20 3d 20 70 2d 3e 57 72 46 6f 72 75  orum = p->WrForu
9e90: 6d 20 3d 20 70 2d 3e 4d 6f 64 46 6f 72 75 6d 20  m = p->ModForum 
9ea0: 3d 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  =.              
9eb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 70                 p
9ec0: 2d 3e 57 72 54 46 6f 72 75 6d 20 3d 20 70 2d 3e  ->WrTForum = p->
9ed0: 41 64 6d 69 6e 46 6f 72 75 6d 20 3d 0a 20 20 20  AdminForum =.   
9ee0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9ef0: 20 20 20 20 20 20 20 20 20 20 70 2d 3e 45 6d 61            p->Ema
9f00: 69 6c 41 6c 65 72 74 20 3d 20 70 2d 3e 41 6e 6e  ilAlert = p->Ann
9f10: 6f 75 6e 63 65 20 3d 20 70 2d 3e 44 65 62 75 67  ounce = p->Debug
9f20: 20 3d 0a 20 20 20 20 20 20 20 20 20 20 20 20 20   =.             
9f30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
9f40: 70 2d 3e 57 72 55 6e 76 65 72 20 3d 20 70 2d 3e  p->WrUnver = p->
9f50: 50 72 69 76 61 74 65 20 3d 20 31 3b 0a 20 20 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 2f 2a 20 46 61 6c            /* Fal
9f80: 6c 20 74 68 72 75 20 69 6e 74 6f 20 52 65 61 64  l thru into Read
9f90: 2f 57 72 69 74 65 20 2a 2f 0a 20 20 20 20 20 20  /Write */.      
9fa0: 63 61 73 65 20 27 69 27 3a 20 20 20 70 2d 3e 52  case 'i':   p->R
9fb0: 65 61 64 20 3d 20 70 2d 3e 57 72 69 74 65 20 3d  ead = p->Write =
9fc0: 20 31 3b 20 20 20 20 20 20 20 20 20 20 20 20 20   1;             
9fd0: 20 20 20 20 20 20 20 20 20 62 72 65 61 6b 3b 0a           break;.
9fe0: 20 20 20 20 20 20 63 61 73 65 20 27 6f 27 3a 20        case 'o': 
9ff0: 20 20 70 2d 3e 52 65 61 64 20 3d 20 31 3b 20 20    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 62                 b
a020: 72 65 61 6b 3b 0a 20 20 20 20 20 20 63 61 73 65  reak;.      case
a030: 20 27 7a 27 3a 20 20 20 70 2d 3e 5a 69 70 20 3d   'z':   p->Zip =
a040: 20 31 3b 20 20 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 62 72 65 61 6b 3b 0a 0a 20 20 20       break;..   
a070: 20 20 20 63 61 73 65 20 27 64 27 3a 20 20 20 70     case 'd':   p
a080: 2d 3e 44 65 6c 65 74 65 20 3d 20 31 3b 20 20 20  ->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 62 72 65 61              brea
a0b0: 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27 68  k;.      case 'h
a0c0: 27 3a 20 20 20 70 2d 3e 48 79 70 65 72 6c 69 6e  ':   p->Hyperlin
a0d0: 6b 20 3d 20 31 3b 20 20 20 20 20 20 20 20 20 20  k = 1;          
a0e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a0f0: 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 63    break;.      c
a100: 61 73 65 20 27 67 27 3a 20 20 20 70 2d 3e 43 6c  ase 'g':   p->Cl
a110: 6f 6e 65 20 3d 20 31 3b 20 20 20 20 20 20 20 20  one = 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 62 72 65 61 6b 3b 0a 20          break;. 
a140: 20 20 20 20 20 63 61 73 65 20 27 70 27 3a 20 20       case 'p':  
a150: 20 70 2d 3e 50 61 73 73 77 6f 72 64 20 3d 20 31   p->Password = 1
a160: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ;               
a170: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 62 72                br
a180: 65 61 6b 3b 0a 0a 20 20 20 20 20 20 63 61 73 65  eak;..      case
a190: 20 27 6a 27 3a 20 20 20 70 2d 3e 52 64 57 69 6b   'j':   p->RdWik
a1a0: 69 20 3d 20 31 3b 20 20 20 20 20 20 20 20 20 20  i = 1;          
a1b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a1c0: 20 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20       break;.    
a1d0: 20 20 63 61 73 65 20 27 6b 27 3a 20 20 20 70 2d    case 'k':   p-
a1e0: 3e 57 72 57 69 6b 69 20 3d 20 70 2d 3e 52 64 57  >WrWiki = p->RdW
a1f0: 69 6b 69 20 3d 20 70 2d 3e 41 70 6e 64 57 69 6b  iki = p->ApndWik
a200: 69 20 3d 31 3b 20 20 20 20 20 20 62 72 65 61 6b  i =1;      break
a210: 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27 6d 27  ;.      case 'm'
a220: 3a 20 20 20 70 2d 3e 41 70 6e 64 57 69 6b 69 20  :   p->ApndWiki 
a230: 3d 20 31 3b 20 20 20 20 20 20 20 20 20 20 20 20  = 1;            
a240: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a250: 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 63 61   break;.      ca
a260: 73 65 20 27 66 27 3a 20 20 20 70 2d 3e 4e 65 77  se 'f':   p->New
a270: 57 69 6b 69 20 3d 20 31 3b 20 20 20 20 20 20 20  Wiki = 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 62 72 65 61 6b 3b 0a 20 20         break;.  
a2a0: 20 20 20 20 63 61 73 65 20 27 6c 27 3a 20 20 20      case 'l':   
a2b0: 70 2d 3e 4d 6f 64 57 69 6b 69 20 3d 20 31 3b 20  p->ModWiki = 1; 
a2c0: 20 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 62 72 65               bre
a2e0: 61 6b 3b 0a 0a 20 20 20 20 20 20 63 61 73 65 20  ak;..      case 
a2f0: 27 65 27 3a 20 20 20 70 2d 3e 52 64 41 64 64 72  'e':   p->RdAddr
a300: 20 3d 20 31 3b 20 20 20 20 20 20 20 20 20 20 20   = 1;           
a310: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a320: 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20      break;.     
a330: 20 63 61 73 65 20 27 72 27 3a 20 20 20 70 2d 3e   case 'r':   p->
a340: 52 64 54 6b 74 20 3d 20 31 3b 20 20 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 62 72 65 61 6b 3b            break;
a370: 0a 20 20 20 20 20 20 63 61 73 65 20 27 6e 27 3a  .      case 'n':
a380: 20 20 20 70 2d 3e 4e 65 77 54 6b 74 20 3d 20 31     p->NewTkt = 1
a390: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ;               
a3a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a3b0: 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 63 61 73  break;.      cas
a3c0: 65 20 27 77 27 3a 20 20 20 70 2d 3e 57 72 54 6b  e 'w':   p->WrTk
a3d0: 74 20 3d 20 70 2d 3e 52 64 54 6b 74 20 3d 20 70  t = p->RdTkt = p
a3e0: 2d 3e 4e 65 77 54 6b 74 20 3d 0a 20 20 20 20 20  ->NewTkt =.     
a3f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 70 2d 3e               p->
a400: 41 70 6e 64 54 6b 74 20 3d 20 31 3b 20 20 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 62 72 65 61 6b 3b            break;
a430: 0a 20 20 20 20 20 20 63 61 73 65 20 27 63 27 3a  .      case 'c':
a440: 20 20 20 70 2d 3e 41 70 6e 64 54 6b 74 20 3d 20     p->ApndTkt = 
a450: 31 3b 20 20 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: 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 63 61 73  break;.      cas
a480: 65 20 27 71 27 3a 20 20 20 70 2d 3e 4d 6f 64 54  e 'q':   p->ModT
a490: 6b 74 20 3d 20 31 3b 20 20 20 20 20 20 20 20 20  kt = 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 62 72 65 61 6b 3b 0a 20 20 20        break;.   
a4c0: 20 20 20 63 61 73 65 20 27 74 27 3a 20 20 20 70     case 't':   p
a4d0: 2d 3e 54 6b 74 46 6d 74 20 3d 20 31 3b 20 20 20  ->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 62 72 65 61              brea
a500: 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27 62  k;.      case 'b
a510: 27 3a 20 20 20 70 2d 3e 41 74 74 61 63 68 20 3d  ':   p->Attach =
a520: 20 31 3b 20 20 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 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 63    break;.      c
a550: 61 73 65 20 27 78 27 3a 20 20 20 70 2d 3e 50 72  ase 'x':   p->Pr
a560: 69 76 61 74 65 20 3d 20 31 3b 20 20 20 20 20 20  ivate = 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 62 72 65 61 6b 3b 0a 20          break;. 
a590: 20 20 20 20 20 63 61 73 65 20 27 79 27 3a 20 20       case 'y':  
a5a0: 20 70 2d 3e 57 72 55 6e 76 65 72 20 3d 20 31 3b   p->WrUnver = 1;
a5b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a5c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 62 72                br
a5d0: 65 61 6b 3b 0a 0a 20 20 20 20 20 20 63 61 73 65  eak;..      case
a5e0: 20 27 36 27 3a 20 20 20 70 2d 3e 41 64 6d 69 6e   '6':   p->Admin
a5f0: 46 6f 72 75 6d 20 3d 20 31 3b 0a 20 20 20 20 20  Forum = 1;.     
a600: 20 63 61 73 65 20 27 35 27 3a 20 20 20 70 2d 3e   case '5':   p->
a610: 4d 6f 64 46 6f 72 75 6d 20 3d 20 31 3b 0a 20 20  ModForum = 1;.  
a620: 20 20 20 20 63 61 73 65 20 27 34 27 3a 20 20 20      case '4':   
a630: 70 2d 3e 57 72 54 46 6f 72 75 6d 20 3d 20 31 3b  p->WrTForum = 1;
a640: 0a 20 20 20 20 20 20 63 61 73 65 20 27 33 27 3a  .      case '3':
a650: 20 20 20 70 2d 3e 57 72 46 6f 72 75 6d 20 3d 20     p->WrForum = 
a660: 31 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27 32  1;.      case '2
a670: 27 3a 20 20 20 70 2d 3e 52 64 46 6f 72 75 6d 20  ':   p->RdForum 
a680: 3d 20 31 3b 20 20 20 20 20 20 20 20 20 20 20 20  = 1;            
a690: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a6a0: 20 20 62 72 65 61 6b 3b 0a 0a 20 20 20 20 20 20    break;..      
a6b0: 63 61 73 65 20 27 37 27 3a 20 20 20 70 2d 3e 45  case '7':   p->E
a6c0: 6d 61 69 6c 41 6c 65 72 74 20 3d 20 31 3b 20 20  mailAlert = 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 62 72 65 61 6b 3b 0a           break;.
a6f0: 20 20 20 20 20 20 63 61 73 65 20 27 41 27 3a 20        case 'A': 
a700: 20 20 70 2d 3e 41 6e 6e 6f 75 6e 63 65 20 3d 20    p->Announce = 
a710: 31 3b 20 20 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 62                 b
a730: 72 65 61 6b 3b 0a 20 20 20 20 20 20 63 61 73 65  reak;.      case
a740: 20 27 44 27 3a 20 20 20 70 2d 3e 44 65 62 75 67   'D':   p->Debug
a750: 20 3d 20 31 3b 20 20 20 20 20 20 20 20 20 20 20   = 1;           
a760: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
a770: 20 20 20 20 20 62 72 65 61 6b 3b 0a 0a 20 20 20       break;..   
a780: 20 20 20 2f 2a 20 54 68 65 20 22 75 22 20 70 72     /* The "u" pr
a790: 69 76 69 6c 65 67 65 20 72 65 63 75 72 73 69 76  ivilege recursiv
a7a0: 65 6c 79 0a 20 20 20 20 20 20 2a 2a 20 69 6e 68  ely.      ** inh
a7b0: 65 72 69 74 73 20 61 6c 6c 20 70 72 69 76 69 6c  erits all privil
a7c0: 65 67 65 73 20 6f 66 20 74 68 65 20 75 73 65 72  eges of the user
a7d0: 20 6e 61 6d 65 64 20 22 72 65 61 64 65 72 22 20   named "reader" 
a7e0: 2a 2f 0a 20 20 20 20 20 20 63 61 73 65 20 27 75  */.      case 'u
a7f0: 27 3a 20 7b 0a 20 20 20 20 20 20 20 20 69 66 28  ': {.        if(
a800: 20 70 2d 3e 58 52 65 61 64 65 72 3d 3d 30 20 29   p->XReader==0 )
a810: 7b 0a 20 20 20 20 20 20 20 20 20 20 63 6f 6e 73  {.          cons
a820: 74 20 63 68 61 72 20 2a 7a 55 73 65 72 3b 0a 20  t char *zUser;. 
a830: 20 20 20 20 20 20 20 20 20 70 2d 3e 58 52 65 61           p->XRea
a840: 64 65 72 20 3d 20 31 3b 0a 20 20 20 20 20 20 20  der = 1;.       
a850: 20 20 20 7a 55 73 65 72 20 3d 20 64 62 5f 74 65     zUser = db_te
a860: 78 74 28 22 22 2c 20 22 53 45 4c 45 43 54 20 63  xt("", "SELECT c
a870: 61 70 20 46 52 4f 4d 20 75 73 65 72 20 57 48 45  ap FROM user WHE
a880: 52 45 20 6c 6f 67 69 6e 3d 27 72 65 61 64 65 72  RE login='reader
a890: 27 22 29 3b 0a 20 20 20 20 20 20 20 20 20 20 6c  '");.          l
a8a0: 6f 67 69 6e 5f 73 65 74 5f 63 61 70 61 62 69 6c  ogin_set_capabil
a8b0: 69 74 69 65 73 28 7a 55 73 65 72 2c 20 66 6c 61  ities(zUser, fla
a8c0: 67 73 29 3b 0a 20 20 20 20 20 20 20 20 7d 0a 20  gs);.        }. 
a8d0: 20 20 20 20 20 20 20 62 72 65 61 6b 3b 0a 20 20         break;.  
a8e0: 20 20 20 20 7d 0a 0a 20 20 20 20 20 20 2f 2a 20      }..      /* 
a8f0: 54 68 65 20 22 76 22 20 70 72 69 76 69 6c 65 67  The "v" privileg
a900: 65 20 72 65 63 75 72 73 69 76 65 6c 79 0a 20 20  e recursively.  
a910: 20 20 20 20 2a 2a 20 69 6e 68 65 72 69 74 73 20      ** inherits 
a920: 61 6c 6c 20 70 72 69 76 69 6c 65 67 65 73 20 6f  all privileges o
a930: 66 20 74 68 65 20 75 73 65 72 20 6e 61 6d 65 64  f the user named
a940: 20 22 64 65 76 65 6c 6f 70 65 72 22 20 2a 2f 0a   "developer" */.
a950: 20 20 20 20 20 20 63 61 73 65 20 27 76 27 3a 20        case 'v': 
a960: 7b 0a 20 20 20 20 20 20 20 20 69 66 28 20 70 2d  {.        if( p-
a970: 3e 58 44 65 76 65 6c 6f 70 65 72 3d 3d 30 20 29  >XDeveloper==0 )
a980: 7b 0a 20 20 20 20 20 20 20 20 20 20 63 6f 6e 73  {.          cons
a990: 74 20 63 68 61 72 20 2a 7a 44 65 76 3b 0a 20 20  t char *zDev;.  
a9a0: 20 20 20 20 20 20 20 20 70 2d 3e 58 44 65 76 65          p->XDeve
a9b0: 6c 6f 70 65 72 20 3d 20 31 3b 0a 20 20 20 20 20  loper = 1;.     
a9c0: 20 20 20 20 20 7a 44 65 76 20 3d 20 64 62 5f 74       zDev = db_t
a9d0: 65 78 74 28 22 22 2c 20 22 53 45 4c 45 43 54 20  ext("", "SELECT 
a9e0: 63 61 70 20 46 52 4f 4d 20 75 73 65 72 20 57 48  cap FROM user WH
a9f0: 45 52 45 20 6c 6f 67 69 6e 3d 27 64 65 76 65 6c  ERE login='devel
aa00: 6f 70 65 72 27 22 29 3b 0a 20 20 20 20 20 20 20  oper'");.       
aa10: 20 20 20 6c 6f 67 69 6e 5f 73 65 74 5f 63 61 70     login_set_cap
aa20: 61 62 69 6c 69 74 69 65 73 28 7a 44 65 76 2c 20  abilities(zDev, 
aa30: 66 6c 61 67 73 29 3b 0a 20 20 20 20 20 20 20 20  flags);.        
aa40: 7d 0a 20 20 20 20 20 20 20 20 62 72 65 61 6b 3b  }.        break;
aa50: 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a 20  .      }.    }. 
aa60: 20 7d 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 5a 65 72 6f   }.}../*.** Zero
aa70: 65 73 20 6f 75 74 20 67 2e 70 65 72 6d 20 61 6e  es out g.perm an
aa80: 64 20 63 61 6c 6c 73 20 6c 6f 67 69 6e 5f 73 65  d calls login_se
aa90: 74 5f 63 61 70 61 62 69 6c 69 74 69 65 73 28 7a  t_capabilities(z
aaa0: 43 61 70 2c 66 6c 61 67 73 29 2e 0a 2a 2f 0a 76  Cap,flags)..*/.v
aab0: 6f 69 64 20 6c 6f 67 69 6e 5f 72 65 70 6c 61 63  oid login_replac
aac0: 65 5f 63 61 70 61 62 69 6c 69 74 69 65 73 28 63  e_capabilities(c
aad0: 6f 6e 73 74 20 63 68 61 72 20 2a 7a 43 61 70 2c  onst char *zCap,
aae0: 20 75 6e 73 69 67 6e 65 64 20 66 6c 61 67 73 29   unsigned flags)
aaf0: 7b 0a 20 20 6d 65 6d 73 65 74 28 26 67 2e 70 65  {.  memset(&g.pe
ab00: 72 6d 2c 20 30 2c 20 73 69 7a 65 6f 66 28 67 2e  rm, 0, sizeof(g.
ab10: 70 65 72 6d 29 29 3b 0a 20 20 6c 6f 67 69 6e 5f  perm));.  login_
ab20: 73 65 74 5f 63 61 70 61 62 69 6c 69 74 69 65 73  set_capabilities
ab30: 28 7a 43 61 70 2c 20 66 6c 61 67 73 29 3b 0a 20  (zCap, flags);. 
ab40: 20 6c 6f 67 69 6e 5f 61 6e 6f 6e 5f 6f 6e 63 65   login_anon_once
ab50: 20 3d 20 31 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 49   = 1;.}../*.** I
ab60: 66 20 74 68 65 20 63 75 72 72 65 6e 74 20 6c 6f  f the current lo
ab70: 67 69 6e 20 6c 61 63 6b 73 20 61 6e 79 20 6f 66  gin lacks any of
ab80: 20 74 68 65 20 63 61 70 61 62 69 6c 69 74 69 65   the capabilitie
ab90: 73 20 6c 69 73 74 65 64 20 69 6e 0a 2a 2a 20 74  s listed in.** t
aba0: 68 65 20 69 6e 70 75 74 2c 20 74 68 65 6e 20 72  he input, then r
abb0: 65 74 75 72 6e 20 30 2e 20 20 49 66 20 61 6c 6c  eturn 0.  If all
abc0: 20 63 61 70 61 62 69 6c 69 74 69 65 73 20 61 72   capabilities ar
abd0: 65 20 70 72 65 73 65 6e 74 2c 20 74 68 65 6e 0a  e present, then.
abe0: 2a 2a 20 72 65 74 75 72 6e 20 31 2e 0a 2a 2f 0a  ** return 1..*/.
abf0: 69 6e 74 20 6c 6f 67 69 6e 5f 68 61 73 5f 63 61  int login_has_ca
ac00: 70 61 62 69 6c 69 74 79 28 63 6f 6e 73 74 20 63  pability(const c
ac10: 68 61 72 20 2a 7a 43 61 70 2c 20 69 6e 74 20 6e  har *zCap, int n
ac20: 43 61 70 2c 20 75 33 32 20 66 6c 67 73 29 7b 0a  Cap, u32 flgs){.
ac30: 20 20 69 6e 74 20 69 3b 0a 20 20 69 6e 74 20 72    int i;.  int r
ac40: 63 20 3d 20 31 3b 0a 20 20 46 6f 73 73 69 6c 55  c = 1;.  FossilU
ac50: 73 65 72 50 65 72 6d 73 20 2a 70 20 3d 20 28 66  serPerms *p = (f
ac60: 6c 67 73 20 26 20 4c 4f 47 49 4e 5f 41 4e 4f 4e  lgs & LOGIN_ANON
ac70: 29 20 3f 20 26 67 2e 61 6e 6f 6e 20 3a 20 26 67  ) ? &g.anon : &g
ac80: 2e 70 65 72 6d 3b 0a 20 20 69 66 28 20 6e 43 61  .perm;.  if( nCa
ac90: 70 3c 30 20 29 20 6e 43 61 70 20 3d 20 73 74 72  p<0 ) nCap = str
aca0: 6c 65 6e 28 7a 43 61 70 29 3b 0a 20 20 66 6f 72  len(zCap);.  for
acb0: 28 69 3d 30 3b 20 69 3c 6e 43 61 70 20 26 26 20  (i=0; i<nCap && 
acc0: 72 63 20 26 26 20 7a 43 61 70 5b 69 5d 3b 20 69  rc && zCap[i]; i
acd0: 2b 2b 29 7b 0a 20 20 20 20 73 77 69 74 63 68 28  ++){.    switch(
ace0: 20 7a 43 61 70 5b 69 5d 20 29 7b 0a 20 20 20 20   zCap[i] ){.    
acf0: 20 20 63 61 73 65 20 27 61 27 3a 20 20 72 63 20    case 'a':  rc 
ad00: 3d 20 70 2d 3e 41 64 6d 69 6e 3b 20 20 20 20 20  = p->Admin;     
ad10: 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 63 61 73  break;.      cas
ad20: 65 20 27 62 27 3a 20 20 72 63 20 3d 20 70 2d 3e  e 'b':  rc = p->
ad30: 41 74 74 61 63 68 3b 20 20 20 20 62 72 65 61 6b  Attach;    break
ad40: 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27 63 27  ;.      case 'c'
ad50: 3a 20 20 72 63 20 3d 20 70 2d 3e 41 70 6e 64 54  :  rc = p->ApndT
ad60: 6b 74 3b 20 20 20 62 72 65 61 6b 3b 0a 20 20 20  kt;   break;.   
ad70: 20 20 20 63 61 73 65 20 27 64 27 3a 20 20 72 63     case 'd':  rc
ad80: 20 3d 20 70 2d 3e 44 65 6c 65 74 65 3b 20 20 20   = p->Delete;   
ad90: 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 63 61   break;.      ca
ada0: 73 65 20 27 65 27 3a 20 20 72 63 20 3d 20 70 2d  se 'e':  rc = p-
adb0: 3e 52 64 41 64 64 72 3b 20 20 20 20 62 72 65 61  >RdAddr;    brea
adc0: 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27 66  k;.      case 'f
add0: 27 3a 20 20 72 63 20 3d 20 70 2d 3e 4e 65 77 57  ':  rc = p->NewW
ade0: 69 6b 69 3b 20 20 20 62 72 65 61 6b 3b 0a 20 20  iki;   break;.  
adf0: 20 20 20 20 63 61 73 65 20 27 67 27 3a 20 20 72      case 'g':  r
ae00: 63 20 3d 20 70 2d 3e 43 6c 6f 6e 65 3b 20 20 20  c = p->Clone;   
ae10: 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 63    break;.      c
ae20: 61 73 65 20 27 68 27 3a 20 20 72 63 20 3d 20 70  ase 'h':  rc = p
ae30: 2d 3e 48 79 70 65 72 6c 69 6e 6b 3b 20 62 72 65  ->Hyperlink; bre
ae40: 61 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27  ak;.      case '
ae50: 69 27 3a 20 20 72 63 20 3d 20 70 2d 3e 57 72 69  i':  rc = p->Wri
ae60: 74 65 3b 20 20 20 20 20 62 72 65 61 6b 3b 0a 20  te;     break;. 
ae70: 20 20 20 20 20 63 61 73 65 20 27 6a 27 3a 20 20       case 'j':  
ae80: 72 63 20 3d 20 70 2d 3e 52 64 57 69 6b 69 3b 20  rc = p->RdWiki; 
ae90: 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20     break;.      
aea0: 63 61 73 65 20 27 6b 27 3a 20 20 72 63 20 3d 20  case 'k':  rc = 
aeb0: 70 2d 3e 57 72 57 69 6b 69 3b 20 20 20 20 62 72  p->WrWiki;    br
aec0: 65 61 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20  eak;.      case 
aed0: 27 6c 27 3a 20 20 72 63 20 3d 20 70 2d 3e 4d 6f  'l':  rc = p->Mo
aee0: 64 57 69 6b 69 3b 20 20 20 62 72 65 61 6b 3b 0a  dWiki;   break;.
aef0: 20 20 20 20 20 20 63 61 73 65 20 27 6d 27 3a 20        case 'm': 
af00: 20 72 63 20 3d 20 70 2d 3e 41 70 6e 64 57 69 6b   rc = p->ApndWik
af10: 69 3b 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20  i;  break;.     
af20: 20 63 61 73 65 20 27 6e 27 3a 20 20 72 63 20 3d   case 'n':  rc =
af30: 20 70 2d 3e 4e 65 77 54 6b 74 3b 20 20 20 20 62   p->NewTkt;    b
af40: 72 65 61 6b 3b 0a 20 20 20 20 20 20 63 61 73 65  reak;.      case
af50: 20 27 6f 27 3a 20 20 72 63 20 3d 20 70 2d 3e 52   'o':  rc = p->R
af60: 65 61 64 3b 20 20 20 20 20 20 62 72 65 61 6b 3b  ead;      break;
af70: 0a 20 20 20 20 20 20 63 61 73 65 20 27 70 27 3a  .      case 'p':
af80: 20 20 72 63 20 3d 20 70 2d 3e 50 61 73 73 77 6f    rc = p->Passwo
af90: 72 64 3b 20 20 62 72 65 61 6b 3b 0a 20 20 20 20  rd;  break;.    
afa0: 20 20 63 61 73 65 20 27 71 27 3a 20 20 72 63 20    case 'q':  rc 
afb0: 3d 20 70 2d 3e 4d 6f 64 54 6b 74 3b 20 20 20 20  = p->ModTkt;    
afc0: 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 63 61 73  break;.      cas
afd0: 65 20 27 72 27 3a 20 20 72 63 20 3d 20 70 2d 3e  e 'r':  rc = p->
afe0: 52 64 54 6b 74 3b 20 20 20 20 20 62 72 65 61 6b  RdTkt;     break
aff0: 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27 73 27  ;.      case 's'
b000: 3a 20 20 72 63 20 3d 20 70 2d 3e 53 65 74 75 70  :  rc = p->Setup
b010: 3b 20 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20  ;     break;.   
b020: 20 20 20 63 61 73 65 20 27 74 27 3a 20 20 72 63     case 't':  rc
b030: 20 3d 20 70 2d 3e 54 6b 74 46 6d 74 3b 20 20 20   = p->TktFmt;   
b040: 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 2f 2a   break;.      /*
b050: 20 63 61 73 65 20 27 75 27 3a 20 52 45 41 44 45   case 'u': READE
b060: 52 20 20 20 20 2a 2f 0a 20 20 20 20 20 20 2f 2a  R    */.      /*
b070: 20 63 61 73 65 20 27 76 27 3a 20 44 45 56 45 4c   case 'v': DEVEL
b080: 4f 50 45 52 20 2a 2f 0a 20 20 20 20 20 20 63 61  OPER */.      ca
b090: 73 65 20 27 77 27 3a 20 20 72 63 20 3d 20 70 2d  se 'w':  rc = p-
b0a0: 3e 57 72 54 6b 74 3b 20 20 20 20 20 62 72 65 61  >WrTkt;     brea
b0b0: 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27 78  k;.      case 'x
b0c0: 27 3a 20 20 72 63 20 3d 20 70 2d 3e 50 72 69 76  ':  rc = p->Priv
b0d0: 61 74 65 3b 20 20 20 62 72 65 61 6b 3b 0a 20 20  ate;   break;.  
b0e0: 20 20 20 20 63 61 73 65 20 27 79 27 3a 20 20 72      case 'y':  r
b0f0: 63 20 3d 20 70 2d 3e 57 72 55 6e 76 65 72 3b 20  c = p->WrUnver; 
b100: 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20 63    break;.      c
b110: 61 73 65 20 27 7a 27 3a 20 20 72 63 20 3d 20 70  ase 'z':  rc = p
b120: 2d 3e 5a 69 70 3b 20 20 20 20 20 20 20 62 72 65  ->Zip;       bre
b130: 61 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20 27  ak;.      case '
b140: 32 27 3a 20 20 72 63 20 3d 20 70 2d 3e 52 64 46  2':  rc = p->RdF
b150: 6f 72 75 6d 3b 20 20 20 62 72 65 61 6b 3b 0a 20  orum;   break;. 
b160: 20 20 20 20 20 63 61 73 65 20 27 33 27 3a 20 20       case '3':  
b170: 72 63 20 3d 20 70 2d 3e 57 72 46 6f 72 75 6d 3b  rc = p->WrForum;
b180: 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20 20 20     break;.      
b190: 63 61 73 65 20 27 34 27 3a 20 20 72 63 20 3d 20  case '4':  rc = 
b1a0: 70 2d 3e 57 72 54 46 6f 72 75 6d 3b 20 20 62 72  p->WrTForum;  br
b1b0: 65 61 6b 3b 0a 20 20 20 20 20 20 63 61 73 65 20  eak;.      case 
b1c0: 27 35 27 3a 20 20 72 63 20 3d 20 70 2d 3e 4d 6f  '5':  rc = p->Mo
b1d0: 64 46 6f 72 75 6d 3b 20 20 62 72 65 61 6b 3b 0a  dForum;  break;.
b1e0: 20 20 20 20 20 20 63 61 73 65 20 27 36 27 3a 20        case '6': 
b1f0: 20 72 63 20 3d 20 70 2d 3e 41 64 6d 69 6e 46 6f   rc = p->AdminFo
b200: 72 75 6d 3b 62 72 65 61 6b 3b 0a 20 20 20 20 20  rum;break;.     
b210: 20 63 61 73 65 20 27 37 27 3a 20 20 72 63 20 3d   case '7':  rc =
b220: 20 70 2d 3e 45 6d 61 69 6c 41 6c 65 72 74 3b 62   p->EmailAlert;b
b230: 72 65 61 6b 3b 0a 20 20 20 20 20 20 63 61 73 65  reak;.      case
b240: 20 27 41 27 3a 20 20 72 63 20 3d 20 70 2d 3e 41   'A':  rc = p->A
b250: 6e 6e 6f 75 6e 63 65 3b 20 20 62 72 65 61 6b 3b  nnounce;  break;
b260: 0a 20 20 20 20 20 20 63 61 73 65 20 27 44 27 3a  .      case 'D':
b270: 20 20 72 63 20 3d 20 70 2d 3e 44 65 62 75 67 3b    rc = p->Debug;
b280: 20 20 20 20 20 62 72 65 61 6b 3b 0a 20 20 20 20       break;.    
b290: 20 20 64 65 66 61 75 6c 74 3a 20 20 20 72 63 20    default:   rc 
b2a0: 3d 20 30 3b 20 20 20 20 20 20 20 20 20 20 20 20  = 0;            
b2b0: 62 72 65 61 6b 3b 0a 20 20 20 20 7d 0a 20 20 7d  break;.    }.  }
b2c0: 0a 20 20 72 65 74 75 72 6e 20 72 63 3b 0a 7d 0a  .  return rc;.}.
b2d0: 0a 2f 2a 0a 2a 2a 20 43 68 61 6e 67 65 20 74 68  ./*.** Change th
b2e0: 65 20 6c 6f 67 69 6e 20 74 6f 20 7a 55 73 65 72  e login to zUser
b2f0: 2e 0a 2a 2f 0a 76 6f 69 64 20 6c 6f 67 69 6e 5f  ..*/.void login_
b300: 61 73 5f 75 73 65 72 28 63 6f 6e 73 74 20 63 68  as_user(const ch
b310: 61 72 20 2a 7a 55 73 65 72 29 7b 0a 20 20 63 68  ar *zUser){.  ch
b320: 61 72 20 2a 7a 43 61 70 20 3d 20 22 22 3b 20 20  ar *zCap = "";  
b330: 20 2f 2a 20 4e 65 77 20 63 61 70 61 62 69 6c 69   /* New capabili
b340: 74 69 65 73 20 2a 2f 0a 0a 20 20 2f 2a 20 54 75  ties */..  /* Tu
b350: 72 6e 20 6f 66 66 20 61 6c 6c 20 63 61 70 61 62  rn off all capab
b360: 69 6c 69 74 69 65 73 20 66 72 6f 6d 20 70 72 69  ilities from pri
b370: 6f 72 20 6c 6f 67 69 6e 73 20 2a 2f 0a 20 20 6d  or logins */.  m
b380: 65 6d 73 65 74 28 20 26 67 2e 70 65 72 6d 2c 20  emset( &g.perm, 
b390: 30 2c 20 73 69 7a 65 6f 66 28 67 2e 70 65 72 6d  0, sizeof(g.perm
b3a0: 29 20 29 3b 0a 0a 20 20 2f 2a 20 53 65 74 20 74  ) );..  /* Set t
b3b0: 68 65 20 67 6c 6f 62 61 6c 20 76 61 72 69 61 62  he global variab
b3c0: 6c 65 73 20 72 65 63 6f 72 64 69 6e 67 20 74 68  les recording th
b3d0: 65 20 75 73 65 72 69 64 20 61 6e 64 20 6c 6f 67  e userid and log
b3e0: 69 6e 2e 20 20 54 68 65 0a 20 20 2a 2a 20 22 6e  in.  The.  ** "n
b3f0: 6f 62 6f 64 79 22 20 75 73 65 72 20 69 73 20 61  obody" user is a
b400: 20 73 70 65 63 69 61 6c 20 63 61 73 65 20 69 6e   special case in
b410: 20 74 68 61 74 20 67 2e 7a 4c 6f 67 69 6e 3d 3d   that g.zLogin==
b420: 30 2e 0a 20 20 2a 2f 0a 20 20 67 2e 75 73 65 72  0..  */.  g.user
b430: 55 69 64 20 3d 20 64 62 5f 69 6e 74 28 30 2c 20  Uid = db_int(0, 
b440: 22 53 45 4c 45 43 54 20 75 69 64 20 46 52 4f 4d  "SELECT uid FROM
b450: 20 75 73 65 72 20 57 48 45 52 45 20 6c 6f 67 69   user WHERE logi
b460: 6e 3d 25 51 22 2c 20 7a 55 73 65 72 29 3b 0a 20  n=%Q", zUser);. 
b470: 20 69 66 28 20 67 2e 75 73 65 72 55 69 64 3d 3d   if( g.userUid==
b480: 30 20 29 7b 0a 20 20 20 20 7a 55 73 65 72 20 3d  0 ){.    zUser =
b490: 20 30 3b 0a 20 20 20 20 67 2e 75 73 65 72 55 69   0;.    g.userUi
b4a0: 64 20 3d 20 64 62 5f 69 6e 74 28 30 2c 20 22 53  d = db_int(0, "S
b4b0: 45 4c 45 43 54 20 75 69 64 20 46 52 4f 4d 20 75  ELECT uid FROM u
b4c0: 73 65 72 20 57 48 45 52 45 20 6c 6f 67 69 6e 3d  ser WHERE login=
b4d0: 27 6e 6f 62 6f 64 79 27 22 29 3b 0a 20 20 7d 0a  'nobody'");.  }.
b4e0: 20 20 69 66 28 20 67 2e 75 73 65 72 55 69 64 20    if( g.userUid 
b4f0: 29 7b 0a 20 20 20 20 7a 43 61 70 20 3d 20 64 62  ){.    zCap = db
b500: 5f 74 65 78 74 28 22 22 2c 20 22 53 45 4c 45 43  _text("", "SELEC
b510: 54 20 63 61 70 20 46 52 4f 4d 20 75 73 65 72 20  T cap FROM user 
b520: 57 48 45 52 45 20 75 69 64 3d 25 64 22 2c 20 67  WHERE uid=%d", g
b530: 2e 75 73 65 72 55 69 64 29 3b 0a 20 20 7d 0a 20  .userUid);.  }. 
b540: 20 69 66 28 20 66 6f 73 73 69 6c 5f 73 74 72 63   if( fossil_strc
b550: 6d 70 28 7a 55 73 65 72 2c 22 6e 6f 62 6f 64 79  mp(zUser,"nobody
b560: 22 29 3d 3d 30 20 29 20 7a 55 73 65 72 20 3d 20  ")==0 ) zUser = 
b570: 30 3b 0a 20 20 67 2e 7a 4c 6f 67 69 6e 20 3d 20  0;.  g.zLogin = 
b580: 66 6f 73 73 69 6c 5f 73 74 72 64 75 70 28 7a 55  fossil_strdup(zU
b590: 73 65 72 29 3b 0a 0a 20 20 2f 2a 20 53 65 74 20  ser);..  /* Set 
b5a0: 74 68 65 20 63 61 70 61 62 69 6c 69 74 69 65 73  the capabilities
b5b0: 20 2a 2f 0a 20 20 6c 6f 67 69 6e 5f 73 65 74 5f   */.  login_set_
b5c0: 63 61 70 61 62 69 6c 69 74 69 65 73 28 7a 43 61  capabilities(zCa
b5d0: 70 2c 20 30 29 3b 0a 20 20 6c 6f 67 69 6e 5f 61  p, 0);.  login_a
b5e0: 6e 6f 6e 5f 6f 6e 63 65 20 3d 20 31 3b 0a 20 20  non_once = 1;.  
b5f0: 6c 6f 67 69 6e 5f 73 65 74 5f 61 6e 6f 6e 5f 6e  login_set_anon_n
b600: 6f 62 6f 64 79 5f 63 61 70 61 62 69 6c 69 74 69  obody_capabiliti
b610: 65 73 28 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 52  es();.}../*.** R
b620: 65 74 75 72 6e 20 74 72 75 65 20 69 66 20 74 68  eturn true if th
b630: 65 20 75 73 65 72 20 69 73 20 22 6e 6f 62 6f 64  e user is "nobod
b640: 79 22 0a 2a 2f 0a 69 6e 74 20 6c 6f 67 69 6e 5f  y".*/.int login_
b650: 69 73 5f 6e 6f 62 6f 64 79 28 76 6f 69 64 29 7b  is_nobody(void){
b660: 0a 20 20 72 65 74 75 72 6e 20 67 2e 7a 4c 6f 67  .  return g.zLog
b670: 69 6e 3d 3d 30 20 7c 7c 20 67 2e 7a 4c 6f 67 69  in==0 || g.zLogi
b680: 6e 5b 30 5d 3d 3d 30 20 7c 7c 20 66 6f 73 73 69  n[0]==0 || fossi
b690: 6c 5f 73 74 72 63 6d 70 28 67 2e 7a 4c 6f 67 69  l_strcmp(g.zLogi
b6a0: 6e 2c 22 6e 6f 62 6f 64 79 22 29 3d 3d 30 3b 0a  n,"nobody")==0;.
b6b0: 7d 0a 0a 2f 2a 0a 2a 2a 20 52 65 74 75 72 6e 20  }../*.** Return 
b6c0: 74 72 75 65 20 69 66 20 74 68 65 20 75 73 65 72  true if the user
b6d0: 20 69 73 20 61 20 73 70 65 63 69 66 69 63 20 69   is a specific i
b6e0: 6e 64 69 76 69 64 75 61 6c 2c 20 6e 6f 74 20 22  ndividual, not "
b6f0: 6e 6f 62 6f 64 79 22 20 6f 72 0a 2a 2a 20 22 61  nobody" or.** "a
b700: 6e 6f 6e 79 6d 6f 75 73 22 2e 0a 2a 2f 0a 69 6e  nonymous"..*/.in
b710: 74 20 6c 6f 67 69 6e 5f 69 73 5f 69 6e 64 69 76  t login_is_indiv
b720: 69 64 75 61 6c 28 76 6f 69 64 29 7b 0a 20 20 72  idual(void){.  r
b730: 65 74 75 72 6e 20 67 2e 7a 4c 6f 67 69 6e 21 3d  eturn g.zLogin!=
b740: 30 20 26 26 20 67 2e 7a 4c 6f 67 69 6e 5b 30 5d  0 && g.zLogin[0]
b750: 21 3d 30 20 26 26 20 66 6f 73 73 69 6c 5f 73 74  !=0 && fossil_st
b760: 72 63 6d 70 28 67 2e 7a 4c 6f 67 69 6e 2c 22 6e  rcmp(g.zLogin,"n
b770: 6f 62 6f 64 79 22 29 21 3d 30 0a 20 20 20 20 20  obody")!=0.     
b780: 20 20 20 20 20 20 26 26 20 66 6f 73 73 69 6c 5f        && fossil_
b790: 73 74 72 63 6d 70 28 67 2e 7a 4c 6f 67 69 6e 2c  strcmp(g.zLogin,
b7a0: 22 61 6e 6f 6e 79 6d 6f 75 73 22 29 21 3d 30 3b  "anonymous")!=0;
b7b0: 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 52 65 74 75 72 6e  .}../*.** Return
b7c0: 20 74 68 65 20 6c 6f 67 69 6e 20 6e 61 6d 65 2e   the login name.
b7d0: 20 20 49 66 20 6e 6f 20 6c 6f 67 69 6e 20 6e 61    If no login na
b7e0: 6d 65 20 69 73 20 73 70 65 63 69 66 69 65 64 2c  me is specified,
b7f0: 20 72 65 74 75 72 6e 20 22 6e 6f 62 6f 64 79 22   return "nobody"
b800: 2e 0a 2a 2f 0a 63 6f 6e 73 74 20 63 68 61 72 20  ..*/.const char 
b810: 2a 6c 6f 67 69 6e 5f 6e 61 6d 65 28 76 6f 69 64  *login_name(void
b820: 29 7b 0a 20 20 72 65 74 75 72 6e 20 28 67 2e 7a  ){.  return (g.z
b830: 4c 6f 67 69 6e 20 26 26 20 67 2e 7a 4c 6f 67 69  Login && g.zLogi
b840: 6e 5b 30 5d 29 20 3f 20 67 2e 7a 4c 6f 67 69 6e  n[0]) ? g.zLogin
b850: 20 3a 20 22 6e 6f 62 6f 64 79 22 3b 0a 7d 0a 0a   : "nobody";.}..
b860: 2f 2a 0a 2a 2a 20 43 61 6c 6c 20 74 68 69 73 20  /*.** Call this 
b870: 72 6f 75 74 69 6e 65 20 77 68 65 6e 20 74 68 65  routine when the
b880: 20 63 72 65 64 65 6e 74 69 61 6c 20 63 68 65 63   credential chec
b890: 6b 20 66 61 69 6c 73 2e 20 20 49 74 20 63 61 75  k fails.  It cau
b8a0: 73 65 73 0a 2a 2a 20 61 20 72 65 64 69 72 65 63  ses.** a redirec
b8b0: 74 20 74 6f 20 74 68 65 20 22 6c 6f 67 69 6e 22  t to the "login"
b8c0: 20 70 61 67 65 2e 0a 2a 2f 0a 76 6f 69 64 20 6c   page..*/.void l
b8d0: 6f 67 69 6e 5f 6e 65 65 64 65 64 28 69 6e 74 20  ogin_needed(int 
b8e0: 61 6e 6f 6e 4f 6b 29 7b 0a 23 69 66 64 65 66 20  anonOk){.#ifdef 
b8f0: 46 4f 53 53 49 4c 5f 45 4e 41 42 4c 45 5f 4a 53  FOSSIL_ENABLE_JS
b900: 4f 4e 0a 20 20 69 66 28 67 2e 6a 73 6f 6e 2e 69  ON.  if(g.json.i
b910: 73 4a 73 6f 6e 4d 6f 64 65 29 7b 0a 20 20 20 20  sJsonMode){.    
b920: 6a 73 6f 6e 5f 65 72 72 28 20 46 53 4c 5f 4a 53  json_err( FSL_JS
b930: 4f 4e 5f 45 5f 44 45 4e 49 45 44 2c 20 4e 55 4c  ON_E_DENIED, NUL
b940: 4c 2c 20 31 20 29 3b 0a 20 20 20 20 66 6f 73 73  L, 1 );.    foss
b950: 69 6c 5f 65 78 69 74 28 30 29 3b 0a 20 20 20 20  il_exit(0);.    
b960: 2f 2a 20 4e 4f 54 52 45 41 43 48 45 44 20 2a 2f  /* NOTREACHED */
b970: 0a 20 20 20 20 61 73 73 65 72 74 28 30 29 3b 0a  .    assert(0);.
b980: 20 20 7d 65 6c 73 65 0a 23 65 6e 64 69 66 20 2f    }else.#endif /
b990: 2a 20 46 4f 53 53 49 4c 5f 45 4e 41 42 4c 45 5f  * FOSSIL_ENABLE_
b9a0: 4a 53 4f 4e 20 2a 2f 0a 20 20 7b 0a 20 20 20 20  JSON */.  {.    
b9b0: 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 55 72 6c  const char *zUrl
b9c0: 20 3d 20 50 44 28 22 52 45 51 55 45 53 54 5f 55   = PD("REQUEST_U
b9d0: 52 49 22 2c 20 22 69 6e 64 65 78 22 29 3b 0a 20  RI", "index");. 
b9e0: 20 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a     const char *z
b9f0: 51 53 20 3d 20 50 28 22 51 55 45 52 59 5f 53 54  QS = P("QUERY_ST
ba00: 52 49 4e 47 22 29 3b 0a 20 20 20 20 42 6c 6f 62  RING");.    Blob
ba10: 20 72 65 64 69 72 3b 0a 20 20 20 20 62 6c 6f 62   redir;.    blob
ba20: 5f 69 6e 69 74 28 26 72 65 64 69 72 2c 20 30 2c  _init(&redir, 0,
ba30: 20 30 29 3b 0a 20 20 20 20 69 66 28 20 66 6f 73   0);.    if( fos
ba40: 73 69 6c 5f 77 61 6e 74 73 5f 68 74 74 70 73 28  sil_wants_https(
ba50: 31 29 20 29 7b 0a 20 20 20 20 20 20 62 6c 6f 62  1) ){.      blob
ba60: 5f 61 70 70 65 6e 64 66 28 26 72 65 64 69 72 2c  _appendf(&redir,
ba70: 20 22 25 73 2f 6c 6f 67 69 6e 3f 67 3d 25 54 22   "%s/login?g=%T"
ba80: 2c 20 67 2e 7a 48 74 74 70 73 55 52 4c 2c 20 7a  , g.zHttpsURL, z
ba90: 55 72 6c 29 3b 0a 20 20 20 20 7d 65 6c 73 65 7b  Url);.    }else{
baa0: 0a 20 20 20 20 20 20 62 6c 6f 62 5f 61 70 70 65  .      blob_appe
bab0: 6e 64 66 28 26 72 65 64 69 72 2c 20 22 25 52 2f  ndf(&redir, "%R/
bac0: 6c 6f 67 69 6e 3f 67 3d 25 54 22 2c 20 7a 55 72  login?g=%T", zUr
bad0: 6c 29 3b 0a 20 20 20 20 7d 0a 20 20 20 20 69 66  l);.    }.    if
bae0: 28 20 61 6e 6f 6e 4f 6b 20 29 20 62 6c 6f 62 5f  ( anonOk ) blob_
baf0: 61 70 70 65 6e 64 28 26 72 65 64 69 72 2c 20 22  append(&redir, "
bb00: 26 61 6e 6f 6e 22 2c 20 35 29 3b 0a 20 20 20 20  &anon", 5);.    
bb10: 69 66 28 20 7a 51 53 20 26 26 20 7a 51 53 5b 30  if( zQS && zQS[0
bb20: 5d 20 29 7b 0a 20 20 20 20 20 20 62 6c 6f 62 5f  ] ){.      blob_
bb30: 61 70 70 65 6e 64 66 28 26 72 65 64 69 72 2c 20  appendf(&redir, 
bb40: 22 26 25 73 22 2c 20 7a 51 53 29 3b 0a 20 20 20  "&%s", zQS);.   
bb50: 20 7d 0a 20 20 20 20 63 67 69 5f 72 65 64 69 72   }.    cgi_redir
bb60: 65 63 74 28 62 6c 6f 62 5f 73 74 72 28 26 72 65  ect(blob_str(&re
bb70: 64 69 72 29 29 3b 0a 20 20 20 20 2f 2a 20 4e 4f  dir));.    /* NO
bb80: 54 52 45 41 43 48 45 44 20 2a 2f 0a 20 20 20 20  TREACHED */.    
bb90: 61 73 73 65 72 74 28 30 29 3b 0a 20 20 7d 0a 7d  assert(0);.  }.}
bba0: 0a 0a 2f 2a 0a 2a 2a 20 43 61 6c 6c 20 74 68 69  ../*.** Call thi
bbb0: 73 20 72 6f 75 74 69 6e 65 20 69 66 20 74 68 65  s routine if the
bbc0: 20 75 73 65 72 20 6c 61 63 6b 73 20 67 2e 70 65   user lacks g.pe
bbd0: 72 6d 2e 48 79 70 65 72 6c 69 6e 6b 20 70 65 72  rm.Hyperlink per
bbe0: 6d 69 73 73 69 6f 6e 2e 20 20 49 66 0a 2a 2a 20  mission.  If.** 
bbf0: 74 68 65 20 61 6e 6f 6e 79 6d 6f 75 73 20 75 73  the anonymous us
bc00: 65 72 20 68 61 73 20 48 79 70 65 72 6c 69 6e 6b  er has Hyperlink
bc10: 20 70 65 72 6d 69 73 73 69 6f 6e 2c 20 74 68 65   permission, the
bc20: 6e 20 70 61 69 6e 74 20 61 20 6d 65 73 61 67 65  n paint a mesage
bc30: 0a 2a 2a 20 74 6f 20 69 6e 66 6f 72 6d 20 74 68  .** to inform th
bc40: 65 20 75 73 65 72 20 74 68 61 74 20 6d 75 63 68  e user that much
bc50: 20 6d 6f 72 65 20 69 6e 66 6f 72 6d 61 74 69 6f   more informatio
bc60: 6e 20 69 73 20 61 76 61 69 6c 61 62 6c 65 20 62  n is available b
bc70: 79 0a 2a 2a 20 6c 6f 67 67 69 6e 67 20 69 6e 20  y.** logging in 
bc80: 61 73 20 61 6e 6f 6e 79 6d 6f 75 73 2e 0a 2a 2f  as anonymous..*/
bc90: 0a 76 6f 69 64 20 6c 6f 67 69 6e 5f 61 6e 6f 6e  .void login_anon
bca0: 79 6d 6f 75 73 5f 61 76 61 69 6c 61 62 6c 65 28  ymous_available(
bcb0: 76 6f 69 64 29 7b 0a 20 20 69 66 28 20 21 67 2e  void){.  if( !g.
bcc0: 70 65 72 6d 2e 48 79 70 65 72 6c 69 6e 6b 20 26  perm.Hyperlink &
bcd0: 26 20 67 2e 61 6e 6f 6e 2e 48 79 70 65 72 6c 69  & g.anon.Hyperli
bce0: 6e 6b 20 29 7b 0a 20 20 20 20 63 6f 6e 73 74 20  nk ){.    const 
bcf0: 63 68 61 72 20 2a 7a 55 72 6c 20 3d 20 50 44 28  char *zUrl = PD(
bd00: 22 52 45 51 55 45 53 54 5f 55 52 49 22 2c 20 22  "REQUEST_URI", "
bd10: 69 6e 64 65 78 22 29 3b 0a 20 20 20 20 40 20 3c  index");.    @ <
bd20: 70 3e 4d 61 6e 79 20 3c 73 70 61 6e 20 63 6c 61  p>Many <span cla
bd30: 73 73 3d 22 64 69 73 61 62 6c 65 64 22 3e 68 79  ss="disabled">hy
bd40: 70 65 72 6c 69 6e 6b 73 20 61 72 65 20 64 69 73  perlinks are dis
bd50: 61 62 6c 65 64 2e 3c 2f 73 70 61 6e 3e 3c 62 72  abled.</span><br
bd60: 20 2f 3e 0a 20 20 20 20 40 20 55 73 65 20 3c 61   />.    @ Use <a
bd70: 20 68 72 65 66 3d 22 25 52 2f 6c 6f 67 69 6e 3f   href="%R/login?
bd80: 61 6e 6f 6e 3d 31 26 61 6d 70 3b 67 3d 25 54 28  anon=1&amp;g=%T(
bd90: 7a 55 72 6c 29 22 3e 61 6e 6f 6e 79 6d 6f 75 73  zUrl)">anonymous
bda0: 20 6c 6f 67 69 6e 3c 2f 61 3e 0a 20 20 20 20 40   login</a>.    @
bdb0: 20 74 6f 20 65 6e 61 62 6c 65 20 68 79 70 65 72   to enable hyper
bdc0: 6c 69 6e 6b 73 2e 3c 2f 70 3e 0a 20 20 7d 0a 7d  links.</p>.  }.}
bdd0: 0a 0a 2f 2a 0a 2a 2a 20 57 68 69 6c 65 20 72 65  ../*.** While re
bde0: 6e 64 65 72 69 6e 67 20 61 20 66 6f 72 6d 2c 20  ndering a form, 
bdf0: 63 61 6c 6c 20 74 68 69 73 20 72 6f 75 74 69 6e  call this routin
be00: 65 20 74 6f 20 61 64 64 20 74 68 65 20 41 6e 74  e to add the Ant
be10: 69 2d 43 53 52 46 20 74 6f 6b 65 6e 0a 2a 2a 20  i-CSRF token.** 
be20: 61 73 20 61 20 68 69 64 64 65 6e 20 65 6c 65 6d  as a hidden elem
be30: 65 6e 74 20 6f 66 20 74 68 65 20 66 6f 72 6d 2e  ent of the form.
be40: 0a 2a 2f 0a 76 6f 69 64 20 6c 6f 67 69 6e 5f 69  .*/.void login_i
be50: 6e 73 65 72 74 5f 63 73 72 66 5f 73 65 63 72 65  nsert_csrf_secre
be60: 74 28 76 6f 69 64 29 7b 0a 20 20 40 20 3c 69 6e  t(void){.  @ <in
be70: 70 75 74 20 74 79 70 65 3d 22 68 69 64 64 65 6e  put type="hidden
be80: 22 20 6e 61 6d 65 3d 22 63 73 72 66 22 20 76 61  " name="csrf" va
be90: 6c 75 65 3d 22 25 73 28 67 2e 7a 43 73 72 66 54  lue="%s(g.zCsrfT
bea0: 6f 6b 65 6e 29 22 20 2f 3e 0a 7d 0a 0a 2f 2a 0a  oken)" />.}../*.
beb0: 2a 2a 20 42 65 66 6f 72 65 20 75 73 69 6e 67 20  ** Before using 
bec0: 74 68 65 20 72 65 73 75 6c 74 73 20 6f 66 20 61  the results of a
bed0: 20 66 6f 72 6d 2c 20 66 69 72 73 74 20 63 61 6c   form, first cal
bee0: 6c 20 74 68 69 73 20 72 6f 75 74 69 6e 65 20 74  l this routine t
bef0: 6f 20 76 65 72 69 66 79 0a 2a 2a 20 74 68 61 74  o verify.** that
bf00: 20 74 68 69 73 20 41 6e 74 69 2d 43 53 52 46 20   this Anti-CSRF 
bf10: 74 6f 6b 65 6e 20 69 73 20 70 72 65 73 65 6e 74  token is present
bf20: 20 61 6e 64 20 69 73 20 76 61 6c 69 64 2e 20 20   and is valid.  
bf30: 49 66 20 74 68 65 20 41 6e 74 69 2d 43 53 52 46  If the Anti-CSRF
bf40: 20 74 6f 6b 65 6e 0a 2a 2a 20 69 73 20 6d 69 73   token.** is mis
bf50: 73 69 6e 67 20 6f 72 20 69 73 20 69 6e 63 6f 72  sing or is incor
bf60: 72 65 63 74 2c 20 74 68 61 74 20 69 6e 64 69 63  rect, that indic
bf70: 61 74 65 73 20 61 20 63 72 6f 73 73 2d 73 69 74  ates a cross-sit
bf80: 65 20 73 63 72 69 70 74 69 6e 67 20 61 74 74 61  e scripting atta
bf90: 63 6b 2e 0a 2a 2a 20 49 66 20 74 68 65 20 65 76  ck..** If the ev
bfa0: 65 6e 74 20 6f 66 20 61 6e 20 61 74 74 61 63 6b  ent of an attack
bfb0: 20 69 73 20 64 65 74 65 63 74 65 64 2c 20 61 6e   is detected, an
bfc0: 20 65 72 72 6f 72 20 6d 65 73 73 61 67 65 20 69   error message i
bfd0: 73 20 67 65 6e 65 72 61 74 65 64 20 61 6e 64 0a  s generated and.
bfe0: 2a 2a 20 61 6c 6c 20 66 75 72 74 68 65 72 20 70  ** all further p
bff0: 72 6f 63 65 73 73 69 6e 67 20 69 73 20 61 62 6f  rocessing is abo
c000: 72 74 65 64 2e 0a 2a 2f 0a 76 6f 69 64 20 6c 6f  rted..*/.void lo
c010: 67 69 6e 5f 76 65 72 69 66 79 5f 63 73 72 66 5f  gin_verify_csrf_
c020: 73 65 63 72 65 74 28 76 6f 69 64 29 7b 0a 20 20  secret(void){.  
c030: 69 66 28 20 67 2e 6f 6b 43 73 72 66 20 29 20 72  if( g.okCsrf ) r
c040: 65 74 75 72 6e 3b 0a 20 20 69 66 28 20 66 6f 73  eturn;.  if( fos
c050: 73 69 6c 5f 73 74 72 63 6d 70 28 50 28 22 63 73  sil_strcmp(P("cs
c060: 72 66 22 29 2c 20 67 2e 7a 43 73 72 66 54 6f 6b  rf"), g.zCsrfTok
c070: 65 6e 29 3d 3d 30 20 29 7b 0a 20 20 20 20 67 2e  en)==0 ){.    g.
c080: 6f 6b 43 73 72 66 20 3d 20 31 3b 0a 20 20 20 20  okCsrf = 1;.    
c090: 72 65 74 75 72 6e 3b 0a 20 20 7d 0a 20 20 66 6f  return;.  }.  fo
c0a0: 73 73 69 6c 5f 66 61 74 61 6c 28 22 43 72 6f 73  ssil_fatal("Cros
c0b0: 73 2d 73 69 74 65 20 72 65 71 75 65 73 74 20 66  s-site request f
c0c0: 6f 72 67 65 72 79 20 61 74 74 65 6d 70 74 22 29  orgery attempt")
c0d0: 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 57 45 42 50 41  ;.}../*.** WEBPA
c0e0: 47 45 3a 20 72 65 67 69 73 74 65 72 0a 2a 2a 0a  GE: register.**.
c0f0: 2a 2a 20 50 61 67 65 20 74 6f 20 61 6c 6c 6f 77  ** Page to allow
c100: 20 75 73 65 72 73 20 74 6f 20 73 65 6c 66 2d 72   users to self-r
c110: 65 67 69 73 74 65 72 2e 20 20 54 68 65 20 22 73  egister.  The "s
c120: 65 6c 66 2d 72 65 67 69 73 74 65 72 22 20 73 65  elf-register" se
c130: 74 74 69 6e 67 0a 2a 2a 20 6d 75 73 74 20 62 65  tting.** must be
c140: 20 65 6e 61 62 6c 65 64 20 66 6f 72 20 74 68 69   enabled for thi
c150: 73 20 70 61 67 65 20 74 6f 20 6f 70 65 72 61 74  s page to operat
c160: 65 2e 0a 2a 2f 0a 76 6f 69 64 20 72 65 67 69 73  e..*/.void regis
c170: 74 65 72 5f 70 61 67 65 28 76 6f 69 64 29 7b 0a  ter_page(void){.
c180: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 55    const char *zU
c190: 73 65 72 49 44 2c 20 2a 7a 50 61 73 73 77 64 2c  serID, *zPasswd,
c1a0: 20 2a 7a 43 6f 6e 66 69 72 6d 2c 20 2a 7a 45 41   *zConfirm, *zEA
c1b0: 64 64 72 3b 0a 20 20 63 6f 6e 73 74 20 63 68 61  ddr;.  const cha
c1c0: 72 20 2a 7a 44 4e 61 6d 65 3b 0a 20 20 75 6e 73  r *zDName;.  uns
c1d0: 69 67 6e 65 64 20 69 6e 74 20 75 53 65 65 64 3b  igned int uSeed;
c1e0: 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a  .  const char *z
c1f0: 44 65 63 6f 64 65 64 3b 0a 20 20 63 68 61 72 20  Decoded;.  char 
c200: 2a 7a 43 61 70 74 63 68 61 3b 0a 20 20 69 6e 74  *zCaptcha;.  int
c210: 20 69 45 72 72 4c 69 6e 65 20 3d 20 2d 31 3b 0a   iErrLine = -1;.
c220: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 45    const char *zE
c230: 72 72 20 3d 20 30 3b 0a 20 20 63 68 61 72 20 2a  rr = 0;.  char *
c240: 7a 50 65 72 6d 73 3b 20 20 20 20 20 20 20 20 20  zPerms;         
c250: 20 20 20 20 2f 2a 20 50 65 72 6d 69 73 73 69 6f      /* Permissio
c260: 6e 73 20 66 6f 72 20 74 68 65 20 64 65 66 61 75  ns for the defau
c270: 6c 74 20 75 73 65 72 20 2a 2f 0a 20 20 69 6e 74  lt user */.  int
c280: 20 63 61 6e 44 6f 41 6c 65 72 74 73 20 3d 20 30   canDoAlerts = 0
c290: 3b 20 20 20 20 20 20 2f 2a 20 54 72 75 65 20 69  ;      /* True i
c2a0: 66 20 72 65 63 65 69 76 69 6e 67 20 65 6d 61 69  f receiving emai
c2b0: 6c 20 61 6c 65 72 74 73 20 69 73 20 70 6f 73 73  l alerts is poss
c2c0: 69 62 6c 65 20 2a 2f 0a 20 20 69 6e 74 20 64 6f  ible */.  int do
c2d0: 41 6c 65 72 74 73 20 3d 20 30 3b 20 20 20 20 20  Alerts = 0;     
c2e0: 20 20 20 20 2f 2a 20 54 72 75 65 20 69 66 20 73      /* True if s
c2f0: 75 62 73 63 72 69 70 74 69 6f 6e 20 69 73 20 77  ubscription is w
c300: 61 6e 74 65 64 20 74 6f 6f 20 2a 2f 0a 20 20 69  anted too */.  i
c310: 66 28 20 21 64 62 5f 67 65 74 5f 62 6f 6f 6c 65  f( !db_get_boole
c320: 61 6e 28 22 73 65 6c 66 2d 72 65 67 69 73 74 65  an("self-registe
c330: 72 22 2c 20 30 29 20 29 7b 0a 20 20 20 20 73 74  r", 0) ){.    st
c340: 79 6c 65 5f 68 65 61 64 65 72 28 22 52 65 67 69  yle_header("Regi
c350: 73 74 72 61 74 69 6f 6e 20 6e 6f 74 20 70 6f 73  stration not pos
c360: 73 69 62 6c 65 22 29 3b 0a 20 20 20 20 40 20 3c  sible");.    @ <
c370: 70 3e 54 68 69 73 20 70 72 6f 6a 65 63 74 20 64  p>This project d
c380: 6f 65 73 20 6e 6f 74 20 61 6c 6c 6f 77 20 75 73  oes not allow us
c390: 65 72 20 73 65 6c 66 2d 72 65 67 69 73 74 72 61  er self-registra
c3a0: 74 69 6f 6e 2e 20 50 6c 65 61 73 65 20 63 6f 6e  tion. Please con
c3b0: 74 61 63 74 20 74 68 65 0a 20 20 20 20 40 20 70  tact the.    @ p
c3c0: 72 6f 6a 65 63 74 20 61 64 6d 69 6e 69 73 74 72  roject administr
c3d0: 61 74 6f 72 20 74 6f 20 6f 62 74 61 69 6e 20 61  ator to obtain a
c3e0: 6e 20 61 63 63 6f 75 6e 74 2e 3c 2f 70 3e 0a 20  n account.</p>. 
c3f0: 20 20 20 73 74 79 6c 65 5f 66 6f 6f 74 65 72 28     style_footer(
c400: 29 3b 0a 20 20 20 20 72 65 74 75 72 6e 3b 0a 20  );.    return;. 
c410: 20 7d 0a 20 20 7a 50 65 72 6d 73 20 3d 20 64 62   }.  zPerms = db
c420: 5f 67 65 74 28 22 64 65 66 61 75 6c 74 2d 70 65  _get("default-pe
c430: 72 6d 73 22 2c 22 75 22 29 3b 0a 0a 20 20 2f 2a  rms","u");..  /*
c440: 20 50 72 6f 6d 70 74 20 74 68 65 20 75 73 65 72   Prompt the user
c450: 20 66 6f 72 20 65 6d 61 69 6c 20 61 6c 65 72 74   for email alert
c460: 73 20 69 66 20 74 68 69 73 20 72 65 70 6f 73 69  s if this reposi
c470: 74 6f 72 79 20 69 73 20 63 6f 6e 66 69 67 75 72  tory is configur
c480: 65 64 20 66 6f 72 0a 20 20 2a 2a 20 65 6d 61 69  ed for.  ** emai
c490: 6c 20 61 6c 65 72 74 73 20 61 6e 64 20 69 66 20  l alerts and if 
c4a0: 74 68 65 20 64 65 66 61 75 6c 74 20 70 65 72 6d  the default perm
c4b0: 69 73 73 69 6f 6e 73 20 69 6e 63 6c 75 64 65 20  issions include 
c4c0: 22 37 22 20 2a 2f 0a 20 20 63 61 6e 44 6f 41 6c  "7" */.  canDoAl
c4d0: 65 72 74 73 20 3d 20 61 6c 65 72 74 5f 74 61 62  erts = alert_tab
c4e0: 6c 65 73 5f 65 78 69 73 74 28 29 20 26 26 20 64  les_exist() && d
c4f0: 62 5f 69 6e 74 28 30 2c 0a 20 20 20 20 22 53 45  b_int(0,.    "SE
c500: 4c 45 43 54 20 66 75 6c 6c 63 61 70 28 25 51 29  LECT fullcap(%Q)
c510: 20 47 4c 4f 42 20 27 2a 37 2a 27 22 2c 20 7a 50   GLOB '*7*'", zP
c520: 65 72 6d 73 0a 20 20 29 3b 0a 20 20 64 6f 41 6c  erms.  );.  doAl
c530: 65 72 74 73 20 3d 20 63 61 6e 44 6f 41 6c 65 72  erts = canDoAler
c540: 74 73 20 26 26 20 61 74 6f 69 28 50 44 28 22 61  ts && atoi(PD("a
c550: 6c 65 72 74 73 22 2c 22 31 22 29 29 21 3d 30 3b  lerts","1"))!=0;
c560: 0a 0a 20 20 7a 55 73 65 72 49 44 20 3d 20 50 44  ..  zUserID = PD
c570: 54 28 22 75 22 2c 22 22 29 3b 0a 20 20 7a 50 61  T("u","");.  zPa
c580: 73 73 77 64 20 3d 20 50 44 54 28 22 70 22 2c 22  sswd = PDT("p","
c590: 22 29 3b 0a 20 20 7a 43 6f 6e 66 69 72 6d 20 3d  ");.  zConfirm =
c5a0: 20 50 44 54 28 22 63 70 22 2c 22 22 29 3b 0a 20   PDT("cp","");. 
c5b0: 20 7a 45 41 64 64 72 20 3d 20 50 44 54 28 22 65   zEAddr = PDT("e
c5c0: 61 22 2c 22 22 29 3b 0a 20 20 7a 44 4e 61 6d 65  a","");.  zDName
c5d0: 20 3d 20 50 44 54 28 22 64 6e 22 2c 22 22 29 3b   = PDT("dn","");
c5e0: 0a 0a 20 20 2f 2a 20 56 65 72 69 66 79 20 75 73  ..  /* Verify us
c5f0: 65 72 20 69 6d 70 75 74 73 20 2a 2f 0a 20 20 69  er imputs */.  i
c600: 66 28 20 50 28 22 6e 65 77 22 29 3d 3d 30 20 7c  f( P("new")==0 |
c610: 7c 20 21 63 67 69 5f 63 73 72 66 5f 73 61 66 65  | !cgi_csrf_safe
c620: 28 31 29 20 29 7b 0a 20 20 20 20 2f 2a 20 54 68  (1) ){.    /* Th
c630: 69 73 20 69 73 20 6e 6f 74 20 61 20 76 61 6c 69  is is not a vali
c640: 64 20 66 6f 72 6d 20 73 75 62 6d 69 73 73 69 6f  d form submissio
c650: 6e 2e 20 20 46 61 6c 6c 20 74 68 72 6f 75 67 68  n.  Fall through
c660: 20 69 6e 74 6f 0a 20 20 20 20 2a 2a 20 74 68 65   into.    ** the
c670: 20 66 6f 72 6d 20 64 69 73 70 6c 61 79 20 2a 2f   form display */
c680: 0a 20 20 7d 65 6c 73 65 20 69 66 28 20 21 63 61  .  }else if( !ca
c690: 70 74 63 68 61 5f 69 73 5f 63 6f 72 72 65 63 74  ptcha_is_correct
c6a0: 28 31 29 20 29 7b 0a 20 20 20 20 69 45 72 72 4c  (1) ){.    iErrL
c6b0: 69 6e 65 20 3d 20 36 3b 0a 20 20 20 20 7a 45 72  ine = 6;.    zEr
c6c0: 72 20 3d 20 22 49 6e 63 6f 72 72 65 63 74 20 43  r = "Incorrect C
c6d0: 41 50 54 43 48 41 22 3b 0a 20 20 7d 65 6c 73 65  APTCHA";.  }else
c6e0: 20 69 66 28 20 73 74 72 6c 65 6e 28 7a 55 73 65   if( strlen(zUse
c6f0: 72 49 44 29 3c 33 20 29 7b 0a 20 20 20 20 69 45  rID)<3 ){.    iE
c700: 72 72 4c 69 6e 65 20 3d 20 31 3b 0a 20 20 20 20  rrLine = 1;.    
c710: 7a 45 72 72 20 3d 20 22 55 73 65 72 20 49 44 20  zErr = "User ID 
c720: 74 6f 6f 20 73 68 6f 72 74 2e 20 4d 75 73 74 20  too short. Must 
c730: 62 65 20 61 74 20 6c 65 61 73 74 20 33 20 63 68  be at least 3 ch
c740: 61 72 61 63 74 65 72 73 2e 22 3b 0a 20 20 7d 65  aracters.";.  }e
c750: 6c 73 65 20 69 66 28 20 73 71 6c 69 74 65 33 5f  lse if( sqlite3_
c760: 73 74 72 67 6c 6f 62 28 22 2a 5b 5e 2d 61 2d 7a  strglob("*[^-a-z
c770: 41 2d 5a 30 2d 39 5f 2e 5d 2a 22 2c 7a 55 73 65  A-Z0-9_.]*",zUse
c780: 72 49 44 29 3d 3d 30 20 29 7b 0a 20 20 20 20 69  rID)==0 ){.    i
c790: 45 72 72 4c 69 6e 65 20 3d 20 31 3b 0a 20 20 20  ErrLine = 1;.   
c7a0: 20 7a 45 72 72 20 3d 20 22 55 73 65 72 20 49 44   zErr = "User ID
c7b0: 20 6d 61 79 20 6e 6f 74 20 63 6f 6e 74 61 69 6e   may not contain
c7c0: 20 73 70 61 63 65 73 20 6f 72 20 73 70 65 63 69   spaces or speci
c7d0: 61 6c 20 63 68 61 72 61 63 74 65 72 73 2e 22 3b  al characters.";
c7e0: 0a 20 20 7d 65 6c 73 65 20 69 66 28 20 7a 44 4e  .  }else if( zDN
c7f0: 61 6d 65 5b 30 5d 3d 3d 30 20 29 7b 0a 20 20 20  ame[0]==0 ){.   
c800: 20 69 45 72 72 4c 69 6e 65 20 3d 20 32 3b 0a 20   iErrLine = 2;. 
c810: 20 20 20 7a 45 72 72 20 3d 20 22 52 65 71 75 69     zErr = "Requi
c820: 72 65 64 22 3b 0a 20 20 7d 65 6c 73 65 20 69 66  red";.  }else if
c830: 28 20 7a 45 41 64 64 72 5b 30 5d 3d 3d 30 20 29  ( zEAddr[0]==0 )
c840: 7b 0a 20 20 20 20 69 45 72 72 4c 69 6e 65 20 3d  {.    iErrLine =
c850: 20 33 3b 0a 20 20 20 20 7a 45 72 72 20 3d 20 22   3;.    zErr = "
c860: 52 65 71 75 69 72 65 64 22 3b 0a 20 20 7d 65 6c  Required";.  }el
c870: 73 65 20 69 66 28 20 65 6d 61 69 6c 5f 63 6f 70  se if( email_cop
c880: 79 5f 61 64 64 72 28 7a 45 41 64 64 72 2c 30 29  y_addr(zEAddr,0)
c890: 3d 3d 30 20 29 7b 0a 20 20 20 20 69 45 72 72 4c  ==0 ){.    iErrL
c8a0: 69 6e 65 20 3d 20 33 3b 0a 20 20 20 20 7a 45 72  ine = 3;.    zEr
c8b0: 72 20 3d 20 22 4e 6f 74 20 61 20 76 61 6c 69 64  r = "Not a valid
c8c0: 20 65 6d 61 69 6c 20 61 64 64 72 65 73 73 22 3b   email address";
c8d0: 0a 20 20 7d 65 6c 73 65 20 69 66 28 20 73 74 72  .  }else if( str
c8e0: 6c 65 6e 28 7a 50 61 73 73 77 64 29 3c 36 20 29  len(zPasswd)<6 )
c8f0: 7b 0a 20 20 20 20 69 45 72 72 4c 69 6e 65 20 3d  {.    iErrLine =
c900: 20 34 3b 0a 20 20 20 20 7a 45 72 72 20 3d 20 22   4;.    zErr = "
c910: 50 61 73 73 77 6f 72 64 20 6d 75 73 74 20 62 65  Password must be
c920: 20 61 74 20 6c 65 61 73 74 20 36 20 63 68 61 72   at least 6 char
c930: 61 63 74 65 72 73 20 6c 6f 6e 67 22 3b 0a 20 20  acters long";.  
c940: 7d 65 6c 73 65 20 69 66 28 20 66 6f 73 73 69 6c  }else if( fossil
c950: 5f 73 74 72 63 6d 70 28 7a 50 61 73 73 77 64 2c  _strcmp(zPasswd,
c960: 7a 43 6f 6e 66 69 72 6d 29 21 3d 30 20 29 7b 0a  zConfirm)!=0 ){.
c970: 20 20 20 20 69 45 72 72 4c 69 6e 65 20 3d 20 35      iErrLine = 5
c980: 3b 0a 20 20 20 20 7a 45 72 72 20 3d 20 22 50 61  ;.    zErr = "Pa
c990: 73 73 77 6f 72 64 73 20 64 6f 20 6e 6f 74 20 6d  sswords do not m
c9a0: 61 74 63 68 22 3b 0a 20 20 7d 65 6c 73 65 20 69  atch";.  }else i
c9b0: 66 28 20 64 62 5f 65 78 69 73 74 73 28 22 53 45  f( db_exists("SE
c9c0: 4c 45 43 54 20 31 20 46 52 4f 4d 20 75 73 65 72  LECT 1 FROM user
c9d0: 20 57 48 45 52 45 20 6c 6f 67 69 6e 3d 25 51 22   WHERE login=%Q"
c9e0: 2c 20 7a 55 73 65 72 49 44 29 20 29 7b 0a 20 20  , zUserID) ){.  
c9f0: 20 20 69 45 72 72 4c 69 6e 65 20 3d 20 31 3b 0a    iErrLine = 1;.
ca00: 20 20 20 20 7a 45 72 72 20 3d 20 22 54 68 69 73      zErr = "This
ca10: 20 55 73 65 72 20 49 44 20 69 73 20 61 6c 72 65   User ID is alre
ca20: 61 64 79 20 74 61 6b 65 6e 2e 20 43 68 6f 6f 73  ady taken. Choos
ca30: 65 20 73 6f 6d 65 74 68 69 6e 67 20 64 69 66 66  e something diff
ca40: 65 72 65 6e 74 2e 22 3b 0a 20 20 7d 65 6c 73 65  erent.";.  }else
ca50: 20 69 66 28 0a 20 20 20 20 20 20 2f 2a 20 49 66   if(.      /* If
ca60: 20 74 68 65 20 65 6d 61 69 6c 20 69 73 20 66 6f   the email is fo
ca70: 75 6e 64 20 61 6e 79 77 68 65 72 65 20 69 6e 20  und anywhere in 
ca80: 55 53 45 52 2e 49 4e 46 4f 2e 2e 2e 20 2a 2f 0a  USER.INFO... */.
ca90: 20 20 20 20 20 20 64 62 5f 65 78 69 73 74 73 28        db_exists(
caa0: 22 53 45 4c 45 43 54 20 31 20 46 52 4f 4d 20 75  "SELECT 1 FROM u
cab0: 73 65 72 20 57 48 45 52 45 20 69 6e 66 6f 20 4c  ser WHERE info L
cac0: 49 4b 45 20 27 25 25 25 71 25 25 27 22 2c 20 7a  IKE '%%%q%%'", z
cad0: 45 41 64 64 72 29 0a 20 20 20 20 7c 7c 0a 20 20  EAddr).    ||.  
cae0: 20 20 20 20 2f 2a 20 4f 72 20 69 66 20 74 68 65      /* Or if the
caf0: 20 65 6d 61 69 6c 20 69 73 20 61 20 76 65 72 69   email is a veri
cb00: 66 79 20 73 75 62 73 63 72 69 62 65 72 20 65 6d  fy subscriber em
cb10: 61 69 6c 20 77 69 74 68 20 61 6e 20 61 73 73 6f  ail with an asso
cb20: 63 69 61 74 65 64 0a 20 20 20 20 20 20 2a 2a 20  ciated.      ** 
cb30: 75 73 65 72 2e 2e 2e 20 2a 2f 0a 20 20 20 20 20  user... */.     
cb40: 20 64 62 5f 65 78 69 73 74 73 28 0a 20 20 20 20   db_exists(.    
cb50: 20 20 20 20 22 53 45 4c 45 43 54 20 31 20 46 52      "SELECT 1 FR
cb60: 4f 4d 20 73 75 62 73 63 72 69 62 65 72 20 57 48  OM subscriber WH
cb70: 45 52 45 20 73 65 6d 61 69 6c 3d 25 51 20 41 4e  ERE semail=%Q AN
cb80: 44 20 73 75 6e 61 6d 65 20 49 53 20 4e 4f 54 20  D suname IS NOT 
cb90: 4e 55 4c 4c 22 0a 20 20 20 20 20 20 20 20 22 20  NULL".        " 
cba0: 41 4e 44 20 73 76 65 72 69 66 69 65 64 22 2c 7a  AND sverified",z
cbb0: 45 41 64 64 72 29 0a 20 20 20 29 7b 0a 20 20 20  EAddr).   ){.   
cbc0: 20 69 45 72 72 4c 69 6e 65 20 3d 20 33 3b 0a 20   iErrLine = 3;. 
cbd0: 20 20 20 7a 45 72 72 20 3d 20 22 54 68 69 73 20     zErr = "This 
cbe0: 65 6d 61 69 6c 20 61 64 64 72 65 73 73 20 69 73  email address is
cbf0: 20 61 6c 72 65 61 64 79 20 63 6c 61 69 6d 65 64   already claimed
cc00: 20 62 79 20 61 6e 6f 74 68 65 72 20 75 73 65 72   by another user
cc10: 22 3b 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20  ";.  }else{.    
cc20: 2f 2a 20 49 66 20 61 6c 6c 20 6f 66 20 74 68 65  /* If all of the
cc30: 20 74 65 73 74 73 20 61 62 6f 76 65 20 68 61 76   tests above hav
cc40: 65 20 70 61 73 73 65 64 2c 20 74 68 61 74 20 6d  e passed, that m
cc50: 65 61 6e 73 20 74 68 61 74 20 74 68 65 20 73 75  eans that the su
cc60: 62 6d 69 74 74 65 64 0a 20 20 20 20 2a 2a 20 66  bmitted.    ** f
cc70: 6f 72 6d 20 63 6f 6e 74 61 69 6e 73 20 76 61 6c  orm contains val
cc80: 69 64 20 64 61 74 61 20 61 6e 64 20 77 65 20 63  id data and we c
cc90: 61 6e 20 70 72 6f 63 65 65 64 20 74 6f 20 63 72  an proceed to cr
cca0: 65 61 74 65 20 74 68 65 20 6e 65 77 20 6c 6f 67  eate the new log
ccb0: 69 6e 20 2a 2f 0a 20 20 20 20 42 6c 6f 62 20 73  in */.    Blob s
ccc0: 71 6c 3b 0a 20 20 20 20 69 6e 74 20 75 69 64 3b  ql;.    int uid;
ccd0: 0a 20 20 20 20 63 68 61 72 20 2a 7a 50 61 73 73  .    char *zPass
cce0: 20 3d 20 73 68 61 31 5f 73 68 61 72 65 64 5f 73   = sha1_shared_s
ccf0: 65 63 72 65 74 28 7a 50 61 73 73 77 64 2c 20 7a  ecret(zPasswd, z
cd00: 55 73 65 72 49 44 2c 20 30 29 3b 0a 20 20 20 20  UserID, 0);.    
cd10: 62 6c 6f 62 5f 69 6e 69 74 28 26 73 71 6c 2c 20  blob_init(&sql, 
cd20: 30 2c 20 30 29 3b 0a 20 20 20 20 62 6c 6f 62 5f  0, 0);.    blob_
cd30: 61 70 70 65 6e 64 5f 73 71 6c 28 26 73 71 6c 2c  append_sql(&sql,
cd40: 0a 20 20 20 20 20 20 20 22 49 4e 53 45 52 54 20  .       "INSERT 
cd50: 49 4e 54 4f 20 75 73 65 72 28 6c 6f 67 69 6e 2c  INTO user(login,
cd60: 70 77 2c 63 61 70 2c 69 6e 66 6f 2c 6d 74 69 6d  pw,cap,info,mtim
cd70: 65 29 5c 6e 22 0a 20 20 20 20 20 20 20 22 56 41  e)\n".       "VA
cd80: 4c 55 45 53 28 25 51 2c 25 51 2c 25 51 2c 22 0a  LUES(%Q,%Q,%Q,".
cd90: 20 20 20 20 20 20 20 22 27 25 71 20 3c 25 71 3e         "'%q <%q>
cda0: 5c 6e 73 65 6c 66 2d 72 65 67 69 73 74 65 72 20  \nself-register 
cdb0: 66 72 6f 6d 20 69 70 20 25 71 20 6f 6e 20 27 7c  from ip %q on '|
cdc0: 7c 64 61 74 65 74 69 6d 65 28 27 6e 6f 77 27 29  |datetime('now')
cdd0: 2c 6e 6f 77 28 29 29 22 2c 0a 20 20 20 20 20 20  ,now())",.      
cde0: 20 7a 55 73 65 72 49 44 2c 20 7a 50 61 73 73 2c   zUserID, zPass,
cdf0: 20 7a 50 65 72 6d 73 2c 20 7a 44 4e 61 6d 65 2c   zPerms, zDName,
ce00: 20 7a 45 41 64 64 72 2c 20 67 2e 7a 49 70 41 64   zEAddr, g.zIpAd
ce10: 64 72 29 3b 0a 20 20 20 20 66 6f 73 73 69 6c 5f  dr);.    fossil_
ce20: 66 72 65 65 28 7a 50 61 73 73 29 3b 0a 20 20 20  free(zPass);.   
ce30: 20 64 62 5f 6d 75 6c 74 69 5f 65 78 65 63 28 22   db_multi_exec("
ce40: 25 73 22 2c 20 62 6c 6f 62 5f 73 71 6c 5f 74 65  %s", blob_sql_te
ce50: 78 74 28 26 73 71 6c 29 29 3b 0a 20 20 20 20 75  xt(&sql));.    u
ce60: 69 64 20 3d 20 64 62 5f 69 6e 74 28 30 2c 20 22  id = db_int(0, "
ce70: 53 45 4c 45 43 54 20 75 69 64 20 46 52 4f 4d 20  SELECT uid FROM 
ce80: 75 73 65 72 20 57 48 45 52 45 20 6c 6f 67 69 6e  user WHERE login
ce90: 3d 25 51 22 2c 20 7a 55 73 65 72 49 44 29 3b 0a  =%Q", zUserID);.
cea0: 20 20 20 20 6c 6f 67 69 6e 5f 73 65 74 5f 75 73      login_set_us
ceb0: 65 72 5f 63 6f 6f 6b 69 65 28 7a 55 73 65 72 49  er_cookie(zUserI
cec0: 44 2c 20 75 69 64 2c 20 4e 55 4c 4c 29 3b 0a 20  D, uid, NULL);. 
ced0: 20 20 20 69 66 28 20 64 6f 41 6c 65 72 74 73 20     if( doAlerts 
cee0: 29 7b 0a 20 20 20 20 20 20 2f 2a 20 41 6c 73 6f  ){.      /* Also
cef0: 20 6d 61 6b 65 20 74 68 65 20 6e 65 77 20 75 73   make the new us
cf00: 65 72 20 61 20 73 75 62 73 63 72 69 62 65 72 2e  er a subscriber.
cf10: 20 2a 2f 0a 20 20 20 20 20 20 42 6c 6f 62 20 68   */.      Blob h
cf20: 64 72 2c 20 62 6f 64 79 3b 0a 20 20 20 20 20 20  dr, body;.      
cf30: 41 6c 65 72 74 53 65 6e 64 65 72 20 2a 70 53 65  AlertSender *pSe
cf40: 6e 64 65 72 3b 0a 20 20 20 20 20 20 73 71 6c 69  nder;.      sqli
cf50: 74 65 33 5f 69 6e 74 36 34 20 69 64 3b 20 20 20  te3_int64 id;   
cf60: 2f 2a 20 4e 65 77 20 73 75 62 73 63 72 69 62 65  /* New subscribe
cf70: 72 20 49 64 20 2a 2f 0a 20 20 20 20 20 20 63 6f  r Id */.      co
cf80: 6e 73 74 20 63 68 61 72 20 2a 7a 43 6f 64 65 3b  nst char *zCode;
cf90: 20 20 2f 2a 20 4e 65 77 20 73 75 62 73 63 72 69    /* New subscri
cfa0: 62 65 72 20 63 6f 64 65 20 28 69 6e 20 68 65 78  ber code (in hex
cfb0: 29 20 2a 2f 0a 20 20 20 20 20 20 63 6f 6e 73 74  ) */.      const
cfc0: 20 63 68 61 72 20 2a 7a 47 6f 74 6f 20 3d 20 50   char *zGoto = P
cfd0: 28 22 67 22 29 3b 0a 20 20 20 20 20 20 69 6e 74  ("g");.      int
cfe0: 20 6e 73 75 62 20 3d 20 30 3b 0a 20 20 20 20 20   nsub = 0;.     
cff0: 20 63 68 61 72 20 73 73 75 62 5b 32 30 5d 3b 0a   char ssub[20];.
d000: 20 20 20 20 20 20 73 73 75 62 5b 6e 73 75 62 2b        ssub[nsub+
d010: 2b 5d 20 3d 20 27 61 27 3b 0a 20 20 20 20 20 20  +] = 'a';.      
d020: 69 66 28 20 67 2e 70 65 72 6d 2e 52 65 61 64 20  if( g.perm.Read 
d030: 29 20 20 20 20 73 73 75 62 5b 6e 73 75 62 2b 2b  )    ssub[nsub++
d040: 5d 20 3d 20 27 63 27 3b 0a 20 20 20 20 20 20 69  ] = 'c';.      i
d050: 66 28 20 67 2e 70 65 72 6d 2e 52 64 46 6f 72 75  f( g.perm.RdForu
d060: 6d 20 29 20 73 73 75 62 5b 6e 73 75 62 2b 2b 5d  m ) ssub[nsub++]
d070: 20 3d 20 27 66 27 3b 0a 20 20 20 20 20 20 69 66   = 'f';.      if
d080: 28 20 67 2e 70 65 72 6d 2e 52 64 54 6b 74 20 29  ( g.perm.RdTkt )
d090: 20 20 20 73 73 75 62 5b 6e 73 75 62 2b 2b 5d 20     ssub[nsub++] 
d0a0: 3d 20 27 74 27 3b 0a 20 20 20 20 20 20 69 66 28  = 't';.      if(
d0b0: 20 67 2e 70 65 72 6d 2e 52 64 57 69 6b 69 20 29   g.perm.RdWiki )
d0c0: 20 20 73 73 75 62 5b 6e 73 75 62 2b 2b 5d 20 3d    ssub[nsub++] =
d0d0: 20 27 77 27 3b 0a 20 20 20 20 20 20 73 73 75 62   'w';.      ssub
d0e0: 5b 6e 73 75 62 5d 20 3d 20 30 3b 0a 20 20 20 20  [nsub] = 0;.    
d0f0: 20 20 2f 2a 20 41 6c 73 6f 20 61 64 64 20 74 68    /* Also add th
d100: 65 20 75 73 65 72 20 74 6f 20 74 68 65 20 73 75  e user to the su
d110: 62 73 63 72 69 62 65 72 20 74 61 62 6c 65 2e 20  bscriber table. 
d120: 2a 2f 0a 20 20 20 20 20 20 64 62 5f 6d 75 6c 74  */.      db_mult
d130: 69 5f 65 78 65 63 28 0a 20 20 20 20 20 20 20 20  i_exec(.        
d140: 22 49 4e 53 45 52 54 20 49 4e 54 4f 20 73 75 62  "INSERT INTO sub
d150: 73 63 72 69 62 65 72 28 73 65 6d 61 69 6c 2c 73  scriber(semail,s
d160: 75 6e 61 6d 65 2c 22 0a 20 20 20 20 20 20 20 20  uname,".        
d170: 22 20 20 73 76 65 72 69 66 69 65 64 2c 73 64 6f  "  sverified,sdo
d180: 6e 6f 74 63 61 6c 6c 2c 73 64 69 67 65 73 74 2c  notcall,sdigest,
d190: 73 73 75 62 2c 73 63 74 69 6d 65 2c 6d 74 69 6d  ssub,sctime,mtim
d1a0: 65 2c 73 6d 69 70 29 22 0a 20 20 20 20 20 20 20  e,smip)".       
d1b0: 20 22 20 56 41 4c 55 45 53 28 25 51 2c 25 51 2c   " VALUES(%Q,%Q,
d1c0: 25 64 2c 30 2c 25 64 2c 25 51 2c 6e 6f 77 28 29  %d,0,%d,%Q,now()
d1d0: 2c 6e 6f 77 28 29 2c 25 51 29 22 0a 20 20 20 20  ,now(),%Q)".    
d1e0: 20 20 20 20 22 20 4f 4e 20 43 4f 4e 46 4c 49 43      " ON CONFLIC
d1f0: 54 28 73 65 6d 61 69 6c 29 20 44 4f 20 55 50 44  T(semail) DO UPD
d200: 41 54 45 22 0a 20 20 20 20 20 20 20 20 22 20 20  ATE".        "  
d210: 20 53 45 54 20 73 75 6e 61 6d 65 3d 65 78 63 6c   SET suname=excl
d220: 75 64 65 64 2e 73 75 6e 61 6d 65 22 2c 0a 20 20  uded.suname",.  
d230: 20 20 20 20 20 20 2f 2a 20 73 65 6d 61 69 6c 20        /* semail 
d240: 2a 2f 20 20 20 20 7a 45 41 64 64 72 2c 0a 20 20  */    zEAddr,.  
d250: 20 20 20 20 20 20 2f 2a 20 73 75 6e 61 6d 65 20        /* suname 
d260: 2a 2f 20 20 20 20 7a 55 73 65 72 49 44 2c 0a 20  */    zUserID,. 
d270: 20 20 20 20 20 20 20 2f 2a 20 73 76 65 72 69 66         /* sverif
d280: 69 65 64 20 2a 2f 20 30 2c 0a 20 20 20 20 20 20  ied */ 0,.      
d290: 20 20 2f 2a 20 73 64 69 67 65 73 74 20 2a 2f 20    /* sdigest */ 
d2a0: 20 20 30 2c 0a 20 20 20 20 20 20 20 20 2f 2a 20    0,.        /* 
d2b0: 73 73 75 62 20 2a 2f 20 20 20 20 20 20 73 73 75  ssub */      ssu
d2c0: 62 2c 0a 20 20 20 20 20 20 20 20 2f 2a 20 73 6d  b,.        /* sm
d2d0: 69 70 20 2a 2f 20 20 20 20 20 20 67 2e 7a 49 70  ip */      g.zIp
d2e0: 41 64 64 72 0a 20 20 20 20 20 20 29 3b 0a 20 20  Addr.      );.  
d2f0: 20 20 20 20 69 64 20 3d 20 64 62 5f 6c 61 73 74      id = db_last
d300: 5f 69 6e 73 65 72 74 5f 72 6f 77 69 64 28 29 3b  _insert_rowid();
d310: 0a 20 20 20 20 20 20 69 66 28 20 64 62 5f 65 78  .      if( db_ex
d320: 69 73 74 73 28 22 53 45 4c 45 43 54 20 31 20 46  ists("SELECT 1 F
d330: 52 4f 4d 20 73 75 62 73 63 72 69 62 65 72 20 57  ROM subscriber W
d340: 48 45 52 45 20 73 65 6d 61 69 6c 3d 25 51 22 0a  HERE semail=%Q".
d350: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
d360: 20 20 20 20 22 20 20 41 4e 44 20 73 76 65 72 69      "  AND sveri
d370: 66 69 65 64 22 2c 20 7a 45 41 64 64 72 29 20 29  fied", zEAddr) )
d380: 7b 0a 20 20 20 20 20 20 20 20 2f 2a 20 54 68 69  {.        /* Thi
d390: 73 20 74 68 65 20 63 61 73 65 20 77 68 65 72 65  s the case where
d3a0: 20 74 68 65 20 75 73 65 72 20 77 61 73 20 66 6f   the user was fo
d3b0: 72 6d 65 72 6c 79 20 61 20 76 65 72 69 66 69 65  rmerly a verifie
d3c0: 64 20 73 75 62 73 63 72 69 62 65 72 0a 20 20 20  d subscriber.   
d3d0: 20 20 20 20 20 2a 2a 20 61 6e 64 20 68 65 72 65       ** and here
d3e0: 20 74 68 65 79 20 68 61 76 65 20 61 6c 73 6f 20   they have also 
d3f0: 72 65 67 69 73 74 65 72 65 64 20 61 73 20 61 20  registered as a 
d400: 75 73 65 72 20 61 73 20 77 65 6c 6c 2e 20 20 49  user as well.  I
d410: 74 20 69 73 0a 20 20 20 20 20 20 20 20 2a 2a 20  t is.        ** 
d420: 6e 6f 74 20 6e 65 63 65 73 73 61 72 79 20 74 6f  not necessary to
d430: 20 72 65 70 65 61 74 20 74 68 65 20 76 65 72 66   repeat the verf
d440: 69 63 61 74 69 6f 6e 20 73 74 65 70 20 2a 2f 0a  ication step */.
d450: 20 20 20 20 20 20 20 20 72 65 64 69 72 65 63 74          redirect
d460: 5f 74 6f 5f 67 28 29 3b 0a 20 20 20 20 20 20 7d  _to_g();.      }
d470: 0a 20 20 20 20 20 20 7a 43 6f 64 65 20 3d 20 64  .      zCode = d
d480: 62 5f 74 65 78 74 28 30 2c 0a 20 20 20 20 20 20  b_text(0,.      
d490: 20 20 20 20 20 22 53 45 4c 45 43 54 20 68 65 78       "SELECT hex
d4a0: 28 73 75 62 73 63 72 69 62 65 72 43 6f 64 65 29  (subscriberCode)
d4b0: 20 46 52 4f 4d 20 73 75 62 73 63 72 69 62 65 72   FROM subscriber
d4c0: 20 57 48 45 52 45 20 73 75 62 73 63 72 69 62 65   WHERE subscribe
d4d0: 72 49 64 3d 25 6c 6c 64 22 2c 0a 20 20 20 20 20  rId=%lld",.     
d4e0: 20 20 20 20 20 20 69 64 29 3b 0a 20 20 20 20 20        id);.     
d4f0: 20 2f 2a 20 41 20 76 65 72 69 66 69 63 61 74 69   /* A verificati
d500: 6f 6e 20 65 6d 61 69 6c 20 2a 2f 0a 20 20 20 20  on email */.    
d510: 20 20 70 53 65 6e 64 65 72 20 3d 20 61 6c 65 72    pSender = aler
d520: 74 5f 73 65 6e 64 65 72 5f 6e 65 77 28 30 2c 30  t_sender_new(0,0
d530: 29 3b 0a 20 20 20 20 20 20 62 6c 6f 62 5f 69 6e  );.      blob_in
d540: 69 74 28 26 68 64 72 2c 30 2c 30 29 3b 0a 20 20  it(&hdr,0,0);.  
d550: 20 20 20 20 62 6c 6f 62 5f 69 6e 69 74 28 26 62      blob_init(&b
d560: 6f 64 79 2c 30 2c 30 29 3b 0a 20 20 20 20 20 20  ody,0,0);.      
d570: 62 6c 6f 62 5f 61 70 70 65 6e 64 66 28 26 68 64  blob_appendf(&hd
d580: 72 2c 20 22 54 6f 3a 20 3c 25 73 3e 5c 6e 22 2c  r, "To: <%s>\n",
d590: 20 7a 45 41 64 64 72 29 3b 0a 20 20 20 20 20 20   zEAddr);.      
d5a0: 62 6c 6f 62 5f 61 70 70 65 6e 64 66 28 26 68 64  blob_appendf(&hd
d5b0: 72 2c 20 22 53 75 62 6a 65 63 74 3a 20 53 75 62  r, "Subject: Sub
d5c0: 73 63 72 69 70 74 69 6f 6e 20 76 65 72 69 66 69  scription verifi
d5d0: 63 61 74 69 6f 6e 5c 6e 22 29 3b 0a 20 20 20 20  cation\n");.    
d5e0: 20 20 61 6c 65 72 74 5f 61 70 70 65 6e 64 5f 63    alert_append_c
d5f0: 6f 6e 66 69 72 6d 61 74 69 6f 6e 5f 6d 65 73 73  onfirmation_mess
d600: 61 67 65 28 26 62 6f 64 79 2c 20 7a 43 6f 64 65  age(&body, zCode
d610: 29 3b 0a 20 20 20 20 20 20 61 6c 65 72 74 5f 73  );.      alert_s
d620: 65 6e 64 28 70 53 65 6e 64 65 72 2c 20 26 68 64  end(pSender, &hd
d630: 72 2c 20 26 62 6f 64 79 2c 20 30 29 3b 0a 20 20  r, &body, 0);.  
d640: 20 20 20 20 73 74 79 6c 65 5f 68 65 61 64 65 72      style_header
d650: 28 22 45 6d 61 69 6c 20 56 65 72 69 66 69 63 61  ("Email Verifica
d660: 74 69 6f 6e 22 29 3b 0a 20 20 20 20 20 20 69 66  tion");.      if
d670: 28 20 70 53 65 6e 64 65 72 2d 3e 7a 45 72 72 20  ( pSender->zErr 
d680: 29 7b 0a 20 20 20 20 20 20 20 20 40 20 3c 68 31  ){.        @ <h1
d690: 3e 49 6e 74 65 72 6e 61 6c 20 45 72 72 6f 72 3c  >Internal Error<
d6a0: 2f 68 31 3e 0a 20 20 20 20 20 20 20 20 40 20 3c  /h1>.        @ <
d6b0: 70 3e 54 68 65 20 66 6f 6c 6c 6f 77 69 6e 67 20  p>The following 
d6c0: 69 6e 74 65 72 6e 61 6c 20 65 72 72 6f 72 20 77  internal error w
d6d0: 61 73 20 65 6e 63 6f 75 6e 74 65 72 65 64 20 77  as encountered w
d6e0: 68 69 6c 65 20 74 72 79 69 6e 67 0a 20 20 20 20  hile trying.    
d6f0: 20 20 20 20 40 20 74 6f 20 73 65 6e 64 20 74 68      @ to send th
d700: 65 20 63 6f 6e 66 69 72 6d 61 74 69 6f 6e 20 65  e confirmation e
d710: 6d 61 69 6c 3a 0a 20 20 20 20 20 20 20 20 40 20  mail:.        @ 
d720: 3c 62 6c 6f 63 6b 71 75 6f 74 65 3e 3c 70 72 65  <blockquote><pre
d730: 3e 0a 20 20 20 20 20 20 20 20 40 20 25 68 28 70  >.        @ %h(p
d740: 53 65 6e 64 65 72 2d 3e 7a 45 72 72 29 0a 20 20  Sender->zErr).  
d750: 20 20 20 20 20 20 40 20 3c 2f 70 72 65 3e 3c 2f        @ </pre></
d760: 62 6c 6f 63 6b 71 75 6f 74 65 3e 0a 20 20 20 20  blockquote>.    
d770: 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 20 20 20    }else{.       
d780: 20 40 20 3c 70 3e 41 6e 20 65 6d 61 69 6c 20 68   @ <p>An email h
d790: 61 73 20 62 65 65 6e 20 73 65 6e 74 20 74 6f 20  as been sent to 
d7a0: 22 25 68 28 7a 45 41 64 64 72 29 22 2e 20 54 68  "%h(zEAddr)". Th
d7b0: 61 74 20 65 6d 61 69 6c 20 63 6f 6e 74 61 69 6e  at email contain
d7c0: 73 20 61 0a 20 20 20 20 20 20 20 20 40 20 68 79  s a.        @ hy
d7d0: 70 65 72 6c 69 6e 6b 20 74 68 61 74 20 79 6f 75  perlink that you
d7e0: 20 6d 75 73 74 20 63 6c 69 63 6b 20 6f 6e 20 69   must click on i
d7f0: 6e 20 6f 72 64 65 72 20 74 6f 20 61 63 74 69 76  n order to activ
d800: 61 74 65 20 79 6f 75 72 0a 20 20 20 20 20 20 20  ate your.       
d810: 20 40 20 73 75 62 73 63 72 69 70 74 69 6f 6e 2e   @ subscription.
d820: 3c 2f 70 3e 0a 20 20 20 20 20 20 7d 0a 20 20 20  </p>.      }.   
d830: 20 20 20 61 6c 65 72 74 5f 73 65 6e 64 65 72 5f     alert_sender_
d840: 66 72 65 65 28 70 53 65 6e 64 65 72 29 3b 0a 20  free(pSender);. 
d850: 20 20 20 20 20 69 66 28 20 7a 47 6f 74 6f 20 29       if( zGoto )
d860: 7b 0a 20 20 20 20 20 20 20 20 40 20 3c 70 3e 3c  {.        @ <p><
d870: 61 20 68 72 65 66 3d 27 25 68 28 7a 47 6f 74 6f  a href='%h(zGoto
d880: 29 27 3e 43 6f 6e 74 69 6e 75 65 3c 2f 61 3e 0a  )'>Continue</a>.
d890: 20 20 20 20 20 20 7d 0a 20 20 20 20 20 20 73 74        }.      st
d8a0: 79 6c 65 5f 66 6f 6f 74 65 72 28 29 3b 0a 20 20  yle_footer();.  
d8b0: 20 20 20 20 72 65 74 75 72 6e 3b 0a 20 20 20 20      return;.    
d8c0: 7d 0a 20 20 20 20 72 65 64 69 72 65 63 74 5f 74  }.    redirect_t
d8d0: 6f 5f 67 28 29 3b 0a 20 20 7d 0a 0a 20 20 2f 2a  o_g();.  }..  /*
d8e0: 20 50 72 65 70 61 72 65 20 74 68 65 20 63 61 70   Prepare the cap
d8f0: 74 63 68 61 2e 20 2a 2f 0a 20 20 75 53 65 65 64  tcha. */.  uSeed
d900: 20 3d 20 63 61 70 74 63 68 61 5f 73 65 65 64 28   = captcha_seed(
d910: 29 3b 0a 20 20 7a 44 65 63 6f 64 65 64 20 3d 20  );.  zDecoded = 
d920: 63 61 70 74 63 68 61 5f 64 65 63 6f 64 65 28 75  captcha_decode(u
d930: 53 65 65 64 29 3b 0a 20 20 7a 43 61 70 74 63 68  Seed);.  zCaptch
d940: 61 20 3d 20 63 61 70 74 63 68 61 5f 72 65 6e 64  a = captcha_rend
d950: 65 72 28 7a 44 65 63 6f 64 65 64 29 3b 0a 0a 20  er(zDecoded);.. 
d960: 20 73 74 79 6c 65 5f 68 65 61 64 65 72 28 22 52   style_header("R
d970: 65 67 69 73 74 65 72 22 29 3b 0a 20 20 2f 2a 20  egister");.  /* 
d980: 50 72 69 6e 74 20 6f 75 74 20 74 68 65 20 72 65  Print out the re
d990: 67 69 73 74 72 61 74 69 6f 6e 20 66 6f 72 6d 2e  gistration form.
d9a0: 20 2a 2f 0a 20 20 66 6f 72 6d 5f 62 65 67 69 6e   */.  form_begin
d9b0: 28 30 2c 20 22 25 52 2f 72 65 67 69 73 74 65 72  (0, "%R/register
d9c0: 22 29 3b 0a 20 20 69 66 28 20 50 28 22 67 22 29  ");.  if( P("g")
d9d0: 20 29 7b 0a 20 20 20 20 40 20 3c 69 6e 70 75 74   ){.    @ <input
d9e0: 20 74 79 70 65 3d 22 68 69 64 64 65 6e 22 20 6e   type="hidden" n
d9f0: 61 6d 65 3d 22 67 22 20 76 61 6c 75 65 3d 22 25  ame="g" value="%
da00: 68 28 50 28 22 67 22 29 29 22 20 2f 3e 0a 20 20  h(P("g"))" />.  
da10: 7d 0a 20 20 40 20 3c 70 3e 3c 69 6e 70 75 74 20  }.  @ <p><input 
da20: 74 79 70 65 3d 22 68 69 64 64 65 6e 22 20 6e 61  type="hidden" na
da30: 6d 65 3d 22 63 61 70 74 63 68 61 73 65 65 64 22  me="captchaseed"
da40: 20 76 61 6c 75 65 3d 22 25 75 28 75 53 65 65 64   value="%u(uSeed
da50: 29 22 20 2f 3e 0a 20 20 40 20 3c 74 61 62 6c 65  )" />.  @ <table
da60: 20 63 6c 61 73 73 3d 22 6c 6f 67 69 6e 5f 6f 75   class="login_ou
da70: 74 22 3e 0a 20 20 40 20 3c 74 72 3e 0a 20 20 40  t">.  @ <tr>.  @
da80: 20 20 20 3c 74 64 20 63 6c 61 73 73 3d 22 66 6f     <td class="fo
da90: 72 6d 5f 6c 61 62 65 6c 22 20 61 6c 69 67 6e 3d  rm_label" align=
daa0: 22 72 69 67 68 74 22 3e 55 73 65 72 20 49 44 3a  "right">User ID:
dab0: 3c 2f 74 64 3e 0a 20 20 40 20 20 20 3c 74 64 3e  </td>.  @   <td>
dac0: 3c 69 6e 70 75 74 20 74 79 70 65 3d 22 74 65 78  <input type="tex
dad0: 74 22 20 6e 61 6d 65 3d 22 75 22 20 76 61 6c 75  t" name="u" valu
dae0: 65 3d 22 25 68 28 7a 55 73 65 72 49 44 29 22 20  e="%h(zUserID)" 
daf0: 73 69 7a 65 3d 22 33 30 22 3e 3c 2f 74 64 3e 0a  size="30"></td>.
db00: 20 20 40 0a 20 20 69 66 28 20 69 45 72 72 4c 69    @.  if( iErrLi
db10: 6e 65 3d 3d 31 20 29 7b 0a 20 20 20 20 40 20 3c  ne==1 ){.    @ <
db20: 74 72 3e 3c 74 64 3e 3c 74 64 3e 3c 73 70 61 6e  tr><td><td><span
db30: 20 63 6c 61 73 73 3d 27 6c 6f 67 69 6e 45 72 72   class='loginErr
db40: 6f 72 27 3e 26 75 61 72 72 3b 20 25 68 28 7a 45  or'>&uarr; %h(zE
db50: 72 72 29 3c 2f 73 70 61 6e 3e 3c 2f 74 64 3e 3c  rr)</span></td><
db60: 2f 74 72 3e 0a 20 20 7d 0a 20 20 40 20 3c 74 72  /tr>.  }.  @ <tr
db70: 3e 0a 20 20 40 20 20 20 3c 74 64 20 63 6c 61 73  >.  @   <td clas
db80: 73 3d 22 66 6f 72 6d 5f 6c 61 62 65 6c 22 20 61  s="form_label" a
db90: 6c 69 67 6e 3d 22 72 69 67 68 74 22 3e 44 69 73  lign="right">Dis
dba0: 70 6c 61 79 20 4e 61 6d 65 3a 3c 2f 74 64 3e 0a  play Name:</td>.
dbb0: 20 20 40 20 20 20 3c 74 64 3e 3c 69 6e 70 75 74    @   <td><input
dbc0: 20 74 79 70 65 3d 22 74 65 78 74 22 20 6e 61 6d   type="text" nam
dbd0: 65 3d 22 64 6e 22 20 76 61 6c 75 65 3d 22 25 68  e="dn" value="%h
dbe0: 28 7a 44 4e 61 6d 65 29 22 20 73 69 7a 65 3d 22  (zDName)" size="
dbf0: 33 30 22 3e 3c 2f 74 64 3e 0a 20 20 40 20 3c 2f  30"></td>.  @ </
dc00: 74 72 3e 0a 20 20 69 66 28 20 69 45 72 72 4c 69  tr>.  if( iErrLi
dc10: 6e 65 3d 3d 32 20 29 7b 0a 20 20 20 20 40 20 3c  ne==2 ){.    @ <
dc20: 74 72 3e 3c 74 64 3e 3c 74 64 3e 3c 73 70 61 6e  tr><td><td><span
dc30: 20 63 6c 61 73 73 3d 27 6c 6f 67 69 6e 45 72 72   class='loginErr
dc40: 6f 72 27 3e 26 75 61 72 72 3b 20 25 68 28 7a 45  or'>&uarr; %h(zE
dc50: 72 72 29 3c 2f 73 70 61 6e 3e 3c 2f 74 64 3e 3c  rr)</span></td><
dc60: 2f 74 72 3e 0a 20 20 7d 0a 20 20 40 20 3c 2f 74  /tr>.  }.  @ </t
dc70: 72 3e 0a 20 20 40 20 3c 74 72 3e 0a 20 20 40 20  r>.  @ <tr>.  @ 
dc80: 20 20 3c 74 64 20 63 6c 61 73 73 3d 22 66 6f 72    <td class="for
dc90: 6d 5f 6c 61 62 65 6c 22 20 61 6c 69 67 6e 3d 22  m_label" align="
dca0: 72 69 67 68 74 22 3e 45 6d 61 69 6c 20 41 64 64  right">Email Add
dcb0: 72 65 73 73 3a 3c 2f 74 64 3e 0a 20 20 40 20 20  ress:</td>.  @  
dcc0: 20 3c 74 64 3e 3c 69 6e 70 75 74 20 74 79 70 65   <td><input type
dcd0: 3d 22 74 65 78 74 22 20 6e 61 6d 65 3d 22 65 61  ="text" name="ea
dce0: 22 20 76 61 6c 75 65 3d 22 25 68 28 7a 45 41 64  " value="%h(zEAd
dcf0: 64 72 29 22 20 73 69 7a 65 3d 22 33 30 22 3e 3c  dr)" size="30"><
dd00: 2f 74 64 3e 0a 20 20 40 20 3c 2f 74 72 3e 0a 20  /td>.  @ </tr>. 
dd10: 20 69 66 28 20 69 45 72 72 4c 69 6e 65 3d 3d 33   if( iErrLine==3
dd20: 20 29 7b 0a 20 20 20 20 40 20 3c 74 72 3e 3c 74   ){.    @ <tr><t
dd30: 64 3e 3c 74 64 3e 3c 73 70 61 6e 20 63 6c 61 73  d><td><span clas
dd40: 73 3d 27 6c 6f 67 69 6e 45 72 72 6f 72 27 3e 26  s='loginError'>&
dd50: 75 61 72 72 3b 20 25 68 28 7a 45 72 72 29 3c 2f  uarr; %h(zErr)</
dd60: 73 70 61 6e 3e 3c 2f 74 64 3e 3c 2f 74 72 3e 0a  span></td></tr>.
dd70: 20 20 7d 0a 20 20 69 66 28 20 63 61 6e 44 6f 41    }.  if( canDoA
dd80: 6c 65 72 74 73 20 29 7b 0a 20 20 20 20 69 6e 74  lerts ){.    int
dd90: 20 61 20 3d 20 61 74 6f 69 28 50 44 28 22 61 6c   a = atoi(PD("al
dda0: 65 72 74 73 22 2c 22 31 22 29 29 3b 0a 20 20 20  erts","1"));.   
ddb0: 20 40 20 3c 74 72 3e 0a 20 20 20 20 40 20 20 20   @ <tr>.    @   
ddc0: 3c 74 64 20 63 6c 61 73 73 3d 22 66 6f 72 6d 5f  <td class="form_
ddd0: 6c 61 62 65 6c 22 20 61 6c 69 67 6e 3d 22 72 69  label" align="ri
dde0: 67 68 74 22 3e 45 6d 61 69 6c 26 6e 62 73 70 3b  ght">Email&nbsp;
ddf0: 41 6c 65 72 74 73 3f 3c 2f 74 64 3e 0a 20 20 20  Alerts?</td>.   
de00: 20 40 20 20 20 3c 74 64 3e 3c 73 65 6c 65 63 74   @   <td><select
de10: 20 73 69 7a 65 3d 27 31 27 20 6e 61 6d 65 3d 27   size='1' name='
de20: 61 6c 65 72 74 73 27 3e 0a 20 20 20 20 40 20 20  alerts'>.    @  
de30: 20 20 20 20 20 3c 6f 70 74 69 6f 6e 20 76 61 6c       <option val
de40: 75 65 3d 22 31 22 20 25 73 28 61 3f 22 73 65 6c  ue="1" %s(a?"sel
de50: 65 63 74 65 64 22 3a 22 22 29 3e 59 65 73 3c 2f  ected":"")>Yes</
de60: 6f 70 74 69 6f 6e 3e 0a 20 20 20 20 40 20 20 20  option>.    @   
de70: 20 20 20 20 3c 6f 70 74 69 6f 6e 20 76 61 6c 75      <option valu
de80: 65 3d 22 30 22 20 25 73 28 21 61 3f 22 73 65 6c  e="0" %s(!a?"sel
de90: 65 63 74 65 64 22 3a 22 22 29 3e 4e 6f 3c 2f 6f  ected":"")>No</o
dea0: 70 74 69 6f 6e 3e 0a 20 20 20 20 40 20 20 20 3c  ption>.    @   <
deb0: 2f 73 65 6c 65 63 74 3e 3c 2f 74 64 3e 3c 2f 74  /select></td></t
dec0: 72 3e 0a 20 20 7d 0a 20 20 40 20 3c 74 72 3e 0a  r>.  }.  @ <tr>.
ded0: 20 20 40 20 20 20 3c 74 64 20 63 6c 61 73 73 3d    @   <td class=
dee0: 22 66 6f 72 6d 5f 6c 61 62 65 6c 22 20 61 6c 69  "form_label" ali
def0: 67 6e 3d 22 72 69 67 68 74 22 3e 50 61 73 73 77  gn="right">Passw
df00: 6f 72 64 3a 3c 2f 74 64 3e 0a 20 20 40 20 20 20  ord:</td>.  @   
df10: 3c 74 64 3e 3c 69 6e 70 75 74 20 74 79 70 65 3d  <td><input type=
df20: 22 70 61 73 73 77 6f 72 64 22 20 6e 61 6d 65 3d  "password" name=
df30: 22 70 22 20 76 61 6c 75 65 3d 22 25 68 28 7a 50  "p" value="%h(zP
df40: 61 73 73 77 64 29 22 20 73 69 7a 65 3d 22 33 30  asswd)" size="30
df50: 22 3e 3c 2f 74 64 3e 0a 20 20 40 20 3c 74 72 3e  "></td>.  @ <tr>
df60: 0a 20 20 69 66 28 20 69 45 72 72 4c 69 6e 65 3d  .  if( iErrLine=
df70: 3d 34 20 29 7b 0a 20 20 20 20 40 20 3c 74 72 3e  =4 ){.    @ <tr>
df80: 3c 74 64 3e 3c 74 64 3e 3c 73 70 61 6e 20 63 6c  <td><td><span cl
df90: 61 73 73 3d 27 6c 6f 67 69 6e 45 72 72 6f 72 27  ass='loginError'
dfa0: 3e 26 75 61 72 72 3b 20 25 68 28 7a 45 72 72 29  >&uarr; %h(zErr)
dfb0: 3c 2f 73 70 61 6e 3e 3c 2f 74 64 3e 3c 2f 74 72  </span></td></tr
dfc0: 3e 0a 20 20 7d 0a 20 20 40 20 3c 74 72 3e 0a 20  >.  }.  @ <tr>. 
dfd0: 20 40 20 20 20 3c 74 64 20 63 6c 61 73 73 3d 22   @   <td class="
dfe0: 66 6f 72 6d 5f 6c 61 62 65 6c 22 20 61 6c 69 67  form_label" alig
dff0: 6e 3d 22 72 69 67 68 74 22 3e 43 6f 6e 66 69 72  n="right">Confir
e000: 6d 3a 3c 2f 74 64 3e 0a 20 20 40 20 20 20 3c 74  m:</td>.  @   <t
e010: 64 3e 3c 69 6e 70 75 74 20 74 79 70 65 3d 22 70  d><input type="p
e020: 61 73 73 77 6f 72 64 22 20 6e 61 6d 65 3d 22 63  assword" name="c
e030: 70 22 20 76 61 6c 75 65 3d 22 25 68 28 7a 43 6f  p" value="%h(zCo
e040: 6e 66 69 72 6d 29 22 20 73 69 7a 65 3d 22 33 30  nfirm)" size="30
e050: 22 3e 3c 2f 74 64 3e 0a 20 20 40 20 3c 2f 74 72  "></td>.  @ </tr
e060: 3e 0a 20 20 69 66 28 20 69 45 72 72 4c 69 6e 65  >.  if( iErrLine
e070: 3d 3d 35 20 29 7b 0a 20 20 20 20 40 20 3c 74 72  ==5 ){.    @ <tr
e080: 3e 3c 74 64 3e 3c 74 64 3e 3c 73 70 61 6e 20 63  ><td><td><span c
e090: 6c 61 73 73 3d 27 6c 6f 67 69 6e 45 72 72 6f 72  lass='loginError
e0a0: 27 3e 26 75 61 72 72 3b 20 25 68 28 7a 45 72 72  '>&uarr; %h(zErr
e0b0: 29 3c 2f 73 70 61 6e 3e 3c 2f 74 64 3e 3c 2f 74  )</span></td></t
e0c0: 72 3e 0a 20 20 7d 0a 20 20 40 20 3c 74 72 3e 0a  r>.  }.  @ <tr>.
e0d0: 20 20 40 20 20 20 3c 74 64 20 63 6c 61 73 73 3d    @   <td class=
e0e0: 22 66 6f 72 6d 5f 6c 61 62 65 6c 22 20 61 6c 69  "form_label" ali
e0f0: 67 6e 3d 22 72 69 67 68 74 22 3e 43 61 70 74 63  gn="right">Captc
e100: 68 61 3a 3c 2f 74 64 3e 0a 20 20 40 20 20 20 3c  ha:</td>.  @   <
e110: 74 64 3e 3c 69 6e 70 75 74 20 74 79 70 65 3d 22  td><input type="
e120: 74 65 78 74 22 20 6e 61 6d 65 3d 22 63 61 70 74  text" name="capt
e130: 63 68 61 22 20 76 61 6c 75 65 3d 22 22 20 73 69  cha" value="" si
e140: 7a 65 3d 22 33 30 22 3e 3c 2f 74 64 3e 0a 20 20  ze="30"></td>.  
e150: 40 20 3c 2f 74 72 3e 0a 20 20 69 66 28 20 69 45  @ </tr>.  if( iE
e160: 72 72 4c 69 6e 65 3d 3d 36 20 29 7b 0a 20 20 20  rrLine==6 ){.   
e170: 20 40 20 3c 74 72 3e 3c 74 64 3e 3c 74 64 3e 3c   @ <tr><td><td><
e180: 73 70 61 6e 20 63 6c 61 73 73 3d 27 6c 6f 67 69  span class='logi
e190: 6e 45 72 72 6f 72 27 3e 26 75 61 72 72 3b 20 25  nError'>&uarr; %
e1a0: 68 28 7a 45 72 72 29 3c 2f 73 70 61 6e 3e 3c 2f  h(zErr)</span></
e1b0: 74 64 3e 3c 2f 74 72 3e 0a 20 20 7d 0a 20 20 40  td></tr>.  }.  @
e1c0: 20 3c 74 72 3e 3c 74 64 3e 3c 2f 74 64 3e 0a 20   <tr><td></td>. 
e1d0: 20 40 20 3c 74 64 3e 3c 69 6e 70 75 74 20 74 79   @ <td><input ty
e1e0: 70 65 3d 22 73 75 62 6d 69 74 22 20 6e 61 6d 65  pe="submit" name
e1f0: 3d 22 6e 65 77 22 20 76 61 6c 75 65 3d 22 52 65  ="new" value="Re
e200: 67 69 73 74 65 72 22 20 2f 3e 3c 2f 74 64 3e 3c  gister" /></td><
e210: 2f 74 72 3e 0a 20 20 40 20 3c 2f 74 61 62 6c 65  /tr>.  @ </table
e220: 3e 0a 20 20 40 20 3c 64 69 76 20 63 6c 61 73 73  >.  @ <div class
e230: 3d 22 63 61 70 74 63 68 61 22 3e 3c 74 61 62 6c  ="captcha"><tabl
e240: 65 20 63 6c 61 73 73 3d 22 63 61 70 74 63 68 61  e class="captcha
e250: 22 3e 3c 74 72 3e 3c 74 64 3e 3c 70 72 65 20 63  "><tr><td><pre c
e260: 6c 61 73 73 3d 22 63 61 70 74 63 68 61 22 3e 0a  lass="captcha">.
e270: 20 20 40 20 25 68 28 7a 43 61 70 74 63 68 61 29    @ %h(zCaptcha)
e280: 0a 20 20 40 20 3c 2f 70 72 65 3e 0a 20 20 40 20  .  @ </pre>.  @ 
e290: 45 6e 74 65 72 20 74 68 69 73 20 38 2d 6c 65 74  Enter this 8-let
e2a0: 74 65 72 20 63 6f 64 65 20 69 6e 20 74 68 65 20  ter code in the 
e2b0: 22 43 61 70 74 63 68 61 22 20 62 6f 78 20 61 62  "Captcha" box ab
e2c0: 6f 76 65 2e 0a 20 20 40 20 3c 2f 74 64 3e 3c 2f  ove..  @ </td></
e2d0: 74 72 3e 3c 2f 74 61 62 6c 65 3e 3c 2f 64 69 76  tr></table></div
e2e0: 3e 0a 20 20 40 20 3c 2f 66 6f 72 6d 3e 0a 20 20  >.  @ </form>.  
e2f0: 73 74 79 6c 65 5f 66 6f 6f 74 65 72 28 29 3b 0a  style_footer();.
e300: 0a 20 20 66 72 65 65 28 7a 43 61 70 74 63 68 61  .  free(zCaptcha
e310: 29 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a 20 52 75 6e 20  );.}../*.** Run 
e320: 53 51 4c 20 6f 6e 20 74 68 65 20 72 65 70 6f 73  SQL on the repos
e330: 69 74 6f 72 79 20 64 61 74 61 62 61 73 65 20 66  itory database f
e340: 6f 72 20 65 76 65 72 79 20 72 65 70 6f 73 69 74  or every reposit
e350: 6f 72 79 20 69 6e 20 6f 75 72 0a 2a 2a 20 6c 6f  ory in our.** lo
e360: 67 69 6e 20 67 72 6f 75 70 2e 20 20 54 68 65 20  gin group.  The 
e370: 53 51 4c 20 69 73 20 72 75 6e 20 69 6e 20 61 20  SQL is run in a 
e380: 73 65 70 61 72 61 74 65 20 64 61 74 61 62 61 73  separate databas
e390: 65 20 63 6f 6e 6e 65 63 74 69 6f 6e 2e 0a 2a 2a  e connection..**
e3a0: 0a 2a 2a 20 41 6e 79 20 6d 65 6d 62 65 72 73 20  .** Any members 
e3b0: 6f 66 20 74 68 65 20 6c 6f 67 69 6e 20 67 72 6f  of the login gro
e3c0: 75 70 20 77 68 6f 73 65 20 72 65 70 6f 73 69 74  up whose reposit
e3d0: 6f 72 79 20 64 61 74 61 62 61 73 65 20 66 69 6c  ory database fil
e3e0: 65 0a 2a 2a 20 63 61 6e 6e 6f 74 20 62 65 20 66  e.** cannot be f
e3f0: 6f 75 6e 64 20 69 73 20 73 69 6c 65 6e 74 6c 79  ound is silently
e400: 20 72 65 6d 6f 76 65 64 20 66 72 6f 6d 20 74 68   removed from th
e410: 65 20 67 72 6f 75 70 2e 0a 2a 2a 0a 2a 2a 20 45  e group..**.** E
e420: 72 72 6f 72 20 6d 65 73 73 61 67 65 73 20 61 63  rror messages ac
e430: 63 75 6d 75 6c 61 74 65 20 61 6e 64 20 61 72 65  cumulate and are
e440: 20 72 65 74 75 72 6e 65 64 20 69 6e 20 2a 70 7a   returned in *pz
e450: 45 72 72 6f 72 4d 73 67 2e 20 20 54 68 65 0a 2a  ErrorMsg.  The.*
e460: 2a 20 6d 65 6d 6f 72 79 20 75 73 65 64 20 74 6f  * memory used to
e470: 20 68 6f 6c 64 20 74 68 65 73 65 20 6d 65 73 73   hold these mess
e480: 61 67 65 73 20 73 68 6f 75 6c 64 20 62 65 20 66  ages should be f
e490: 72 65 65 64 20 75 73 69 6e 67 0a 2a 2a 20 66 6f  reed using.** fo
e4a0: 73 73 69 6c 5f 66 72 65 65 28 29 20 69 66 20 6f  ssil_free() if o
e4b0: 6e 65 20 64 65 73 69 72 65 64 20 74 6f 20 61 76  ne desired to av
e4c0: 6f 69 64 20 61 20 6d 65 6d 6f 72 79 20 6c 65 61  oid a memory lea
e4d0: 6b 2e 20 20 54 68 65 0a 2a 2a 20 7a 50 72 65 66  k.  The.** zPref
e4e0: 69 78 20 61 6e 64 20 7a 53 75 66 66 69 78 20 73  ix and zSuffix s
e4f0: 74 72 69 6e 67 73 20 73 75 72 72 6f 75 6e 64 20  trings surround 
e500: 65 61 63 68 20 65 72 72 6f 72 20 6d 65 73 73 61  each error messa
e510: 67 65 2e 0a 2a 2a 0a 2a 2a 20 52 65 74 75 72 6e  ge..**.** Return
e520: 20 74 68 65 20 6e 75 6d 62 65 72 20 6f 66 20 65   the number of e
e530: 72 72 6f 72 73 2e 0a 2a 2f 0a 69 6e 74 20 6c 6f  rrors..*/.int lo
e540: 67 69 6e 5f 67 72 6f 75 70 5f 73 71 6c 28 0a 20  gin_group_sql(. 
e550: 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 53 71   const char *zSq
e560: 6c 2c 20 20 20 20 20 20 20 20 2f 2a 20 54 68 65  l,        /* The
e570: 20 53 51 4c 20 74 6f 20 72 75 6e 20 2a 2f 0a 20   SQL to run */. 
e580: 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 50 72   const char *zPr
e590: 65 66 69 78 2c 20 20 20 20 20 2f 2a 20 50 72 65  efix,     /* Pre
e5a0: 66 69 78 20 74 6f 20 65 61 63 68 20 65 72 72 6f  fix to each erro
e5b0: 72 20 6d 65 73 73 61 67 65 20 2a 2f 0a 20 20 63  r message */.  c
e5c0: 6f 6e 73 74 20 63 68 61 72 20 2a 7a 53 75 66 66  onst char *zSuff
e5d0: 69 78 2c 20 20 20 20 20 2f 2a 20 53 75 66 66 69  ix,     /* Suffi
e5e0: 78 20 74 6f 20 65 61 63 68 20 65 72 72 6f 72 20  x to each error 
e5f0: 6d 65 73 73 61 67 65 20 2a 2f 0a 20 20 63 68 61  message */.  cha
e600: 72 20 2a 2a 70 7a 45 72 72 6f 72 4d 73 67 20 20  r **pzErrorMsg  
e610: 20 20 20 20 20 20 2f 2a 20 57 72 69 74 65 20 65        /* Write e
e620: 72 72 6f 72 20 6d 65 73 73 61 67 65 20 68 65 72  rror message her
e630: 65 2c 20 69 66 20 6e 6f 74 20 4e 55 4c 4c 20 2a  e, if not NULL *
e640: 2f 0a 29 7b 0a 20 20 73 71 6c 69 74 65 33 20 2a  /.){.  sqlite3 *
e650: 70 50 65 65 72 3b 20 20 20 20 20 20 20 20 20 20  pPeer;          
e660: 2f 2a 20 43 6f 6e 6e 65 63 74 69 6f 6e 20 74 6f  /* Connection to
e670: 20 61 6e 6f 74 68 65 72 20 64 61 74 61 62 61 73   another databas
e680: 65 20 2a 2f 0a 20 20 69 6e 74 20 6e 45 72 72 20  e */.  int nErr 
e690: 3d 20 30 3b 20 20 20 20 20 20 20 20 20 20 20 20  = 0;            
e6a0: 2f 2a 20 4e 75 6d 62 65 72 20 6f 66 20 65 72 72  /* Number of err
e6b0: 6f 72 73 20 73 65 65 6e 20 73 6f 20 66 61 72 20  ors seen so far 
e6c0: 2a 2f 0a 20 20 69 6e 74 20 72 63 3b 20 20 20 20  */.  int rc;    
e6d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
e6e0: 20 52 65 73 75 6c 74 20 63 6f 64 65 20 66 72 6f   Result code fro
e6f0: 6d 20 73 75 62 72 6f 75 74 69 6e 65 20 63 61 6c  m subroutine cal
e700: 6c 73 20 2a 2f 0a 20 20 63 68 61 72 20 2a 7a 45  ls */.  char *zE
e710: 72 72 3b 20 20 20 20 20 20 20 20 20 20 20 20 20  rr;             
e720: 20 2f 2a 20 53 51 4c 69 74 65 20 65 72 72 6f 72   /* SQLite error
e730: 20 74 65 78 74 20 2a 2f 0a 20 20 63 68 61 72 20   text */.  char 
e740: 2a 7a 53 65 6c 66 43 6f 64 65 3b 20 20 20 20 20  *zSelfCode;     
e750: 20 20 20 20 2f 2a 20 50 72 6f 6a 65 63 74 20 63      /* Project c
e760: 6f 64 65 20 66 6f 72 20 6f 75 72 73 65 6c 66 20  ode for ourself 
e770: 2a 2f 0a 20 20 42 6c 6f 62 20 65 72 72 3b 20 20  */.  Blob err;  
e780: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a                /*
e790: 20 41 63 63 75 6d 75 6c 61 74 65 20 65 72 72 6f   Accumulate erro
e7a0: 72 73 20 68 65 72 65 20 2a 2f 0a 20 20 53 74 6d  rs here */.  Stm
e7b0: 74 20 71 3b 20 20 20 20 20 20 20 20 20 20 20 20  t q;            
e7c0: 20 20 20 20 20 20 2f 2a 20 51 75 65 72 79 20 6f        /* Query o
e7d0: 66 20 61 6c 6c 20 70 65 65 72 2d 2a 20 65 6e 74  f all peer-* ent
e7e0: 72 69 65 73 20 69 6e 20 43 4f 4e 46 49 47 20 2a  ries in CONFIG *
e7f0: 2f 0a 0a 20 20 69 66 28 20 7a 50 72 65 66 69 78  /..  if( zPrefix
e800: 3d 3d 30 20 29 20 7a 50 72 65 66 69 78 20 3d 20  ==0 ) zPrefix = 
e810: 22 22 3b 0a 20 20 69 66 28 20 7a 53 75 66 66 69  "";.  if( zSuffi
e820: 78 3d 3d 30 20 29 20 7a 53 75 66 66 69 78 20 3d  x==0 ) zSuffix =
e830: 20 22 22 3b 0a 20 20 69 66 28 20 70 7a 45 72 72   "";.  if( pzErr
e840: 6f 72 4d 73 67 20 29 20 2a 70 7a 45 72 72 6f 72  orMsg ) *pzError
e850: 4d 73 67 20 3d 20 30 3b 0a 20 20 7a 53 65 6c 66  Msg = 0;.  zSelf
e860: 43 6f 64 65 20 3d 20 61 62 62 72 65 76 69 61 74  Code = abbreviat
e870: 65 64 5f 70 72 6f 6a 65 63 74 5f 63 6f 64 65 28  ed_project_code(
e880: 64 62 5f 67 65 74 28 22 70 72 6f 6a 65 63 74 2d  db_get("project-
e890: 63 6f 64 65 22 2c 20 22 78 22 29 29 3b 0a 20 20  code", "x"));.  
e8a0: 62 6c 6f 62 5f 7a 65 72 6f 28 26 65 72 72 29 3b  blob_zero(&err);
e8b0: 0a 20 20 64 62 5f 70 72 65 70 61 72 65 28 26 71  .  db_prepare(&q
e8c0: 2c 0a 20 20 20 20 22 53 45 4c 45 43 54 20 6e 61  ,.    "SELECT na
e8d0: 6d 65 2c 20 76 61 6c 75 65 20 46 52 4f 4d 20 63  me, value FROM c
e8e0: 6f 6e 66 69 67 22 0a 20 20 20 20 22 20 57 48 45  onfig".    " WHE
e8f0: 52 45 20 6e 61 6d 65 20 47 4c 4f 42 20 27 70 65  RE name GLOB 'pe
e900: 65 72 2d 72 65 70 6f 2d 2a 27 22 0a 20 20 20 20  er-repo-*'".    
e910: 22 20 20 20 41 4e 44 20 6e 61 6d 65 20 3c 3e 20  "   AND name <> 
e920: 27 70 65 65 72 2d 72 65 70 6f 2d 25 71 27 22 0a  'peer-repo-%q'".
e930: 20 20 20 20 22 20 4f 52 44 45 52 20 42 59 20 2b      " ORDER BY +
e940: 76 61 6c 75 65 22 2c 0a 20 20 20 20 7a 53 65 6c  value",.    zSel
e950: 66 43 6f 64 65 0a 20 20 29 3b 0a 20 20 77 68 69  fCode.  );.  whi
e960: 6c 65 28 20 64 62 5f 73 74 65 70 28 26 71 29 3d  le( db_step(&q)=
e970: 3d 53 51 4c 49 54 45 5f 52 4f 57 20 29 7b 0a 20  =SQLITE_ROW ){. 
e980: 20 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a     const char *z
e990: 52 65 70 6f 4e 61 6d 65 20 3d 20 64 62 5f 63 6f  RepoName = db_co
e9a0: 6c 75 6d 6e 5f 74 65 78 74 28 26 71 2c 20 31 29  lumn_text(&q, 1)
e9b0: 3b 0a 20 20 20 20 69 66 28 20 66 69 6c 65 5f 73  ;.    if( file_s
e9c0: 69 7a 65 28 7a 52 65 70 6f 4e 61 6d 65 2c 20 45  ize(zRepoName, E
e9d0: 78 74 46 49 4c 45 29 3c 30 20 29 7b 0a 20 20 20  xtFILE)<0 ){.   
e9e0: 20 20 20 2f 2a 20 53 69 6c 65 6e 74 6c 79 20 72     /* Silently r
e9f0: 65 6d 6f 76 65 20 6e 6f 6e 2d 65 78 69 73 74 65  emove non-existe
ea00: 6e 74 20 72 65 70 6f 73 69 74 6f 72 69 65 73 20  nt repositories 
ea10: 66 72 6f 6d 20 74 68 65 20 6c 6f 67 69 6e 20 67  from the login g
ea20: 72 6f 75 70 2e 20 2a 2f 0a 20 20 20 20 20 20 63  roup. */.      c
ea30: 6f 6e 73 74 20 63 68 61 72 20 2a 7a 4c 61 62 65  onst char *zLabe
ea40: 6c 20 3d 20 64 62 5f 63 6f 6c 75 6d 6e 5f 74 65  l = db_column_te
ea50: 78 74 28 26 71 2c 20 30 29 3b 0a 20 20 20 20 20  xt(&q, 0);.     
ea60: 20 64 62 5f 6d 75 6c 74 69 5f 65 78 65 63 28 0a   db_multi_exec(.
ea70: 20 20 20 20 20 20 20 20 20 22 44 45 4c 45 54 45           "DELETE
ea80: 20 46 52 4f 4d 20 63 6f 6e 66 69 67 20 57 48 45   FROM config WHE
ea90: 52 45 20 6e 61 6d 65 20 47 4c 4f 42 20 27 70 65  RE name GLOB 'pe
eaa0: 65 72 2d 2a 2d 25 71 27 22 2c 0a 20 20 20 20 20  er-*-%q'",.     
eab0: 20 20 20 20 26 7a 4c 61 62 65 6c 5b 31 30 5d 0a      &zLabel[10].
eac0: 20 20 20 20 20 20 29 3b 0a 20 20 20 20 20 20 63        );.      c
ead0: 6f 6e 74 69 6e 75 65 3b 0a 20 20 20 20 7d 0a 20  ontinue;.    }. 
eae0: 20 20 20 72 63 20 3d 20 73 71 6c 69 74 65 33 5f     rc = sqlite3_
eaf0: 6f 70 65 6e 5f 76 32 28 0a 20 20 20 20 20 20 20  open_v2(.       
eb00: 20 20 7a 52 65 70 6f 4e 61 6d 65 2c 20 26 70 50    zRepoName, &pP
eb10: 65 65 72 2c 0a 20 20 20 20 20 20 20 20 20 53 51  eer,.         SQ
eb20: 4c 49 54 45 5f 4f 50 45 4e 5f 52 45 41 44 57 52  LITE_OPEN_READWR
eb30: 49 54 45 2c 0a 20 20 20 20 20 20 20 20 20 67 2e  ITE,.         g.
eb40: 7a 56 66 73 4e 61 6d 65 0a 20 20 20 20 29 3b 0a  zVfsName.    );.
eb50: 20 20 20 20 69 66 28 20 72 63 21 3d 53 51 4c 49      if( rc!=SQLI
eb60: 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 20 20 62  TE_OK ){.      b
eb70: 6c 6f 62 5f 61 70 70 65 6e 64 66 28 26 65 72 72  lob_appendf(&err
eb80: 2c 20 22 25 73 25 73 3a 20 25 73 25 73 22 2c 20  , "%s%s: %s%s", 
eb90: 7a 50 72 65 66 69 78 2c 20 7a 52 65 70 6f 4e 61  zPrefix, zRepoNa
eba0: 6d 65 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20  me,.            
ebb0: 20 20 20 20 20 20 20 73 71 6c 69 74 65 33 5f 65         sqlite3_e
ebc0: 72 72 6d 73 67 28 70 50 65 65 72 29 2c 20 7a 53  rrmsg(pPeer), zS
ebd0: 75 66 66 69 78 29 3b 0a 20 20 20 20 20 20 6e 45  uffix);.      nE
ebe0: 72 72 2b 2b 3b 0a 20 20 20 20 20 20 73 71 6c 69  rr++;.      sqli
ebf0: 74 65 33 5f 63 6c 6f 73 65 28 70 50 65 65 72 29  te3_close(pPeer)
ec00: 3b 0a 20 20 20 20 20 20 63 6f 6e 74 69 6e 75 65  ;.      continue
ec10: 3b 0a 20 20 20 20 7d 0a 20 20 20 20 73 71 6c 69  ;.    }.    sqli
ec20: 74 65 33 5f 63 72 65 61 74 65 5f 66 75 6e 63 74  te3_create_funct
ec30: 69 6f 6e 28 70 50 65 65 72 2c 20 22 73 68 61 72  ion(pPeer, "shar
ec40: 65 64 5f 73 65 63 72 65 74 22 2c 20 33 2c 20 53  ed_secret", 3, S
ec50: 51 4c 49 54 45 5f 55 54 46 38 2c 0a 20 20 20 20  QLITE_UTF8,.    
ec60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
ec70: 20 20 20 20 20 20 20 20 30 2c 20 73 68 61 31 5f          0, sha1_
ec80: 73 68 61 72 65 64 5f 73 65 63 72 65 74 5f 73 71  shared_secret_sq
ec90: 6c 5f 66 75 6e 63 74 69 6f 6e 2c 20 30 2c 20 30  l_function, 0, 0
eca0: 29 3b 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 63  );.    sqlite3_c
ecb0: 72 65 61 74 65 5f 66 75 6e 63 74 69 6f 6e 28 70  reate_function(p
ecc0: 50 65 65 72 2c 20 22 6e 6f 77 22 2c 20 30 2c 53  Peer, "now", 0,S
ecd0: 51 4c 49 54 45 5f 55 54 46 38 2c 30 2c 64 62 5f  QLITE_UTF8,0,db_
ece0: 6e 6f 77 5f 66 75 6e 63 74 69 6f 6e 2c 30 2c 30  now_function,0,0
ecf0: 29 3b 0a 20 20 20 20 73 71 6c 69 74 65 33 5f 62  );.    sqlite3_b
ed00: 75 73 79 5f 74 69 6d 65 6f 75 74 28 70 50 65 65  usy_timeout(pPee
ed10: 72 2c 20 35 30 30 30 29 3b 0a 20 20 20 20 7a 45  r, 5000);.    zE
ed20: 72 72 20 3d 20 30 3b 0a 20 20 20 20 72 63 20 3d  rr = 0;.    rc =
ed30: 20 73 71 6c 69 74 65 33 5f 65 78 65 63 28 70 50   sqlite3_exec(pP
ed40: 65 65 72 2c 20 7a 53 71 6c 2c 20 30 2c 20 30 2c  eer, zSql, 0, 0,
ed50: 20 26 7a 45 72 72 29 3b 0a 20 20 20 20 69 66 28   &zErr);.    if(
ed60: 20 7a 45 72 72 20 29 7b 0a 20 20 20 20 20 20 62   zErr ){.      b
ed70: 6c 6f 62 5f 61 70 70 65 6e 64 66 28 26 65 72 72  lob_appendf(&err
ed80: 2c 20 22 25 73 25 73 3a 20 25 73 25 73 22 2c 20  , "%s%s: %s%s", 
ed90: 7a 50 72 65 66 69 78 2c 20 7a 52 65 70 6f 4e 61  zPrefix, zRepoNa
eda0: 6d 65 2c 20 7a 45 72 72 2c 20 7a 53 75 66 66 69  me, zErr, zSuffi
edb0: 78 29 3b 0a 20 20 20 20 20 20 73 71 6c 69 74 65  x);.      sqlite
edc0: 33 5f 66 72 65 65 28 7a 45 72 72 29 3b 0a 20 20  3_free(zErr);.  
edd0: 20 20 20 20 6e 45 72 72 2b 2b 3b 0a 20 20 20 20      nErr++;.    
ede0: 7d 65 6c 73 65 20 69 66 28 20 72 63 21 3d 53 51  }else if( rc!=SQ
edf0: 4c 49 54 45 5f 4f 4b 20 29 7b 0a 20 20 20 20 20  LITE_OK ){.     
ee00: 20 62 6c 6f 62 5f 61 70 70 65 6e 64 66 28 26 65   blob_appendf(&e
ee10: 72 72 2c 20 22 25 73 25 73 3a 20 25 73 25 73 22  rr, "%s%s: %s%s"
ee20: 2c 20 7a 50 72 65 66 69 78 2c 20 7a 52 65 70 6f  , zPrefix, zRepo
ee30: 4e 61 6d 65 2c 0a 20 20 20 20 20 20 20 20 20 20  Name,.          
ee40: 20 20 20 20 20 20 20 20 20 73 71 6c 69 74 65 33           sqlite3
ee50: 5f 65 72 72 6d 73 67 28 70 50 65 65 72 29 2c 20  _errmsg(pPeer), 
ee60: 7a 53 75 66 66 69 78 29 3b 0a 20 20 20 20 20 20  zSuffix);.      
ee70: 6e 45 72 72 2b 2b 3b 0a 20 20 20 20 7d 0a 20 20  nErr++;.    }.  
ee80: 20 20 73 71 6c 69 74 65 33 5f 63 6c 6f 73 65 28    sqlite3_close(
ee90: 70 50 65 65 72 29 3b 0a 20 20 7d 0a 20 20 64 62  pPeer);.  }.  db
eea0: 5f 66 69 6e 61 6c 69 7a 65 28 26 71 29 3b 0a 20  _finalize(&q);. 
eeb0: 20 69 66 28 20 70 7a 45 72 72 6f 72 4d 73 67 20   if( pzErrorMsg 
eec0: 26 26 20 62 6c 6f 62 5f 73 69 7a 65 28 26 65 72  && blob_size(&er
eed0: 72 29 3e 30 20 29 7b 0a 20 20 20 20 2a 70 7a 45  r)>0 ){.    *pzE
eee0: 72 72 6f 72 4d 73 67 20 3d 20 66 6f 73 73 69 6c  rrorMsg = fossil
eef0: 5f 73 74 72 64 75 70 28 62 6c 6f 62 5f 73 74 72  _strdup(blob_str
ef00: 28 26 65 72 72 29 29 3b 0a 20 20 7d 0a 20 20 62  (&err));.  }.  b
ef10: 6c 6f 62 5f 72 65 73 65 74 28 26 65 72 72 29 3b  lob_reset(&err);
ef20: 0a 20 20 66 6f 73 73 69 6c 5f 66 72 65 65 28 7a  .  fossil_free(z
ef30: 53 65 6c 66 43 6f 64 65 29 3b 0a 20 20 72 65 74  SelfCode);.  ret
ef40: 75 72 6e 20 6e 45 72 72 3b 0a 7d 0a 0a 2f 2a 0a  urn nErr;.}../*.
ef50: 2a 2a 20 41 74 74 65 6d 70 74 20 74 6f 20 6a 6f  ** Attempt to jo
ef60: 69 6e 20 61 20 6c 6f 67 69 6e 2d 67 72 6f 75 70  in a login-group
ef70: 2e 0a 2a 2a 0a 2a 2a 20 49 66 20 70 72 6f 62 6c  ..**.** If probl
ef80: 65 6d 73 20 61 72 69 73 65 2c 20 6c 65 61 76 65  ems arise, leave
ef90: 20 61 6e 20 65 72 72 6f 72 20 6d 65 73 73 61 67   an error messag
efa0: 65 20 69 6e 20 2a 70 7a 45 72 72 4d 73 67 2e 0a  e in *pzErrMsg..
efb0: 2a 2f 0a 76 6f 69 64 20 6c 6f 67 69 6e 5f 67 72  */.void login_gr
efc0: 6f 75 70 5f 6a 6f 69 6e 28 0a 20 20 63 6f 6e 73  oup_join(.  cons
efd0: 74 20 63 68 61 72 20 2a 7a 52 65 70 6f 2c 20 20  t char *zRepo,  
efe0: 20 20 20 20 20 20 20 2f 2a 20 52 65 70 6f 73 69         /* Reposi
eff0: 74 6f 72 79 20 66 69 6c 65 20 69 6e 20 74 68 65  tory file in the
f000: 20 6c 6f 67 69 6e 20 67 72 6f 75 70 20 2a 2f 0a   login group */.
f010: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 4c    const char *zL
f020: 6f 67 69 6e 2c 20 20 20 20 20 20 20 20 2f 2a 20  ogin,        /* 
f030: 4c 6f 67 69 6e 20 6e 61 6d 65 20 66 6f 72 20 74  Login name for t
f040: 68 65 20 6f 74 68 65 72 20 72 65 70 6f 20 2a 2f  he other repo */
f050: 0a 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a  .  const char *z
f060: 50 61 73 73 77 6f 72 64 2c 20 20 20 20 20 2f 2a  Password,     /*
f070: 20 50 61 73 73 77 6f 72 64 20 74 6f 20 70 72 6f   Password to pro
f080: 76 65 20 77 65 20 61 72 65 20 61 75 74 68 6f 72  ve we are author
f090: 69 7a 65 64 20 74 6f 20 6a 6f 69 6e 20 2a 2f 0a  ized to join */.
f0a0: 20 20 63 6f 6e 73 74 20 63 68 61 72 20 2a 7a 4e    const char *zN
f0b0: 65 77 4e 61 6d 65 2c 20 20 20 20 20 20 2f 2a 20  ewName,      /* 
f0c0: 4e 61 6d 65 20 6f 66 20 6e 65 77 20 6c 6f 67 69  Name of new logi
f0d0: 6e 20 67 72 6f 75 70 20 69 66 20 6d 61 6b 69 6e  n group if makin
f0e0: 67 20 61 20 6e 65 77 20 6f 6e 65 20 2a 2f 0a 20  g a new one */. 
f0f0: 20 63 68 61 72 20 2a 2a 70 7a 45 72 72 4d 73 67   char **pzErrMsg
f100: 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a 20 4c              /* L
f110: 65 61 76 65 20 61 6e 20 65 72 72 6f 72 20 6d 65  eave an error me
f120: 73 73 61 67 65 20 68 65 72 65 20 2a 2f 0a 29 7b  ssage here */.){
f130: 0a 20 20 42 6c 6f 62 20 66 75 6c 6c 4e 61 6d 65  .  Blob fullName
f140: 3b 20 20 20 20 20 20 20 20 20 20 20 20 20 2f 2a  ;             /*
f150: 20 42 6c 6f 62 20 66 6f 72 20 66 69 6e 64 69 6e   Blob for findin
f160: 67 20 66 75 6c 6c 20 70 61 74 68 6e 61 6d 65 73  g full pathnames
f170: 20 2a 2f 0a 20 20 73 71 6c 69 74 65 33 20 2a 70   */.  sqlite3 *p
f180: 4f 74 68 65 72 3b 20 20 20 20 20 20 20 20 20 20  Other;          
f190: 20 2f 2a 20 54 68 65 20 6f 74 68 65 72 20 72 65   /* The other re
f1a0: 70 6f 73 69 74 6f 72 79 20 2a 2f 0a 20 20 69 6e  pository */.  in
f1b0: 74 20 72 63 3b 20 20 20 20 20 20 20 20 20 20 20  t rc;           
f1c0: 20 20 20 20 20 20 20 20 20 2f 2a 20 52 65 74 75           /* Retu
f1d0: 72 6e 20 63 6f 64 65 20 66 72 6f 6d 20 73 71 6c  rn code from sql
f1e0: 69 74 65 33 20 66 75 6e 63 74 69 6f 6e 73 20 2a  ite3 functions *
f1f0: 2f 0a 20 20 63 68 61 72 20 2a 7a 4f 74 68 65 72  /.  char *zOther
f200: 50 72 6f 6a 43 6f 64 65 3b 20 20 20 20 20 20 2f  ProjCode;      /
f210: 2a 20 50 72 6f 6a 65 63 74 20 63 6f 64 65 20 66  * Project code f
f220: 6f 72 20 70 4f 74 68 65 72 20 2a 2f 0a 20 20 63  or pOther */.  c
f230: 68 61 72 20 2a 7a 50 77 48 61 73 68 3b 20 20 20  har *zPwHash;   
f240: 20 20 20 20 20 20 20 20 20 20 2f 2a 20 50 61 73            /* Pas
f250: 73 77 6f 72 64 20 68 61 73 68 20 6f 6e 20 70 4f  sword hash on pO
f260: 74 68 65 72 20 2a 2f 0a 20 20 63 68 61 72 20 2a  ther */.  char *
f270: 7a 53 65 6c 66 52 65 70 6f 3b 20 20 20 20 20 20  zSelfRepo;      
f280: 20 20 20 20 20 2f 2a 20 4e 61 6d 65 20 6f 66 20       /* Name of 
f290: 6f 75 72 20 72 65 70 6f 73 69 74 6f 72 79 20 2a  our repository *
f2a0: 2f 0a 20 20 63 68 61 72 20 2a 7a 53 65 6c 66 4c  /.  char *zSelfL
f2b0: 61 62 65 6c 3b 20 20 20 20 20 20 20 20 20 20 2f  abel;          /
f2c0: 2a 20 50 72 6f 6a 65 63 74 2d 6e 61 6d 65 20 66  * Project-name f
f2d0: 6f 72 20 6f 75 72 20 72 65 70 6f 73 69 74 6f 72  or our repositor
f2e0: 79 20 2a 2f 0a 20 20 63 68 61 72 20 2a 7a 53 65  y */.  char *zSe
f2f0: 6c 66 50 72 6f 6a 43 6f 64 65 3b 20 20 20 20 20  lfProjCode;     
f300: 20 20 2f 2a 20 4f 75 72 20 70 72 6f 6a 65 63 74    /* Our project
f310: 2d 63 6f 64 65 20 2a 2f 0a 20 20 63 68 61 72 20  -code */.  char 
f320: 2a 7a 53 71 6c 3b 20 20 20 20 20 20 20 20 20 20  *zSql;          
f330: 20 20 20 20 20 20 2f 2a 20 53 51 4c 20 74 6f 20        /* SQL to 
f340: 72 75 6e 20 6f 6e 20 61 6c 6c 20 70 65 65 72 73  run on all peers
f350: 20 2a 2f 0a 20 20 63 6f 6e 73 74 20 63 68 61 72   */.  const char
f360: 20 2a 7a 53 65 6c 66 3b 20 20 20 20 20 20 20 20   *zSelf;        
f370: 20 2f 2a 20 54 68 65 20 41 54 54 41 43 48 20 6e   /* The ATTACH n
f380: 61 6d 65 20 6f 66 20 6f 75 72 20 72 65 70 6f 73  ame of our repos
f390: 69 74 6f 72 79 20 2a 2f 0a 0a 20 20 2a 70 7a 45  itory */..  *pzE
f3a0: 72 72 4d 73 67 20 3d 20 30 3b 20 20 20 2f 2a 20  rrMsg = 0;   /* 
f3b0: 44 65 66 61 75 6c 74 20 74 6f 20 6e 6f 20 65 72  Default to no er
f3c0: 72 6f 72 73 20 2a 2f 0a 20 20 7a 53 65 6c 66 20  rors */.  zSelf 
f3d0: 3d 20 22 72 65 70 6f 73 69 74 6f 72 79 22 3b 0a  = "repository";.
f3e0: 0a 20 20 2f 2a 20 47 65 74 20 74 68 65 20 66 75  .  /* Get the fu
f3f0: 6c 6c 20 70 61 74 68 6e 61 6d 65 20 6f 66 20 74  ll pathname of t
f400: 68 65 20 6f 74 68 65 72 20 72 65 70 6f 73 69 74  he other reposit
f410: 6f 72 79 20 2a 2f 0a 20 20 66 69 6c 65 5f 63 61  ory */.  file_ca
f420: 6e 6f 6e 69 63 61 6c 5f 6e 61 6d 65 28 7a 52 65  nonical_name(zRe
f430: 70 6f 2c 20 26 66 75 6c 6c 4e 61 6d 65 2c 20 30  po, &fullName, 0
f440: 29 3b 0a 20 20 7a 52 65 70 6f 20 3d 20 66 6f 73  );.  zRepo = fos
f450: 73 69 6c 5f 73 74 72 64 75 70 28 62 6c 6f 62 5f  sil_strdup(blob_
f460: 73 74 72 28 26 66 75 6c 6c 4e 61 6d 65 29 29 3b  str(&fullName));
f470: 0a 20 20 62 6c 6f 62 5f 72 65 73 65 74 28 26 66  .  blob_reset(&f
f480: 75 6c 6c 4e 61 6d 65 29 3b 0a 0a 20 20 2f 2a 20  ullName);..  /* 
f490: 47 65 74 20 74 68 65 20 66 75 6c 6c 20 70 61 74  Get the full pat
f4a0: 68 6e 61 6d 65 20 66 6f 72 20 6f 75 72 20 72 65  hname for our re
f4b0: 70 6f 73 69 74 6f 72 79 2e 20 20 41 6c 73 6f 20  pository.  Also 
f4c0: 74 68 65 20 70 72 6f 6a 65 63 74 20 63 6f 64 65  the project code
f4d0: 0a 20 20 2a 2a 20 61 6e 64 20 70 72 6f 6a 65 63  .  ** and projec
f4e0: 74 20 6e 61 6d 65 20 66 6f 72 20 6f 75 72 73 65  t name for ourse
f4f0: 6c 66 2e 20 2a 2f 0a 20 20 66 69 6c 65 5f 63 61  lf. */.  file_ca
f500: 6e 6f 6e 69 63 61 6c 5f 6e 61 6d 65 28 67 2e 7a  nonical_name(g.z
f510: 52 65 70 6f 73 69 74 6f 72 79 4e 61 6d 65 2c 20  RepositoryName, 
f520: 26 66 75 6c 6c 4e 61 6d 65 2c 20 30 29 3b 0a 20  &fullName, 0);. 
f530: 20 7a 53 65 6c 66 52 65 70 6f 20 3d 20 66 6f 73   zSelfRepo = fos
f540: 73 69 6c 5f 73 74 72 64 75 70 28 62 6c 6f 62 5f  sil_strdup(blob_
f550: 73 74 72 28 26 66 75 6c 6c 4e 61 6d 65 29 29 3b  str(&fullName));
f560: 0a 20 20 62 6c 6f 62 5f 72 65 73 65 74 28 26 66  .  blob_reset(&f
f570: 75 6c 6c 4e 61 6d 65 29 3b 0a 20 20 7a 53 65 6c  ullName);.  zSel
f580: 66 50 72 6f 6a 43 6f 64 65 20 3d 20 64 62 5f 67  fProjCode = db_g
f590: 65 74 28 22 70 72 6f 6a 65 63 74 2d 63 6f 64 65  et("project-code
f5a0: 22 2c 20 22 75 6e 6b 6e 6f 77 6e 22 29 3b 0a 20  ", "unknown");. 
f5b0: 20 7a 53 65 6c 66 4c 61 62 65 6c 20 3d 20 64 62   zSelfLabel = db
f5c0: 5f 67 65 74 28 22 70 72 6f 6a 65 63 74 2d 6e 61  _get("project-na
f5d0: 6d 65 22 2c 20 30 29 3b 0a 20 20 69 66 28 20 7a  me", 0);.  if( z
f5e0: 53 65 6c 66 4c 61 62 65 6c 3d 3d 30 20 29 7b 0a  SelfLabel==0 ){.
f5f0: 20 20 20 20 7a 53 65 6c 66 4c 61 62 65 6c 20 3d      zSelfLabel =
f600: 20 7a 53 65 6c 66 50 72 6f 6a 43 6f 64 65 3b 0a   zSelfProjCode;.
f610: 20 20 7d 0a 0a 20 20 2f 2a 20 4d 61 6b 65 20 73    }..  /* Make s
f620: 75 72 65 20 77 65 20 61 72 65 20 6e 6f 74 20 74  ure we are not t
f630: 72 79 69 6e 67 20 74 6f 20 6a 6f 69 6e 20 6f 75  rying to join ou
f640: 72 73 65 6c 76 65 73 20 2a 2f 0a 20 20 69 66 28  rselves */.  if(
f650: 20 66 6f 73 73 69 6c 5f 73 74 72 63 6d 70 28 7a   fossil_strcmp(z
f660: 52 65 70 6f 2c 20 7a 53 65 6c 66 52 65 70 6f 29  Repo, zSelfRepo)
f670: 3d 3d 30 20 29 7b 0a 20 20 20 20 2a 70 7a 45 72  ==0 ){.    *pzEr
f680: 72 4d 73 67 20 3d 20 6d 70 72 69 6e 74 66 28 22  rMsg = mprintf("
f690: 54 68 65 20 5c 22 6f 74 68 65 72 5c 22 20 72 65  The \"other\" re
f6a0: 70 6f 73 69 74 6f 72 79 20 69 73 20 74 68 65 20  pository is the 
f6b0: 73 61 6d 65 20 61 73 20 74 68 69 73 20 6f 6e 65  same as this one
f6c0: 2e 22 29 3b 0a 20 20 20 20 72 65 74 75 72 6e 3b  .");.    return;
f6d0: 0a 20 20 7d 0a 0a 20 20 2f 2a 20 4d 61 6b 65 20  .  }..  /* Make 
f6e0: 73 75 72 65 20 74 68 65 20 6f 74 68 65 72 20 72  sure the other r
f6f0: 65 70 6f 73 69 74 6f 72 79 20 69 73 20 61 20 76  epository is a v
f700: 61 6c 69 64 20 46 6f 73 73 69 6c 20 64 61 74 61  alid Fossil data
f710: 62 61 73 65 20 2a 2f 0a 20 20 69 66 28 20 66 69  base */.  if( fi
f720: 6c 65 5f 73 69 7a 65 28 7a 52 65 70 6f 2c 20 45  le_size(zRepo, E
f730: 78 74 46 49 4c 45 29 3c 30 20 29 7b 0a 20 20 20  xtFILE)<0 ){.   
f740: 20 2a 70 7a 45 72 72 4d 73 67 20 3d 20 6d 70 72   *pzErrMsg = mpr
f750: 69 6e 74 66 28 22 72 65 70 6f 73 69 74 6f 72 79  intf("repository
f760: 20 66 69 6c 65 20 5c 22 25 73 5c 22 20 64 6f 65   file \"%s\" doe
f770: 73 20 6e 6f 74 20 65 78 69 73 74 22 2c 20 7a 52  s not exist", zR
f780: 65 70 6f 29 3b 0a 20 20 20 20 72 65 74 75 72 6e  epo);.    return
f790: 3b 0a 20 20 7d 0a 20 20 72 63 20 3d 20 73 71 6c  ;.  }.  rc = sql
f7a0: 69 74 65 33 5f 6f 70 65 6e 5f 76 32 28 0a 20 20  ite3_open_v2(.  
f7b0: 20 20 20 20 20 7a 52 65 70 6f 2c 20 26 70 4f 74       zRepo, &pOt
f7c0: 68 65 72 2c 0a 20 20 20 20 20 20 20 53 51 4c 49  her,.       SQLI
f7d0: 54 45 5f 4f 50 45 4e 5f 52 45 41 44 57 52 49 54  TE_OPEN_READWRIT
f7e0: 45 20 7c 20 53 51 4c 49 54 45 5f 4f 50 45 4e 5f  E | SQLITE_OPEN_
f7f0: 43 52 45 41 54 45 2c 0a 20 20 20 20 20 20 20 67  CREATE,.       g
f800: 2e 7a 56 66 73 4e 61 6d 65 0a 20 20 29 3b 0a 20  .zVfsName.  );. 
f810: 20 69 66 28 20 72 63 21 3d 53 51 4c 49 54 45 5f   if( rc!=SQLITE_
f820: 4f 4b 20 29 7b 0a 20 20 20 20 2a 70 7a 45 72 72  OK ){.    *pzErr
f830: 4d 73 67 20 3d 20 66 6f 73 73 69 6c 5f 73 74 72  Msg = fossil_str
f840: 64 75 70 28 73 71 6c 69 74 65 33 5f 65 72 72 6d  dup(sqlite3_errm
f850: 73 67 28 70 4f 74 68 65 72 29 29 3b 0a 20 20 7d  sg(pOther));.  }
f860: 65 6c 73 65 7b 0a 20 20 20 20 72 63 20 3d 20 73  else{.    rc = s
f870: 71 6c 69 74 65 33 5f 65 78 65 63 28 70 4f 74 68  qlite3_exec(pOth
f880: 65 72 2c 20 22 53 45 4c 45 43 54 20 63 6f 75 6e  er, "SELECT coun
f890: 74 28 2a 29 20 46 52 4f 4d 20 75 73 65 72 22 2c  t(*) FROM user",
f8a0: 20 30 2c 20 30 2c 20 70 7a 45 72 72 4d 73 67 29   0, 0, pzErrMsg)
f8b0: 3b 0a 20 20 7d 0a 20 20 73 71 6c 69 74 65 33 5f  ;.  }.  sqlite3_
f8c0: 63 6c 6f 73 65 28 70 4f 74 68 65 72 29 3b 0a 20  close(pOther);. 
f8d0: 20 69 66 28 20 72 63 20 29 20 72 65 74 75 72 6e   if( rc ) return
f8e0: 3b 0a 0a 20 20 2f 2a 20 41 74 74 61 63 68 20 74  ;..  /* Attach t
f8f0: 68 65 20 6f 74 68 65 72 20 72 65 70 6f 73 69 74  he other reposit
f900: 6f 72 79 2e 20 20 4d 61 6b 65 20 73 75 72 65 20  ory.  Make sure 
f910: 74 68 65 20 75 73 65 72 6e 61 6d 65 2f 70 61 73  the username/pas
f920: 73 77 6f 72 64 20 69 73 0a 20 20 2a 2a 20 76 61  sword is.  ** va
f930: 6c 69 64 20 61 6e 64 20 68 61 73 20 53 65 74 75  lid and has Setu
f940: 70 20 70 65 72 6d 69 73 73 69 6f 6e 2e 0a 20 20  p permission..  
f950: 2a 2f 0a 20 20 64 62 5f 61 74 74 61 63 68 28 7a  */.  db_attach(z
f960: 52 65 70 6f 2c 20 22 6f 74 68 65 72 22 29 3b 0a  Repo, "other");.
f970: 20 20 7a 4f 74 68 65 72 50 72 6f 6a 43 6f 64 65    zOtherProjCode
f980: 20 3d 20 64 62 5f 74 65 78 74 28 22 78 22 2c 20   = db_text("x", 
f990: 22 53 45 4c 45 43 54 20 76 61 6c 75 65 20 46 52  "SELECT value FR
f9a0: 4f 4d 20 6f 74 68 65 72 2e 63 6f 6e 66 69 67 22  OM other.config"
f9b0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
f9c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
f9d0: 20 22 20 57 48 45 52 45 20 6e 61 6d 65 3d 27 70   " WHERE name='p
f9e0: 72 6f 6a 65 63 74 2d 63 6f 64 65 27 22 29 3b 0a  roject-code'");.
f9f0: 20 20 7a 50 77 48 61 73 68 20 3d 20 73 68 61 31    zPwHash = sha1
fa00: 5f 73 68 61 72 65 64 5f 73 65 63 72 65 74 28 7a  _shared_secret(z
fa10: 50 61 73 73 77 6f 72 64 2c 20 7a 4c 6f 67 69 6e  Password, zLogin
fa20: 2c 20 7a 4f 74 68 65 72 50 72 6f 6a 43 6f 64 65  , zOtherProjCode
fa30: 29 3b 0a 20 20 69 66 28 20 21 64 62 5f 65 78 69  );.  if( !db_exi
fa40: 73 74 73 28 0a 20 20 20 20 22 53 45 4c 45 43 54  sts(.    "SELECT
fa50: 20 31 20 46 52 4f 4d 20 6f 74 68 65 72 2e 75 73   1 FROM other.us
fa60: 65 72 22 0a 20 20 20 20 22 20 57 48 45 52 45 20  er".    " WHERE 
fa70: 6c 6f 67 69 6e 3d 25 51 20 41 4e 44 20 63 61 70  login=%Q AND cap
fa80: 20 47 4c 4f 42 20 27 2a 73 2a 27 22 0a 20 20 20   GLOB '*s*'".   
fa90: 20 22 20 20 20 41 4e 44 20 28 70 77 3d 25 51 20   "   AND (pw=%Q 
faa0: 4f 52 20 70 77 3d 25 51 29 22 2c 0a 20 20 20 20  OR pw=%Q)",.    
fab0: 7a 4c 6f 67 69 6e 2c 20 7a 50 61 73 73 77 6f 72  zLogin, zPasswor
fac0: 64 2c 20 7a 50 77 48 61 73 68 29 0a 20 20 29 7b  d, zPwHash).  ){
fad0: 0a 20 20 20 20 64 62 5f 64 65 74 61 63 68 28 22  .    db_detach("
fae0: 6f 74 68 65 72 22 29 3b 0a 20 20 20 20 2a 70 7a  other");.    *pz
faf0: 45 72 72 4d 73 67 20 3d 20 22 54 68 65 20 73 75  ErrMsg = "The su
fb00: 70 70 6c 69 65 64 20 75 73 65 72 6e 61 6d 65 2f  pplied username/
fb10: 70 61 73 73 77 6f 72 64 20 64 6f 65 73 20 6e 6f  password does no
fb20: 74 20 63 6f 72 72 65 73 70 6f 6e 64 20 74 6f 20  t correspond to 
fb30: 61 22 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  a".             
fb40: 20 20 20 22 20 75 73 65 72 20 53 65 74 75 70 20     " user Setup 
fb50: 70 65 72 6d 69 73 73 69 6f 6e 20 6f 6e 20 74 68  permission on th
fb60: 65 20 6f 74 68 65 72 20 72 65 70 6f 73 69 74 6f  e other reposito
fb70: 72 79 2e 22 3b 0a 20 20 20 20 72 65 74 75 72 6e  ry.";.    return
fb80: 3b 0a 20 20 7d 0a 0a 20 20 2f 2a 20 43 72 65 61  ;.  }..  /* Crea
fb90: 74 65 20 61 6c 6c 20 74 68 65 20 6e 65 63 65 73  te all the neces
fba0: 73 61 72 79 20 43 4f 4e 46 49 47 20 74 61 62 6c  sary CONFIG tabl
fbb0: 65 20 65 6e 74 72 69 65 73 20 6f 6e 20 62 6f 74  e entries on bot
fbc0: 68 20 74 68 65 0a 20 20 2a 2a 20 6f 74 68 65 72  h the.  ** other
fbd0: 20 72 65 70 6f 73 69 74 6f 72 79 20 61 6e 64 20   repository and 
fbe0: 6f 6e 20 6f 75 72 20 6f 77 6e 20 72 65 70 6f 73  on our own repos
fbf0: 69 74 6f 72 79 2e 0a 20 20 2a 2f 0a 20 20 7a 53  itory..  */.  zS
fc00: 65 6c 66 50 72 6f 6a 43 6f 64 65 20 3d 20 61 62  elfProjCode = ab
fc10: 62 72 65 76 69 61 74 65 64 5f 70 72 6f 6a 65 63  breviated_projec
fc20: 74 5f 63 6f 64 65 28 7a 53 65 6c 66 50 72 6f 6a  t_code(zSelfProj
fc30: 43 6f 64 65 29 3b 0a 20 20 7a 4f 74 68 65 72 50  Code);.  zOtherP
fc40: 72 6f 6a 43 6f 64 65 20 3d 20 61 62 62 72 65 76  rojCode = abbrev
fc50: 69 61 74 65 64 5f 70 72 6f 6a 65 63 74 5f 63 6f  iated_project_co
fc60: 64 65 28 7a 4f 74 68 65 72 50 72 6f 6a 43 6f 64  de(zOtherProjCod
fc70: 65 29 3b 0a 20 20 64 62 5f 62 65 67 69 6e 5f 74  e);.  db_begin_t
fc80: 72 61 6e 73 61 63 74 69 6f 6e 28 29 3b 0a 20 20  ransaction();.  
fc90: 64 62 5f 6d 75 6c 74 69 5f 65 78 65 63 28 0a 20  db_multi_exec(. 
fca0: 20 20 20 22 44 45 4c 45 54 45 20 46 52 4f 4d 20     "DELETE FROM 
fcb0: 5c 22 25 77 5c 22 2e 63 6f 6e 66 69 67 20 57 48  \"%w\".config WH
fcc0: 45 52 45 20 6e 61 6d 65 20 47 4c 4f 42 20 27 70  ERE name GLOB 'p
fcd0: 65 65 72 2d 2a 27 3b 22 0a 20 20 20 20 22 49 4e  eer-*';".    "IN
fce0: 53 45 52 54 20 49 4e 54 4f 20 5c 22 25 77 5c 22  SERT INTO \"%w\"
fcf0: 2e 63 6f 6e 66 69 67 28 6e 61 6d 65 2c 76 61 6c  .config(name,val
fd00: 75 65 29 20 56 41 4c 55 45 53 28 27 70 65 65 72  ue) VALUES('peer
fd10: 2d 72 65 70 6f 2d 25 71 27 2c 25 51 29 3b 22 0a  -repo-%q',%Q);".
fd20: 20 20 20 20 22 49 4e 53 45 52 54 20 49 4e 54 4f      "INSERT INTO
fd30: 20 5c 22 25 77 5c 22 2e 63 6f 6e 66 69 67 28 6e   \"%w\".config(n
fd40: 61 6d 65 2c 76 61 6c 75 65 29 20 22 0a 20 20 20  ame,value) ".   
fd50: 20 22 20 20 53 45 4c 45 43 54 20 27 70 65 65 72   "  SELECT 'peer
fd60: 2d 6e 61 6d 65 2d 25 71 27 2c 20 76 61 6c 75 65  -name-%q', value
fd70: 20 46 52 4f 4d 20 6f 74 68 65 72 2e 63 6f 6e 66   FROM other.conf
fd80: 69 67 22 0a 20 20 20 20 22 20 20 20 57 48 45 52  ig".    "   WHER
fd90: 45 20 6e 61 6d 65 3d 27 70 72 6f 6a 65 63 74 2d  E name='project-
fda0: 6e 61 6d 65 27 3b 22 2c 0a 20 20 20 20 7a 53 65  name';",.    zSe
fdb0: 6c 66 2c 0a 20 20 20 20 7a 53 65 6c 66 2c 20 7a  lf,.    zSelf, z
fdc0: 4f 74 68 65 72 50 72 6f 6a 43 6f 64 65 2c 20 7a  OtherProjCode, z
fdd0: 52 65 70 6f 2c 0a 20 20 20 20 7a 53 65 6c 66 2c  Repo,.    zSelf,
fde0: 20 7a 4f 74 68 65 72 50 72 6f 6a 43 6f 64 65 0a   zOtherProjCode.
fdf0: 20 20 29 3b 0a 20 20 64 62 5f 6d 75 6c 74 69 5f    );.  db_multi_
fe00: 65 78 65 63 28 0a 20 20 20 20 22 49 4e 53 45 52  exec(.    "INSER
fe10: 54 20 4f 52 20 49 47 4e 4f 52 45 20 49 4e 54 4f  T OR IGNORE INTO
fe20: 20 6f 74 68 65 72 2e 63 6f 6e 66 69 67 28 6e 61   other.config(na
fe30: 6d 65 2c 76 61 6c 75 65 29 22 0a 20 20 20 20 22  me,value)".    "
fe40: 20 56 41 4c 55 45 53 28 27 6c 6f 67 69 6e 2d 67   VALUES('login-g
fe50: 72 6f 75 70 2d 6e 61 6d 65 27 2c 25 51 29 3b 22  roup-name',%Q);"
fe60: 0a 20 20 20 20 22 49 4e 53 45 52 54 20 4f 52 20  .    "INSERT OR 
fe70: 49 47 4e 4f 52 45 20 49 4e 54 4f 20 6f 74 68 65  IGNORE INTO othe
fe80: 72 2e 63 6f 6e 66 69 67 28 6e 61 6d 65 2c 76 61  r.config(name,va
fe90: 6c 75 65 29 22 0a 20 20 20 20 22 20 56 41 4c 55  lue)".    " VALU
fea0: 45 53 28 27 6c 6f 67 69 6e 2d 67 72 6f 75 70 2d  ES('login-group-
feb0: 63 6f 64 65 27 2c 6c 6f 77 65 72 28 68 65 78 28  code',lower(hex(
fec0: 72 61 6e 64 6f 6d 62 6c 6f 62 28 38 29 29 29 29  randomblob(8))))
fed0: 3b 22 2c 0a 20 20 20 20 7a 4e 65 77 4e 61 6d 65  ;",.    zNewName
fee0: 0a 20 20 29 3b 0a 20 20 64 62 5f 6d 75 6c 74 69  .  );.  db_multi
fef0: 5f 65 78 65 63 28 0a 20 20 20 20 22 52 45 50 4c  _exec(.    "REPL
ff00: 41 43 45 20 49 4e 54 4f 20 5c 22 25 77 5c 22 2e  ACE INTO \"%w\".
ff10: 63 6f 6e 66 69 67 28 6e 61 6d 65 2c 76 61 6c 75  config(name,valu
ff20: 65 29 22 0a 20 20 20 20 22 20 20 53 45 4c 45 43  e)".    "  SELEC
ff30: 54 20 6e 61 6d 65 2c 20 76 61 6c 75 65 20 46 52  T name, value FR
ff40: 4f 4d 20 6f 74 68 65 72 2e 63 6f 6e 66 69 67 22  OM other.config"
ff50: 0a 20 20 20 20 22 20 20 20 57 48 45 52 45 20 6e  .    "   WHERE n
ff60: 61 6d 65 20 47 4c 4f 42 20 27 70 65 65 72 2d 2a  ame GLOB 'peer-*
ff70: 27 20 4f 52 20 6e 61 6d 65 20 47 4c 4f 42 20 27  ' OR name GLOB '
ff80: 6c 6f 67 69 6e 2d 67 72 6f 75 70 2d 2a 27 22 2c  login-group-*'",
ff90: 0a 20 20 20 20 7a 53 65 6c 66 0a 20 20 29 3b 0a  .    zSelf.  );.
ffa0: 20 20 64 62 5f 65 6e 64 5f 74 72 61 6e 73 61 63    db_end_transac
ffb0: 74 69 6f 6e 28 30 29 3b 0a 20 20 64 62 5f 6d 75  tion(0);.  db_mu
ffc0: 6c 74 69 5f 65 78 65 63 28 22 44 45 54 41 43 48  lti_exec("DETACH
ffd0: 20 6f 74 68 65 72 22 29 3b 0a 0a 20 20 2f 2a 20   other");..  /* 
ffe0: 50 72 6f 70 61 67 61 74 65 20 74 68 65 20 63 68  Propagate the ch
fff0: 61 6e 67 65 73 20 74 6f 20 61 6c 6c 20 6f 74 68  anges to all oth
10000 65 72 20 6d 65 6d 62 65 72 73 20 6f 66 20 74 68  er members of th
10010 65 20 6c 6f 67 69 6e 2d 67 72 6f 75 70 20 2a 2f  e login-group */
10020 0a 20 20 7a 53 71 6c 20 3d 20 6d 70 72 69 6e 74  .  zSql = mprint
10030 66 28 0a 20 20 20 20 22 42 45 47 49 4e 3b 22 0a  f(.    "BEGIN;".
10040 20 20 20 20 22 52 45 50 4c 41 43 45 20 49 4e 54      "REPLACE INT
10050 4f 20 63 6f 6e 66 69 67 28 6e 61 6d 65 2c 76 61  O config(name,va
10060 6c 75 65 2c 6d 74 69 6d 65 29 20 56 41 4c 55 45  lue,mtime) VALUE
10070 53 28 27 70 65 65 72 2d 6e 61 6d 65 2d 25 71 27  S('peer-name-%q'
10080 2c 25 51 2c 6e 6f 77 28 29 29 3b 22 0a 20 20 20  ,%Q,now());".   
10090 20 22 52 45 50 4c 41 43 45 20 49 4e 54 4f 20 63   "REPLACE INTO c
100a0 6f 6e 66 69 67 28 6e 61 6d 65 2c 76 61 6c 75 65  onfig(name,value
100b0 2c 6d 74 69 6d 65 29 20 56 41 4c 55 45 53 28 27  ,mtime) VALUES('
100c0 70 65 65 72 2d 72 65 70 6f 2d 25 71 27 2c 25 51  peer-repo-%q',%Q
100d0 2c 6e 6f 77 28 29 29 3b 22 0a 20 20 20 20 22 43  ,now());".    "C
100e0 4f 4d 4d 49 54 3b 22 2c 0a 20 20 20 20 7a 53 65  OMMIT;",.    zSe
100f0 6c 66 50 72 6f 6a 43 6f 64 65 2c 20 7a 53 65 6c  lfProjCode, zSel
10100 66 4c 61 62 65 6c 2c 20 7a 53 65 6c 66 50 72 6f  fLabel, zSelfPro
10110 6a 43 6f 64 65 2c 20 7a 53 65 6c 66 52 65 70 6f  jCode, zSelfRepo
10120 0a 20 20 29 3b 0a 20 20 6c 6f 67 69 6e 5f 67 72  .  );.  login_gr
10130 6f 75 70 5f 73 71 6c 28 7a 53 71 6c 2c 20 22 3c  oup_sql(zSql, "<
10140 6c 69 3e 20 22 2c 20 22 3c 2f 6c 69 3e 22 2c 20  li> ", "</li>", 
10150 70 7a 45 72 72 4d 73 67 29 3b 0a 20 20 66 6f 73  pzErrMsg);.  fos
10160 73 69 6c 5f 66 72 65 65 28 7a 53 71 6c 29 3b 0a  sil_free(zSql);.
10170 7d 0a 0a 2f 2a 0a 2a 2a 20 4c 65 61 76 65 20 74  }../*.** Leave t
10180 68 65 20 6c 6f 67 69 6e 20 67 72 6f 75 70 20 74  he login group t
10190 68 61 74 20 77 65 20 61 72 65 20 63 75 72 72 65  hat we are curre
101a0 6e 74 6c 79 20 70 61 72 74 20 6f 66 2e 0a 2a 2f  ntly part of..*/
101b0 0a 76 6f 69 64 20 6c 6f 67 69 6e 5f 67 72 6f 75  .void login_grou
101c0 70 5f 6c 65 61 76 65 28 63 68 61 72 20 2a 2a 70  p_leave(char **p
101d0 7a 45 72 72 4d 73 67 29 7b 0a 20 20 63 68 61 72  zErrMsg){.  char
101e0 20 2a 7a 50 72 6f 6a 43 6f 64 65 3b 0a 20 20 63   *zProjCode;.  c
101f0 68 61 72 20 2a 7a 53 71 6c 3b 0a 0a 20 20 2a 70  har *zSql;..  *p
10200 7a 45 72 72 4d 73 67 20 3d 20 30 3b 0a 20 20 7a  zErrMsg = 0;.  z
10210 50 72 6f 6a 43 6f 64 65 20 3d 20 61 62 62 72 65  ProjCode = abbre
10220 76 69 61 74 65 64 5f 70 72 6f 6a 65 63 74 5f 63  viated_project_c
10230 6f 64 65 28 64 62 5f 67 65 74 28 22 70 72 6f 6a  ode(db_get("proj
10240 65 63 74 2d 63 6f 64 65 22 2c 22 78 22 29 29 3b  ect-code","x"));
10250 0a 20 20 7a 53 71 6c 20 3d 20 6d 70 72 69 6e 74  .  zSql = mprint
10260 66 28 0a 20 20 20 20 22 44 45 4c 45 54 45 20 46  f(.    "DELETE F
10270 52 4f 4d 20 63 6f 6e 66 69 67 20 57 48 45 52 45  ROM config WHERE
10280 20 6e 61 6d 65 20 47 4c 4f 42 20 27 70 65 65 72   name GLOB 'peer
10290 2d 2a 2d 25 71 27 3b 22 0a 20 20 20 20 22 44 45  -*-%q';".    "DE
102a0 4c 45 54 45 20 46 52 4f 4d 20 63 6f 6e 66 69 67  LETE FROM config
102b0 22 0a 20 20 20 20 22 20 57 48 45 52 45 20 6e 61  ".    " WHERE na
102c0 6d 65 3d 27 6c 6f 67 69 6e 2d 67 72 6f 75 70 2d  me='login-group-
102d0 6e 61 6d 65 27 22 0a 20 20 20 20 22 20 20 20 41  name'".    "   A
102e0 4e 44 20 28 53 45 4c 45 43 54 20 63 6f 75 6e 74  ND (SELECT count
102f0 28 2a 29 20 46 52 4f 4d 20 63 6f 6e 66 69 67 20  (*) FROM config 
10300 57 48 45 52 45 20 6e 61 6d 65 20 47 4c 4f 42 20  WHERE name GLOB 
10310 27 70 65 65 72 2d 2a 27 29 3d 3d 30 3b 22 2c 0a  'peer-*')==0;",.
10320 20 20 20 20 7a 50 72 6f 6a 43 6f 64 65 0a 20 20      zProjCode.  
10330 29 3b 0a 20 20 66 6f 73 73 69 6c 5f 66 72 65 65  );.  fossil_free
10340 28 7a 50 72 6f 6a 43 6f 64 65 29 3b 0a 20 20 6c  (zProjCode);.  l
10350 6f 67 69 6e 5f 67 72 6f 75 70 5f 73 71 6c 28 7a  ogin_group_sql(z
10360 53 71 6c 2c 20 22 3c 6c 69 3e 20 22 2c 20 22 3c  Sql, "<li> ", "<
10370 2f 6c 69 3e 22 2c 20 70 7a 45 72 72 4d 73 67 29  /li>", pzErrMsg)
10380 3b 0a 20 20 66 6f 73 73 69 6c 5f 66 72 65 65 28  ;.  fossil_free(
10390 7a 53 71 6c 29 3b 0a 20 20 64 62 5f 6d 75 6c 74  zSql);.  db_mult
103a0 69 5f 65 78 65 63 28 0a 20 20 20 20 22 44 45 4c  i_exec(.    "DEL
103b0 45 54 45 20 46 52 4f 4d 20 63 6f 6e 66 69 67 20  ETE FROM config 
103c0 22 0a 20 20 20 20 22 20 57 48 45 52 45 20 6e 61  ".    " WHERE na
103d0 6d 65 20 47 4c 4f 42 20 27 70 65 65 72 2d 2a 27  me GLOB 'peer-*'
103e0 22 0a 20 20 20 20 22 20 20 20 20 4f 52 20 6e 61  ".    "    OR na
103f0 6d 65 20 47 4c 4f 42 20 27 6c 6f 67 69 6e 2d 67  me GLOB 'login-g
10400 72 6f 75 70 2d 2a 27 3b 22 0a 20 20 29 3b 0a 7d  roup-*';".  );.}
10410 0a                                               .