Fossil

Hex Artifact Content
Login

Artifact 779af89a12af7c0c228d0194fa564379ec77ac76:


0000: 23 69 66 64 65 66 20 46 4f 53 53 49 4c 5f 45 4e  #ifdef FOSSIL_EN
0010: 41 42 4c 45 5f 4a 53 4f 4e 0a 2f 2a 0a 2a 2a 20  ABLE_JSON./*.** 
0020: 43 6f 70 79 72 69 67 68 74 20 28 63 29 20 32 30  Copyright (c) 20
0030: 31 31 20 44 2e 20 52 69 63 68 61 72 64 20 48 69  11 D. Richard Hi
0040: 70 70 0a 2a 2a 0a 2a 2a 20 54 68 69 73 20 70 72  pp.**.** This pr
0050: 6f 67 72 61 6d 20 69 73 20 66 72 65 65 20 73 6f  ogram is free so
0060: 66 74 77 61 72 65 3b 20 79 6f 75 20 63 61 6e 20  ftware; you can 
0070: 72 65 64 69 73 74 72 69 62 75 74 65 20 69 74 20  redistribute it 
0080: 61 6e 64 2f 6f 72 0a 2a 2a 20 6d 6f 64 69 66 79  and/or.** modify
0090: 20 69 74 20 75 6e 64 65 72 20 74 68 65 20 74 65   it under the te
00a0: 72 6d 73 20 6f 66 20 74 68 65 20 53 69 6d 70 6c  rms of the Simpl
00b0: 69 66 69 65 64 20 42 53 44 20 4c 69 63 65 6e 73  ified BSD Licens
00c0: 65 20 28 61 6c 73 6f 0a 2a 2a 20 6b 6e 6f 77 6e  e (also.** known
00d0: 20 61 73 20 74 68 65 20 22 32 2d 43 6c 61 75 73   as the "2-Claus
00e0: 65 20 4c 69 63 65 6e 73 65 22 20 6f 72 20 22 46  e License" or "F
00f0: 72 65 65 42 53 44 20 4c 69 63 65 6e 73 65 22 2e  reeBSD License".
0100: 29 0a 2a 2a 0a 2a 2a 20 54 68 69 73 20 70 72 6f  ).**.** This pro
0110: 67 72 61 6d 20 69 73 20 64 69 73 74 72 69 62 75  gram is distribu
0120: 74 65 64 20 69 6e 20 74 68 65 20 68 6f 70 65 20  ted in the hope 
0130: 74 68 61 74 20 69 74 20 77 69 6c 6c 20 62 65 20  that it will be 
0140: 75 73 65 66 75 6c 2c 0a 2a 2a 20 62 75 74 20 77  useful,.** but w
0150: 69 74 68 6f 75 74 20 61 6e 79 20 77 61 72 72 61  ithout any warra
0160: 6e 74 79 3b 20 77 69 74 68 6f 75 74 20 65 76 65  nty; without eve
0170: 6e 20 74 68 65 20 69 6d 70 6c 69 65 64 20 77 61  n the implied wa
0180: 72 72 61 6e 74 79 20 6f 66 0a 2a 2a 20 6d 65 72  rranty of.** mer
0190: 63 68 61 6e 74 61 62 69 6c 69 74 79 20 6f 72 20  chantability or 
01a0: 66 69 74 6e 65 73 73 20 66 6f 72 20 61 20 70 61  fitness for a pa
01b0: 72 74 69 63 75 6c 61 72 20 70 75 72 70 6f 73 65  rticular purpose
01c0: 2e 0a 2a 2a 0a 2a 2a 20 41 75 74 68 6f 72 20 63  ..**.** Author c
01d0: 6f 6e 74 61 63 74 20 69 6e 66 6f 72 6d 61 74 69  ontact informati
01e0: 6f 6e 3a 0a 2a 2a 20 20 20 64 72 68 40 68 77 61  on:.**   drh@hwa
01f0: 63 69 2e 63 6f 6d 0a 2a 2a 20 20 20 68 74 74 70  ci.com.**   http
0200: 3a 2f 2f 77 77 77 2e 68 77 61 63 69 2e 63 6f 6d  ://www.hwaci.com
0210: 2f 64 72 68 2f 0a 2a 2a 0a 2a 2f 0a 23 69 6e 63  /drh/.**.*/.#inc
0220: 6c 75 64 65 20 22 56 45 52 53 49 4f 4e 2e 68 22  lude "VERSION.h"
0230: 0a 23 69 6e 63 6c 75 64 65 20 22 63 6f 6e 66 69  .#include "confi
0240: 67 2e 68 22 0a 23 69 6e 63 6c 75 64 65 20 22 6a  g.h".#include "j
0250: 73 6f 6e 5f 75 73 65 72 2e 68 22 0a 0a 23 69 66  son_user.h"..#if
0260: 20 49 4e 54 45 52 46 41 43 45 0a 23 69 6e 63 6c   INTERFACE.#incl
0270: 75 64 65 20 22 6a 73 6f 6e 5f 64 65 74 61 69 6c  ude "json_detail
0280: 2e 68 22 0a 23 65 6e 64 69 66 0a 0a 73 74 61 74  .h".#endif..stat
0290: 69 63 20 63 73 6f 6e 5f 76 61 6c 75 65 20 2a 20  ic cson_value * 
02a0: 6a 73 6f 6e 5f 75 73 65 72 5f 67 65 74 28 29 3b  json_user_get();
02b0: 0a 73 74 61 74 69 63 20 63 73 6f 6e 5f 76 61 6c  .static cson_val
02c0: 75 65 20 2a 20 6a 73 6f 6e 5f 75 73 65 72 5f 6c  ue * json_user_l
02d0: 69 73 74 28 29 3b 0a 73 74 61 74 69 63 20 63 73  ist();.static cs
02e0: 6f 6e 5f 76 61 6c 75 65 20 2a 20 6a 73 6f 6e 5f  on_value * json_
02f0: 75 73 65 72 5f 73 61 76 65 28 29 3b 0a 0a 2f 2a  user_save();../*
0300: 0a 2a 2a 20 4d 61 70 70 69 6e 67 20 6f 66 20 2f  .** Mapping of /
0310: 6a 73 6f 6e 2f 75 73 65 72 2f 58 58 58 20 63 6f  json/user/XXX co
0320: 6d 6d 61 6e 64 73 2f 70 61 74 68 73 20 74 6f 20  mmands/paths to 
0330: 63 61 6c 6c 62 61 63 6b 73 2e 0a 2a 2f 0a 73 74  callbacks..*/.st
0340: 61 74 69 63 20 63 6f 6e 73 74 20 4a 73 6f 6e 50  atic const JsonP
0350: 61 67 65 44 65 66 20 4a 73 6f 6e 50 61 67 65 44  ageDef JsonPageD
0360: 65 66 73 5f 55 73 65 72 5b 5d 20 3d 20 7b 0a 7b  efs_User[] = {.{
0370: 22 73 61 76 65 22 2c 20 6a 73 6f 6e 5f 75 73 65  "save", json_use
0380: 72 5f 73 61 76 65 2c 20 30 7d 2c 0a 7b 22 67 65  r_save, 0},.{"ge
0390: 74 22 2c 20 6a 73 6f 6e 5f 75 73 65 72 5f 67 65  t", json_user_ge
03a0: 74 2c 20 30 7d 2c 0a 7b 22 6c 69 73 74 22 2c 20  t, 0},.{"list", 
03b0: 6a 73 6f 6e 5f 75 73 65 72 5f 6c 69 73 74 2c 20  json_user_list, 
03c0: 30 7d 2c 0a 2f 2a 20 4c 61 73 74 20 65 6e 74 72  0},./* Last entr
03d0: 79 20 4d 55 53 54 20 68 61 76 65 20 61 20 4e 55  y MUST have a NU
03e0: 4c 4c 20 6e 61 6d 65 2e 20 2a 2f 0a 7b 4e 55 4c  LL name. */.{NUL
03f0: 4c 2c 4e 55 4c 4c 2c 30 7d 0a 7d 3b 0a 0a 0a 2f  L,NULL,0}.};.../
0400: 2a 0a 2a 2a 20 49 6d 70 6c 65 6d 65 6e 74 73 20  *.** Implements 
0410: 74 68 65 20 2f 6a 73 6f 6e 2f 75 73 65 72 20 66  the /json/user f
0420: 61 6d 69 6c 79 20 6f 66 20 70 61 67 65 73 2f 63  amily of pages/c
0430: 6f 6d 6d 61 6e 64 73 2e 0a 2a 2a 0a 2a 2f 0a 63  ommands..**.*/.c
0440: 73 6f 6e 5f 76 61 6c 75 65 20 2a 20 6a 73 6f 6e  son_value * json
0450: 5f 70 61 67 65 5f 75 73 65 72 28 29 7b 0a 20 20  _page_user(){.  
0460: 72 65 74 75 72 6e 20 6a 73 6f 6e 5f 70 61 67 65  return json_page
0470: 5f 64 69 73 70 61 74 63 68 5f 68 65 6c 70 65 72  _dispatch_helper
0480: 28 26 4a 73 6f 6e 50 61 67 65 44 65 66 73 5f 55  (&JsonPageDefs_U
0490: 73 65 72 5b 30 5d 29 3b 0a 7d 0a 0a 0a 2f 2a 0a  ser[0]);.}.../*.
04a0: 2a 2a 20 49 6d 70 6c 20 6f 66 20 2f 6a 73 6f 6e  ** Impl of /json
04b0: 2f 75 73 65 72 2f 6c 69 73 74 2e 20 52 65 71 75  /user/list. Requ
04c0: 69 72 65 73 20 61 64 6d 69 6e 2f 73 65 74 75 70  ires admin/setup
04d0: 20 72 69 67 68 74 73 2e 0a 2a 2f 0a 73 74 61 74   rights..*/.stat
04e0: 69 63 20 63 73 6f 6e 5f 76 61 6c 75 65 20 2a 20  ic cson_value * 
04f0: 6a 73 6f 6e 5f 75 73 65 72 5f 6c 69 73 74 28 29  json_user_list()
0500: 7b 0a 20 20 63 73 6f 6e 5f 76 61 6c 75 65 20 2a  {.  cson_value *
0510: 20 70 61 79 56 20 3d 20 4e 55 4c 4c 3b 0a 20 20   payV = NULL;.  
0520: 53 74 6d 74 20 71 3b 0a 20 20 69 66 28 21 67 2e  Stmt q;.  if(!g.
0530: 70 65 72 6d 2e 41 64 6d 69 6e 20 26 26 20 21 67  perm.Admin && !g
0540: 2e 70 65 72 6d 2e 53 65 74 75 70 29 7b 0a 20 20  .perm.Setup){.  
0550: 20 20 6a 73 6f 6e 5f 73 65 74 5f 65 72 72 28 46    json_set_err(F
0560: 53 4c 5f 4a 53 4f 4e 5f 45 5f 44 45 4e 49 45 44  SL_JSON_E_DENIED
0570: 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,.              
0580: 20 20 20 22 52 65 71 75 69 72 65 73 20 27 61 27     "Requires 'a'
0590: 20 6f 72 20 27 73 27 20 70 72 69 76 69 6c 65 67   or 's' privileg
05a0: 65 73 2e 22 29 3b 0a 20 20 20 20 72 65 74 75 72  es.");.    retur
05b0: 6e 20 4e 55 4c 4c 3b 0a 20 20 7d 0a 20 20 64 62  n NULL;.  }.  db
05c0: 5f 70 72 65 70 61 72 65 28 26 71 2c 22 53 45 4c  _prepare(&q,"SEL
05d0: 45 43 54 20 75 69 64 20 41 53 20 75 69 64 2c 22  ECT uid AS uid,"
05e0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 22 20  .             " 
05f0: 6c 6f 67 69 6e 20 41 53 20 6e 61 6d 65 2c 22 0a  login AS name,".
0600: 20 20 20 20 20 20 20 20 20 20 20 20 20 22 20 63               " c
0610: 61 70 20 41 53 20 63 61 70 61 62 69 6c 69 74 69  ap AS capabiliti
0620: 65 73 2c 22 0a 20 20 20 20 20 20 20 20 20 20 20  es,".           
0630: 20 20 22 20 69 6e 66 6f 20 41 53 20 69 6e 66 6f    " info AS info
0640: 2c 22 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ,".             
0650: 22 20 6d 74 69 6d 65 20 41 53 20 74 69 6d 65 73  " mtime AS times
0660: 74 61 6d 70 22 0a 20 20 20 20 20 20 20 20 20 20  tamp".          
0670: 20 20 20 22 20 46 52 4f 4d 20 75 73 65 72 20 4f     " FROM user O
0680: 52 44 45 52 20 42 59 20 6c 6f 67 69 6e 22 29 3b  RDER BY login");
0690: 0a 20 20 70 61 79 56 20 3d 20 6a 73 6f 6e 5f 73  .  payV = json_s
06a0: 74 6d 74 5f 74 6f 5f 61 72 72 61 79 5f 6f 66 5f  tmt_to_array_of_
06b0: 6f 62 6a 28 26 71 2c 20 4e 55 4c 4c 29 3b 0a 20  obj(&q, NULL);. 
06c0: 20 64 62 5f 66 69 6e 61 6c 69 7a 65 28 26 71 29   db_finalize(&q)
06d0: 3b 0a 20 20 69 66 28 4e 55 4c 4c 20 3d 3d 20 70  ;.  if(NULL == p
06e0: 61 79 56 29 7b 0a 20 20 20 20 6a 73 6f 6e 5f 73  ayV){.    json_s
06f0: 65 74 5f 65 72 72 28 46 53 4c 5f 4a 53 4f 4e 5f  et_err(FSL_JSON_
0700: 45 5f 55 4e 4b 4e 4f 57 4e 2c 0a 20 20 20 20 20  E_UNKNOWN,.     
0710: 20 20 20 20 20 20 20 20 20 20 20 20 22 43 6f 75              "Cou
0720: 6c 64 20 6e 6f 74 20 63 6f 6e 76 65 72 74 20 75  ld not convert u
0730: 73 65 72 20 6c 69 73 74 20 74 6f 20 4a 53 4f 4e  ser list to JSON
0740: 2e 22 29 3b 0a 20 20 7d 0a 20 20 72 65 74 75 72  .");.  }.  retur
0750: 6e 20 70 61 79 56 3b 0a 7d 0a 0a 2f 2a 0a 2a 2a  n payV;.}../*.**
0760: 20 43 72 65 61 74 65 73 20 61 20 6e 65 77 20 4a   Creates a new J
0770: 53 4f 4e 20 4f 62 6a 65 63 74 20 62 61 73 65 64  SON Object based
0780: 20 6f 6e 20 74 68 65 20 64 62 20 73 74 61 74 65   on the db state
0790: 20 6f 66 0a 2a 2a 20 74 68 65 20 67 69 76 65 6e   of.** the given
07a0: 20 75 73 65 72 20 6e 61 6d 65 2e 20 4f 6e 20 65   user name. On e
07b0: 72 72 6f 72 20 28 6e 6f 20 72 65 63 6f 72 64 20  rror (no record 
07c0: 66 6f 75 6e 64 29 0a 2a 2a 20 69 74 20 72 65 74  found).** it ret
07d0: 75 72 6e 73 20 4e 55 4c 4c 2c 20 65 6c 73 65 20  urns NULL, else 
07e0: 74 68 65 20 63 61 6c 6c 65 72 20 6f 77 6e 73 20  the caller owns 
07f0: 74 68 65 20 72 65 74 75 72 6e 65 64 0a 2a 2a 20  the returned.** 
0800: 6f 62 6a 65 63 74 2e 0a 2a 2f 0a 73 74 61 74 69  object..*/.stati
0810: 63 20 63 73 6f 6e 5f 76 61 6c 75 65 20 2a 20 6a  c cson_value * j
0820: 73 6f 6e 5f 6c 6f 61 64 5f 75 73 65 72 5f 62 79  son_load_user_by
0830: 5f 6e 61 6d 65 28 63 68 61 72 20 63 6f 6e 73 74  _name(char const
0840: 20 2a 20 7a 4e 61 6d 65 29 7b 0a 20 20 63 73 6f   * zName){.  cso
0850: 6e 5f 76 61 6c 75 65 20 2a 20 75 20 3d 20 4e 55  n_value * u = NU
0860: 4c 4c 3b 0a 20 20 53 74 6d 74 20 71 3b 0a 20 20  LL;.  Stmt q;.  
0870: 64 62 5f 70 72 65 70 61 72 65 28 26 71 2c 22 53  db_prepare(&q,"S
0880: 45 4c 45 43 54 20 75 69 64 20 41 53 20 75 69 64  ELECT uid AS uid
0890: 2c 22 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ,".             
08a0: 22 20 6c 6f 67 69 6e 20 41 53 20 6e 61 6d 65 2c  " login AS name,
08b0: 22 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 22  ".             "
08c0: 20 63 61 70 20 41 53 20 63 61 70 61 62 69 6c 69   cap AS capabili
08d0: 74 69 65 73 2c 22 0a 20 20 20 20 20 20 20 20 20  ties,".         
08e0: 20 20 20 20 22 20 69 6e 66 6f 20 41 53 20 69 6e      " info AS in
08f0: 66 6f 2c 22 0a 20 20 20 20 20 20 20 20 20 20 20  fo,".           
0900: 20 20 22 20 6d 74 69 6d 65 20 41 53 20 74 69 6d    " mtime AS tim
0910: 65 73 74 61 6d 70 22 0a 20 20 20 20 20 20 20 20  estamp".        
0920: 20 20 20 20 20 22 20 46 52 4f 4d 20 75 73 65 72       " FROM user
0930: 22 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 22  ".             "
0940: 20 57 48 45 52 45 20 6c 6f 67 69 6e 3d 25 51 22   WHERE login=%Q"
0950: 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 7a  ,.             z
0960: 4e 61 6d 65 29 3b 0a 20 20 69 66 28 20 28 53 51  Name);.  if( (SQ
0970: 4c 49 54 45 5f 52 4f 57 20 3d 3d 20 64 62 5f 73  LITE_ROW == db_s
0980: 74 65 70 28 26 71 29 29 20 29 7b 0a 20 20 20 20  tep(&q)) ){.    
0990: 75 20 3d 20 63 73 6f 6e 5f 73 71 6c 69 74 65 33  u = cson_sqlite3
09a0: 5f 72 6f 77 5f 74 6f 5f 6f 62 6a 65 63 74 28 71  _row_to_object(q
09b0: 2e 70 53 74 6d 74 29 3b 0a 20 20 7d 0a 20 20 64  .pStmt);.  }.  d
09c0: 62 5f 66 69 6e 61 6c 69 7a 65 28 26 71 29 3b 0a  b_finalize(&q);.
09d0: 20 20 72 65 74 75 72 6e 20 75 3b 0a 7d 0a 0a 2f    return u;.}../
09e0: 2a 0a 2a 2a 20 49 64 65 6e 74 69 63 61 6c 20 74  *.** Identical t
09f0: 6f 20 6a 73 6f 6e 5f 6c 6f 61 64 5f 75 73 65 72  o json_load_user
0a00: 5f 62 79 5f 6e 61 6d 65 28 29 2c 20 62 75 74 20  _by_name(), but 
0a10: 65 78 70 65 63 74 73 20 61 20 75 73 65 72 20 49  expects a user I
0a20: 44 2e 20 20 52 65 74 75 72 6e 73 0a 2a 2a 20 4e  D.  Returns.** N
0a30: 55 4c 4c 20 69 66 20 6e 6f 20 75 73 65 72 20 66  ULL if no user f
0a40: 6f 75 6e 64 20 77 69 74 68 20 74 68 61 74 20 49  ound with that I
0a50: 44 2e 0a 2a 2f 0a 73 74 61 74 69 63 20 63 73 6f  D..*/.static cso
0a60: 6e 5f 76 61 6c 75 65 20 2a 20 6a 73 6f 6e 5f 6c  n_value * json_l
0a70: 6f 61 64 5f 75 73 65 72 5f 62 79 5f 69 64 28 69  oad_user_by_id(i
0a80: 6e 74 20 75 69 64 29 7b 0a 20 20 63 73 6f 6e 5f  nt uid){.  cson_
0a90: 76 61 6c 75 65 20 2a 20 75 20 3d 20 4e 55 4c 4c  value * u = NULL
0aa0: 3b 0a 20 20 53 74 6d 74 20 71 3b 0a 20 20 64 62  ;.  Stmt q;.  db
0ab0: 5f 70 72 65 70 61 72 65 28 26 71 2c 22 53 45 4c  _prepare(&q,"SEL
0ac0: 45 43 54 20 75 69 64 20 41 53 20 75 69 64 2c 22  ECT uid AS uid,"
0ad0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 22 20  .             " 
0ae0: 6c 6f 67 69 6e 20 41 53 20 6e 61 6d 65 2c 22 0a  login AS name,".
0af0: 20 20 20 20 20 20 20 20 20 20 20 20 20 22 20 63               " c
0b00: 61 70 20 41 53 20 63 61 70 61 62 69 6c 69 74 69  ap AS capabiliti
0b10: 65 73 2c 22 0a 20 20 20 20 20 20 20 20 20 20 20  es,".           
0b20: 20 20 22 20 69 6e 66 6f 20 41 53 20 69 6e 66 6f    " info AS info
0b30: 2c 22 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  ,".             
0b40: 22 20 6d 74 69 6d 65 20 41 53 20 74 69 6d 65 73  " mtime AS times
0b50: 74 61 6d 70 22 0a 20 20 20 20 20 20 20 20 20 20  tamp".          
0b60: 20 20 20 22 20 46 52 4f 4d 20 75 73 65 72 22 0a     " FROM user".
0b70: 20 20 20 20 20 20 20 20 20 20 20 20 20 22 20 57               " W
0b80: 48 45 52 45 20 75 69 64 3d 25 64 22 2c 0a 20 20  HERE uid=%d",.  
0b90: 20 20 20 20 20 20 20 20 20 20 20 75 69 64 29 3b             uid);
0ba0: 0a 20 20 69 66 28 20 28 53 51 4c 49 54 45 5f 52  .  if( (SQLITE_R
0bb0: 4f 57 20 3d 3d 20 64 62 5f 73 74 65 70 28 26 71  OW == db_step(&q
0bc0: 29 29 20 29 7b 0a 20 20 20 20 75 20 3d 20 63 73  )) ){.    u = cs
0bd0: 6f 6e 5f 73 71 6c 69 74 65 33 5f 72 6f 77 5f 74  on_sqlite3_row_t
0be0: 6f 5f 6f 62 6a 65 63 74 28 71 2e 70 53 74 6d 74  o_object(q.pStmt
0bf0: 29 3b 0a 20 20 7d 0a 20 20 64 62 5f 66 69 6e 61  );.  }.  db_fina
0c00: 6c 69 7a 65 28 26 71 29 3b 0a 20 20 72 65 74 75  lize(&q);.  retu
0c10: 72 6e 20 75 3b 0a 7d 0a 0a 0a 2f 2a 0a 2a 2a 20  rn u;.}.../*.** 
0c20: 49 6d 70 6c 20 6f 66 20 2f 6a 73 6f 6e 2f 75 73  Impl of /json/us
0c30: 65 72 2f 67 65 74 2e 20 52 65 71 75 69 72 65 73  er/get. Requires
0c40: 20 61 64 6d 69 6e 20 6f 72 20 73 65 74 75 70 20   admin or setup 
0c50: 72 69 67 68 74 73 2e 0a 2a 2f 0a 73 74 61 74 69  rights..*/.stati
0c60: 63 20 63 73 6f 6e 5f 76 61 6c 75 65 20 2a 20 6a  c cson_value * j
0c70: 73 6f 6e 5f 75 73 65 72 5f 67 65 74 28 29 7b 0a  son_user_get(){.
0c80: 20 20 63 73 6f 6e 5f 76 61 6c 75 65 20 2a 20 70    cson_value * p
0c90: 61 79 56 20 3d 20 4e 55 4c 4c 3b 0a 20 20 63 68  ayV = NULL;.  ch
0ca0: 61 72 20 63 6f 6e 73 74 20 2a 20 70 55 73 65 72  ar const * pUser
0cb0: 20 3d 20 4e 55 4c 4c 3b 0a 20 20 69 66 28 21 67   = NULL;.  if(!g
0cc0: 2e 70 65 72 6d 2e 41 64 6d 69 6e 20 26 26 20 21  .perm.Admin && !
0cd0: 67 2e 70 65 72 6d 2e 53 65 74 75 70 29 7b 0a 20  g.perm.Setup){. 
0ce0: 20 20 20 6a 73 6f 6e 5f 73 65 74 5f 65 72 72 28     json_set_err(
0cf0: 46 53 4c 5f 4a 53 4f 4e 5f 45 5f 44 45 4e 49 45  FSL_JSON_E_DENIE
0d00: 44 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  D,.             
0d10: 20 20 20 20 22 52 65 71 75 69 72 65 73 20 27 61      "Requires 'a
0d20: 27 20 6f 72 20 27 73 27 20 70 72 69 76 69 6c 65  ' or 's' privile
0d30: 67 65 73 2e 22 29 3b 0a 20 20 20 20 72 65 74 75  ges.");.    retu
0d40: 72 6e 20 4e 55 4c 4c 3b 0a 20 20 7d 0a 20 20 70  rn NULL;.  }.  p
0d50: 55 73 65 72 20 3d 20 6a 73 6f 6e 5f 66 69 6e 64  User = json_find
0d60: 5f 6f 70 74 69 6f 6e 5f 63 73 74 72 32 28 22 6e  _option_cstr2("n
0d70: 61 6d 65 22 2c 20 4e 55 4c 4c 2c 20 4e 55 4c 4c  ame", NULL, NULL
0d80: 2c 20 67 2e 6a 73 6f 6e 2e 64 69 73 70 61 74 63  , g.json.dispatc
0d90: 68 44 65 70 74 68 2b 31 29 3b 0a 20 20 69 66 28  hDepth+1);.  if(
0da0: 21 70 55 73 65 72 20 7c 7c 20 21 2a 70 55 73 65  !pUser || !*pUse
0db0: 72 29 7b 0a 20 20 20 20 6a 73 6f 6e 5f 73 65 74  r){.    json_set
0dc0: 5f 65 72 72 28 46 53 4c 5f 4a 53 4f 4e 5f 45 5f  _err(FSL_JSON_E_
0dd0: 4d 49 53 53 49 4e 47 5f 41 52 47 53 2c 22 4d 69  MISSING_ARGS,"Mi
0de0: 73 73 69 6e 67 20 27 6e 61 6d 65 27 20 70 72 6f  ssing 'name' pro
0df0: 70 65 72 74 79 2e 22 29 3b 0a 20 20 20 20 72 65  perty.");.    re
0e00: 74 75 72 6e 20 4e 55 4c 4c 3b 0a 20 20 7d 0a 20  turn NULL;.  }. 
0e10: 20 70 61 79 56 20 3d 20 6a 73 6f 6e 5f 6c 6f 61   payV = json_loa
0e20: 64 5f 75 73 65 72 5f 62 79 5f 6e 61 6d 65 28 70  d_user_by_name(p
0e30: 55 73 65 72 29 3b 0a 20 20 69 66 28 21 70 61 79  User);.  if(!pay
0e40: 56 29 7b 0a 20 20 20 20 6a 73 6f 6e 5f 73 65 74  V){.    json_set
0e50: 5f 65 72 72 28 46 53 4c 5f 4a 53 4f 4e 5f 45 5f  _err(FSL_JSON_E_
0e60: 52 45 53 4f 55 52 43 45 5f 4e 4f 54 5f 46 4f 55  RESOURCE_NOT_FOU
0e70: 4e 44 2c 22 55 73 65 72 20 6e 6f 74 20 66 6f 75  ND,"User not fou
0e80: 6e 64 2e 22 29 3b 0a 20 20 7d 0a 20 20 72 65 74  nd.");.  }.  ret
0e90: 75 72 6e 20 70 61 79 56 3b 0a 7d 0a 0a 2f 2a 0a  urn payV;.}../*.
0ea0: 2a 2a 20 45 78 70 65 63 74 73 20 70 55 73 65 72  ** Expects pUser
0eb0: 20 74 6f 20 63 6f 6e 74 61 69 6e 20 66 6f 73 73   to contain foss
0ec0: 69 6c 20 75 73 65 72 20 66 69 65 6c 64 73 20 69  il user fields i
0ed0: 6e 20 4a 53 4f 4e 20 66 6f 72 6d 3a 20 6e 61 6d  n JSON form: nam
0ee0: 65 2c 0a 2a 2a 20 75 69 64 2c 20 69 6e 66 6f 2c  e,.** uid, info,
0ef0: 20 63 61 70 61 62 69 6c 69 74 69 65 73 2c 20 70   capabilities, p
0f00: 61 73 73 77 6f 72 64 2e 0a 2a 2a 0a 2a 2a 20 41  assword..**.** A
0f10: 74 20 6c 65 61 73 74 20 6f 6e 65 20 6f 66 20 28  t least one of (
0f20: 6e 61 6d 65 2c 20 75 69 64 29 20 6d 75 73 74 20  name, uid) must 
0f30: 62 65 20 69 6e 63 6c 75 64 65 64 2e 20 41 6c 6c  be included. All
0f40: 20 6f 74 68 65 72 73 20 61 72 65 0a 2a 2a 20 6f   others are.** o
0f50: 70 74 69 6f 6e 61 6c 20 61 6e 64 20 74 68 65 69  ptional and thei
0f60: 72 20 64 62 20 66 69 65 6c 64 73 20 77 69 6c 6c  r db fields will
0f70: 20 6e 6f 74 20 62 65 20 75 70 64 61 74 65 64 20   not be updated 
0f80: 69 66 20 74 68 6f 73 65 20 66 69 65 6c 64 73 0a  if those fields.
0f90: 2a 2a 20 61 72 65 20 6e 6f 74 20 69 6e 63 6c 75  ** are not inclu
0fa0: 64 65 64 20 69 6e 20 70 55 73 65 72 2e 0a 2a 2a  ded in pUser..**
0fb0: 0a 2a 2a 20 49 66 20 75 69 64 20 69 73 20 73 70  .** If uid is sp
0fc0: 65 63 69 66 69 65 64 20 74 68 65 6e 20 6e 61 6d  ecified then nam
0fd0: 65 20 6d 61 79 20 72 65 66 65 72 20 74 6f 20 61  e may refer to a
0fe0: 20 5f 6e 65 77 5f 20 6e 61 6d 65 0a 2a 2a 20 66   _new_ name.** f
0ff0: 6f 72 20 61 20 75 73 65 72 2c 20 6f 74 68 65 72  or a user, other
1000: 77 69 73 65 20 74 68 65 20 6e 61 6d 65 20 6d 75  wise the name mu
1010: 73 74 20 72 65 66 65 72 20 74 6f 20 61 6e 20 65  st refer to an e
1020: 78 69 73 74 69 6e 67 20 75 73 65 72 2e 0a 2a 2a  xisting user..**
1030: 20 49 66 20 75 69 64 3d 2d 31 20 74 68 65 6e 20   If uid=-1 then 
1040: 74 68 65 20 6e 61 6d 65 20 6d 75 73 74 20 62 65  the name must be
1050: 20 73 70 65 63 69 66 69 65 64 20 61 6e 64 20 61   specified and a
1060: 20 6e 65 77 20 75 73 65 72 20 69 73 0a 2a 2a 20   new user is.** 
1070: 63 72 65 61 74 65 64 20 28 66 61 69 6c 73 20 69  created (fails i
1080: 66 20 6f 6e 65 20 61 6c 72 65 61 64 79 20 65 78  f one already ex
1090: 69 73 74 73 29 2e 0a 2a 2a 0a 2a 2a 20 49 66 20  ists)..**.** If 
10a0: 75 69 64 20 69 73 20 6e 6f 74 20 73 65 74 2c 20  uid is not set, 
10b0: 74 68 69 73 20 66 75 6e 63 74 69 6f 6e 20 6d 69  this function mi
10c0: 67 68 74 20 6d 6f 64 69 66 79 20 70 55 73 65 72  ght modify pUser
10d0: 20 74 6f 20 63 6f 6e 74 61 69 6e 20 74 68 65 0a   to contain the.
10e0: 2a 2a 20 64 62 2d 66 6f 75 6e 64 20 28 6f 72 20  ** db-found (or 
10f0: 69 6e 73 65 72 74 65 64 29 20 75 73 65 72 20 49  inserted) user I
1100: 44 2e 0a 2a 2a 0a 2a 2a 20 4f 6e 20 65 72 72 6f  D..**.** On erro
1110: 72 20 67 2e 6a 73 6f 6e 27 73 20 65 72 72 6f 72  r g.json's error
1120: 20 73 74 61 74 65 20 69 73 20 73 65 74 20 61 6e   state is set an
1130: 64 20 6f 6e 65 20 6f 66 20 74 68 65 20 46 53 4c  d one of the FSL
1140: 5f 4a 53 4f 4e 5f 45 5f 78 78 78 0a 2a 2a 20 76  _JSON_E_xxx.** v
1150: 61 6c 75 65 73 20 66 72 6f 6d 20 46 6f 73 73 69  alues from Fossi
1160: 6c 4a 73 6f 6e 43 6f 64 65 73 20 69 73 20 72 65  lJsonCodes is re
1170: 74 75 72 6e 65 64 2e 0a 2a 2a 0a 2a 2a 20 4f 6e  turned..**.** On
1180: 20 73 75 63 63 65 73 73 20 74 68 65 20 64 62 20   success the db 
1190: 72 65 63 6f 72 64 20 66 6f 72 20 74 68 65 20 67  record for the g
11a0: 69 76 65 6e 20 75 73 65 72 20 69 73 20 75 70 64  iven user is upd
11b0: 61 74 65 64 2e 0a 2a 2a 0a 2a 2a 20 52 65 71 75  ated..**.** Requ
11c0: 69 72 65 73 20 65 69 74 68 65 72 20 41 64 6d 69  ires either Admi
11d0: 6e 2c 20 53 65 74 75 70 2c 20 6f 72 20 50 61 73  n, Setup, or Pas
11e0: 73 77 6f 72 64 20 61 63 63 65 73 73 2e 20 4e 6f  sword access. No
11f0: 6e 2d 61 64 6d 69 6e 2f 73 65 74 75 70 0a 2a 2a  n-admin/setup.**
1200: 20 75 73 65 72 73 20 63 61 6e 20 6f 6e 6c 79 20   users can only 
1210: 63 68 61 6e 67 65 20 74 68 65 69 72 20 6f 77 6e  change their own
1220: 20 69 6e 66 6f 72 6d 61 74 69 6f 6e 2e 20 4e 6f   information. No
1230: 6e 2d 73 65 74 75 70 20 75 73 65 72 73 20 6d 61  n-setup users ma
1240: 79 0a 2a 2a 20 6e 6f 74 20 6d 6f 64 69 66 79 20  y.** not modify 
1250: 74 68 65 20 27 73 27 20 70 65 72 6d 69 73 73 69  the 's' permissi
1260: 6f 6e 2e 20 41 64 6d 69 6e 20 75 73 65 72 73 20  on. Admin users 
1270: 77 69 74 68 6f 75 74 20 73 65 74 75 70 0a 2a 2a  without setup.**
1280: 20 70 65 72 6d 69 73 73 69 6f 6e 73 20 6d 61 79   permissions may
1290: 20 6e 6f 74 20 65 64 69 74 20 61 6e 79 20 6f 74   not edit any ot
12a0: 68 65 72 20 75 73 65 72 20 77 68 6f 20 68 61 73  her user who has
12b0: 20 74 68 65 20 27 73 27 20 70 65 72 6d 69 73 73   the 's' permiss
12c0: 69 6f 6e 2e 0a 2a 2a 0a 2a 2f 0a 69 6e 74 20 6a  ion..**.*/.int j
12d0: 73 6f 6e 5f 75 73 65 72 5f 75 70 64 61 74 65 5f  son_user_update_
12e0: 66 72 6f 6d 5f 6a 73 6f 6e 28 20 63 73 6f 6e 5f  from_json( cson_
12f0: 6f 62 6a 65 63 74 20 2a 20 70 55 73 65 72 20 29  object * pUser )
1300: 7b 0a 23 64 65 66 69 6e 65 20 43 53 54 52 28 58  {.#define CSTR(X
1310: 29 20 63 73 6f 6e 5f 73 74 72 69 6e 67 5f 63 73  ) cson_string_cs
1320: 74 72 28 63 73 6f 6e 5f 76 61 6c 75 65 5f 67 65  tr(cson_value_ge
1330: 74 5f 73 74 72 69 6e 67 28 20 63 73 6f 6e 5f 6f  t_string( cson_o
1340: 62 6a 65 63 74 5f 67 65 74 28 70 55 73 65 72 2c  bject_get(pUser,
1350: 20 58 20 29 20 29 29 0a 20 20 63 68 61 72 20 63   X ) )).  char c
1360: 6f 6e 73 74 20 2a 20 7a 4e 61 6d 65 20 3d 20 43  onst * zName = C
1370: 53 54 52 28 22 6e 61 6d 65 22 29 3b 0a 20 20 63  STR("name");.  c
1380: 68 61 72 20 63 6f 6e 73 74 20 2a 20 7a 4e 61 6d  har const * zNam
1390: 65 4e 65 77 20 3d 20 7a 4e 61 6d 65 3b 0a 20 20  eNew = zName;.  
13a0: 63 68 61 72 20 2a 20 7a 4e 61 6d 65 46 72 65 65  char * zNameFree
13b0: 20 3d 20 4e 55 4c 4c 3b 0a 20 20 63 68 61 72 20   = NULL;.  char 
13c0: 63 6f 6e 73 74 20 2a 20 7a 49 6e 66 6f 20 3d 20  const * zInfo = 
13d0: 43 53 54 52 28 22 69 6e 66 6f 22 29 3b 0a 20 20  CSTR("info");.  
13e0: 63 68 61 72 20 63 6f 6e 73 74 20 2a 20 7a 43 61  char const * zCa
13f0: 70 20 3d 20 43 53 54 52 28 22 63 61 70 61 62 69  p = CSTR("capabi
1400: 6c 69 74 69 65 73 22 29 3b 0a 20 20 63 68 61 72  lities");.  char
1410: 20 63 6f 6e 73 74 20 2a 20 7a 50 57 20 3d 20 43   const * zPW = C
1420: 53 54 52 28 22 70 61 73 73 77 6f 72 64 22 29 3b  STR("password");
1430: 0a 20 20 63 73 6f 6e 5f 76 61 6c 75 65 20 63 6f  .  cson_value co
1440: 6e 73 74 20 2a 20 66 6f 72 63 65 4c 6f 67 6f 75  nst * forceLogou
1450: 74 20 3d 20 63 73 6f 6e 5f 6f 62 6a 65 63 74 5f  t = cson_object_
1460: 67 65 74 28 70 55 73 65 72 2c 20 22 66 6f 72 63  get(pUser, "forc
1470: 65 4c 6f 67 6f 75 74 22 29 3b 0a 20 20 69 6e 74  eLogout");.  int
1480: 20 67 6f 74 46 69 65 6c 64 73 20 3d 20 30 3b 0a   gotFields = 0;.
1490: 23 75 6e 64 65 66 20 43 53 54 52 0a 20 20 63 73  #undef CSTR.  cs
14a0: 6f 6e 5f 69 6e 74 5f 74 20 75 69 64 20 3d 20 63  on_int_t uid = c
14b0: 73 6f 6e 5f 76 61 6c 75 65 5f 67 65 74 5f 69 6e  son_value_get_in
14c0: 74 65 67 65 72 28 20 63 73 6f 6e 5f 6f 62 6a 65  teger( cson_obje
14d0: 63 74 5f 67 65 74 28 70 55 73 65 72 2c 20 22 75  ct_get(pUser, "u
14e0: 69 64 22 29 20 29 3b 0a 20 20 63 68 61 72 20 63  id") );.  char c
14f0: 6f 6e 73 74 20 74 67 74 48 61 73 53 65 74 75 70  onst tgtHasSetup
1500: 20 3d 20 7a 43 61 70 20 26 26 20 28 4e 55 4c 4c   = zCap && (NULL
1510: 21 3d 73 74 72 63 68 72 28 7a 43 61 70 2c 20 27  !=strchr(zCap, '
1520: 73 27 29 29 3b 0a 20 20 63 68 61 72 20 74 67 74  s'));.  char tgt
1530: 48 61 64 53 65 74 75 70 20 3d 20 30 3b 0a 20 20  HadSetup = 0;.  
1540: 42 6c 6f 62 20 73 71 6c 20 3d 20 65 6d 70 74 79  Blob sql = empty
1550: 5f 62 6c 6f 62 3b 0a 20 20 53 74 6d 74 20 71 20  _blob;.  Stmt q 
1560: 3d 20 65 6d 70 74 79 5f 53 74 6d 74 3b 0a 0a 23  = empty_Stmt;..#
1570: 69 66 20 30 0a 20 20 69 66 28 21 67 2e 70 65 72  if 0.  if(!g.per
1580: 6d 2e 41 64 6d 69 6e 20 26 26 20 21 67 2e 70 65  m.Admin && !g.pe
1590: 72 6d 2e 53 65 74 75 70 20 26 26 20 21 67 2e 70  rm.Setup && !g.p
15a0: 65 72 6d 2e 50 61 73 73 77 6f 72 64 29 7b 0a 20  erm.Password){. 
15b0: 20 20 20 72 65 74 75 72 6e 20 6a 73 6f 6e 5f 73     return json_s
15c0: 65 74 5f 65 72 72 28 20 46 53 4c 5f 4a 53 4f 4e  et_err( FSL_JSON
15d0: 5f 45 5f 44 45 4e 49 45 44 2c 0a 20 20 20 20 20  _E_DENIED,.     
15e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
15f0: 20 20 20 20 22 50 61 73 73 77 6f 72 64 20 63 68      "Password ch
1600: 61 6e 67 65 20 72 65 71 75 69 72 65 73 20 27 61  ange requires 'a
1610: 27 2c 20 27 73 27 2c 20 22 0a 20 20 20 20 20 20  ', 's', ".      
1620: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1630: 20 20 20 22 6f 72 20 27 70 27 20 70 65 72 6d 69     "or 'p' permi
1640: 73 73 69 6f 6e 73 2e 22 29 3b 0a 20 20 7d 0a 23  ssions.");.  }.#
1650: 65 6e 64 69 66 0a 20 20 69 66 28 75 69 64 3c 3d  endif.  if(uid<=
1660: 30 20 26 26 20 28 21 7a 4e 61 6d 65 7c 7c 21 2a  0 && (!zName||!*
1670: 7a 4e 61 6d 65 29 29 7b 0a 20 20 20 20 72 65 74  zName)){.    ret
1680: 75 72 6e 20 6a 73 6f 6e 5f 73 65 74 5f 65 72 72  urn json_set_err
1690: 28 46 53 4c 5f 4a 53 4f 4e 5f 45 5f 4d 49 53 53  (FSL_JSON_E_MISS
16a0: 49 4e 47 5f 41 52 47 53 2c 0a 20 20 20 20 20 20  ING_ARGS,.      
16b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
16c0: 20 20 22 4f 6e 65 20 6f 66 20 27 75 69 64 27 20    "One of 'uid' 
16d0: 6f 72 20 27 6e 61 6d 65 27 20 69 73 20 72 65 71  or 'name' is req
16e0: 75 69 72 65 64 2e 22 29 3b 0a 20 20 7d 65 6c 73  uired.");.  }els
16f0: 65 20 69 66 28 75 69 64 3e 30 29 7b 0a 20 20 20  e if(uid>0){.   
1700: 20 7a 4e 61 6d 65 46 72 65 65 20 3d 20 64 62 5f   zNameFree = db_
1710: 74 65 78 74 28 4e 55 4c 4c 2c 20 22 53 45 4c 45  text(NULL, "SELE
1720: 43 54 20 6c 6f 67 69 6e 20 46 52 4f 4d 20 75 73  CT login FROM us
1730: 65 72 20 57 48 45 52 45 20 75 69 64 3d 25 64 22  er WHERE uid=%d"
1740: 2c 75 69 64 29 3b 0a 20 20 20 20 69 66 28 21 7a  ,uid);.    if(!z
1750: 4e 61 6d 65 46 72 65 65 29 7b 0a 20 20 20 20 20  NameFree){.     
1760: 20 72 65 74 75 72 6e 20 6a 73 6f 6e 5f 73 65 74   return json_set
1770: 5f 65 72 72 28 46 53 4c 5f 4a 53 4f 4e 5f 45 5f  _err(FSL_JSON_E_
1780: 52 45 53 4f 55 52 43 45 5f 4e 4f 54 5f 46 4f 55  RESOURCE_NOT_FOU
1790: 4e 44 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20  ND,.            
17a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 22 4e                "N
17b0: 6f 20 6c 6f 67 69 6e 20 66 6f 75 6e 64 20 66 6f  o login found fo
17c0: 72 20 75 69 64 20 25 64 2e 22 2c 20 75 69 64 29  r uid %d.", uid)
17d0: 3b 0a 20 20 20 20 7d 0a 20 20 20 20 7a 4e 61 6d  ;.    }.    zNam
17e0: 65 20 3d 20 7a 4e 61 6d 65 46 72 65 65 3b 0a 20  e = zNameFree;. 
17f0: 20 7d 65 6c 73 65 20 69 66 28 2d 31 3d 3d 75 69   }else if(-1==ui
1800: 64 29 7b 0a 20 20 20 20 2f 2a 20 74 72 79 20 74  d){.    /* try t
1810: 6f 20 63 72 65 61 74 65 20 61 20 6e 65 77 20 75  o create a new u
1820: 73 65 72 20 2a 2f 0a 20 20 20 20 69 66 28 21 67  ser */.    if(!g
1830: 2e 70 65 72 6d 2e 41 64 6d 69 6e 20 26 26 20 21  .perm.Admin && !
1840: 67 2e 70 65 72 6d 2e 53 65 74 75 70 29 7b 0a 20  g.perm.Setup){. 
1850: 20 20 20 20 20 6a 73 6f 6e 5f 73 65 74 5f 65 72       json_set_er
1860: 72 28 46 53 4c 5f 4a 53 4f 4e 5f 45 5f 44 45 4e  r(FSL_JSON_E_DEN
1870: 49 45 44 2c 0a 20 20 20 20 20 20 20 20 20 20 20  IED,.           
1880: 20 20 20 20 20 20 20 20 22 52 65 71 75 69 72 65          "Require
1890: 73 20 27 61 27 20 6f 72 20 27 73 27 20 70 72 69  s 'a' or 's' pri
18a0: 76 69 6c 65 67 65 73 2e 22 29 3b 0a 20 20 20 20  vileges.");.    
18b0: 20 20 67 6f 74 6f 20 65 72 72 6f 72 3b 0a 20 20    goto error;.  
18c0: 20 20 7d 65 6c 73 65 20 69 66 28 21 7a 4e 61 6d    }else if(!zNam
18d0: 65 20 7c 7c 20 21 2a 7a 4e 61 6d 65 29 7b 0a 20  e || !*zName){. 
18e0: 20 20 20 20 20 6a 73 6f 6e 5f 73 65 74 5f 65 72       json_set_er
18f0: 72 28 46 53 4c 5f 4a 53 4f 4e 5f 45 5f 4d 49 53  r(FSL_JSON_E_MIS
1900: 53 49 4e 47 5f 41 52 47 53 2c 0a 20 20 20 20 20  SING_ARGS,.     
1910: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 22 4e                "N
1920: 6f 20 6e 61 6d 65 20 73 70 65 63 69 66 69 65 64  o name specified
1930: 20 66 6f 72 20 6e 65 77 20 75 73 65 72 2e 22 29   for new user.")
1940: 3b 0a 20 20 20 20 20 20 67 6f 74 6f 20 65 72 72  ;.      goto err
1950: 6f 72 3b 0a 20 20 20 20 7d 65 6c 73 65 20 69 66  or;.    }else if
1960: 28 20 64 62 5f 65 78 69 73 74 73 28 22 53 45 4c  ( db_exists("SEL
1970: 45 43 54 20 31 20 46 52 4f 4d 20 75 73 65 72 20  ECT 1 FROM user 
1980: 57 48 45 52 45 20 6c 6f 67 69 6e 3d 25 51 22 2c  WHERE login=%Q",
1990: 20 7a 4e 61 6d 65 29 20 29 7b 0a 20 20 20 20 20   zName) ){.     
19a0: 20 6a 73 6f 6e 5f 73 65 74 5f 65 72 72 28 46 53   json_set_err(FS
19b0: 4c 5f 4a 53 4f 4e 5f 45 5f 52 45 53 4f 55 52 43  L_JSON_E_RESOURC
19c0: 45 5f 41 4c 52 45 41 44 59 5f 45 58 49 53 54 53  E_ALREADY_EXISTS
19d0: 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,.              
19e0: 20 20 20 20 20 22 55 73 65 72 20 25 73 20 61 6c       "User %s al
19f0: 72 65 61 64 79 20 65 78 69 73 74 73 2e 22 2c 20  ready exists.", 
1a00: 7a 4e 61 6d 65 29 3b 0a 20 20 20 20 20 20 67 6f  zName);.      go
1a10: 74 6f 20 65 72 72 6f 72 3b 0a 20 20 20 20 7d 65  to error;.    }e
1a20: 6c 73 65 7b 0a 20 20 20 20 20 20 53 74 6d 74 20  lse{.      Stmt 
1a30: 69 6e 73 20 3d 20 65 6d 70 74 79 5f 53 74 6d 74  ins = empty_Stmt
1a40: 3b 0a 20 20 20 20 20 20 64 62 5f 70 72 65 70 61  ;.      db_prepa
1a50: 72 65 28 26 69 6e 73 2c 20 22 49 4e 53 45 52 54  re(&ins, "INSERT
1a60: 20 49 4e 54 4f 20 75 73 65 72 20 28 6c 6f 67 69   INTO user (logi
1a70: 6e 29 20 56 41 4c 55 45 53 28 25 51 29 22 2c 7a  n) VALUES(%Q)",z
1a80: 4e 61 6d 65 29 3b 0a 20 20 20 20 20 20 64 62 5f  Name);.      db_
1a90: 73 74 65 70 28 20 26 69 6e 73 20 29 3b 0a 20 20  step( &ins );.  
1aa0: 20 20 20 20 64 62 5f 66 69 6e 61 6c 69 7a 65 28      db_finalize(
1ab0: 26 69 6e 73 29 3b 0a 20 20 20 20 20 20 75 69 64  &ins);.      uid
1ac0: 20 3d 20 64 62 5f 69 6e 74 28 30 2c 22 53 45 4c   = db_int(0,"SEL
1ad0: 45 43 54 20 75 69 64 20 46 52 4f 4d 20 75 73 65  ECT uid FROM use
1ae0: 72 20 57 48 45 52 45 20 6c 6f 67 69 6e 3d 25 51  r WHERE login=%Q
1af0: 22 2c 20 7a 4e 61 6d 65 29 3b 0a 20 20 20 20 20  ", zName);.     
1b00: 20 61 73 73 65 72 74 28 75 69 64 3e 30 29 3b 0a   assert(uid>0);.
1b10: 20 20 20 20 20 20 7a 4e 61 6d 65 4e 65 77 20 3d        zNameNew =
1b20: 20 7a 4e 61 6d 65 3b 0a 20 20 20 20 20 20 63 73   zName;.      cs
1b30: 6f 6e 5f 6f 62 6a 65 63 74 5f 73 65 74 28 20 70  on_object_set( p
1b40: 55 73 65 72 2c 20 22 75 69 64 22 2c 20 63 73 6f  User, "uid", cso
1b50: 6e 5f 76 61 6c 75 65 5f 6e 65 77 5f 69 6e 74 65  n_value_new_inte
1b60: 67 65 72 28 75 69 64 29 20 29 3b 0a 20 20 20 20  ger(uid) );.    
1b70: 7d 0a 20 20 7d 65 6c 73 65 7b 0a 20 20 20 20 75  }.  }else{.    u
1b80: 69 64 20 3d 20 64 62 5f 69 6e 74 28 30 2c 22 53  id = db_int(0,"S
1b90: 45 4c 45 43 54 20 75 69 64 20 46 52 4f 4d 20 75  ELECT uid FROM u
1ba0: 73 65 72 20 57 48 45 52 45 20 6c 6f 67 69 6e 3d  ser WHERE login=
1bb0: 25 51 22 2c 20 7a 4e 61 6d 65 29 3b 0a 20 20 20  %Q", zName);.   
1bc0: 20 69 66 28 75 69 64 3c 3d 30 29 7b 0a 20 20 20   if(uid<=0){.   
1bd0: 20 20 20 6a 73 6f 6e 5f 73 65 74 5f 65 72 72 28     json_set_err(
1be0: 46 53 4c 5f 4a 53 4f 4e 5f 45 5f 52 45 53 4f 55  FSL_JSON_E_RESOU
1bf0: 52 43 45 5f 4e 4f 54 5f 46 4f 55 4e 44 2c 0a 20  RCE_NOT_FOUND,. 
1c00: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1c10: 20 20 22 4e 6f 20 6c 6f 67 69 6e 20 66 6f 75 6e    "No login foun
1c20: 64 20 66 6f 72 20 75 73 65 72 20 5b 25 73 5d 2e  d for user [%s].
1c30: 22 2c 20 7a 4e 61 6d 65 29 3b 0a 20 20 20 20 20  ", zName);.     
1c40: 20 67 6f 74 6f 20 65 72 72 6f 72 3b 0a 20 20 20   goto error;.   
1c50: 20 7d 0a 20 20 20 20 63 73 6f 6e 5f 6f 62 6a 65   }.    cson_obje
1c60: 63 74 5f 73 65 74 28 20 70 55 73 65 72 2c 20 22  ct_set( pUser, "
1c70: 75 69 64 22 2c 20 63 73 6f 6e 5f 76 61 6c 75 65  uid", cson_value
1c80: 5f 6e 65 77 5f 69 6e 74 65 67 65 72 28 75 69 64  _new_integer(uid
1c90: 29 20 29 3b 0a 20 20 7d 0a 0a 20 20 2f 2a 20 4d  ) );.  }..  /* M
1ca0: 61 69 6e 74 65 6e 61 6e 63 65 20 6e 6f 74 65 3a  aintenance note:
1cb0: 20 61 6c 6c 20 65 72 72 6f 72 2d 72 65 74 75 72   all error-retur
1cc0: 6e 73 20 66 72 6f 6d 20 68 65 72 65 20 6f 6e 20  ns from here on 
1cd0: 6f 75 74 20 73 68 6f 75 6c 64 20 67 6f 0a 20 20  out should go.  
1ce0: 20 20 20 76 69 61 20 27 67 6f 74 6f 20 65 72 72     via 'goto err
1cf0: 6f 72 27 20 69 6e 20 6f 72 64 65 72 20 74 6f 20  or' in order to 
1d00: 63 6c 65 61 6e 20 75 70 2e 0a 20 20 2a 2f 0a 0a  clean up..  */..
1d10: 20 20 69 66 28 75 69 64 20 21 3d 20 67 2e 75 73    if(uid != g.us
1d20: 65 72 55 69 64 29 7b 0a 20 20 20 20 69 66 28 21  erUid){.    if(!
1d30: 67 2e 70 65 72 6d 2e 41 64 6d 69 6e 20 26 26 20  g.perm.Admin && 
1d40: 21 67 2e 70 65 72 6d 2e 53 65 74 75 70 29 7b 0a  !g.perm.Setup){.
1d50: 20 20 20 20 20 20 6a 73 6f 6e 5f 73 65 74 5f 65        json_set_e
1d60: 72 72 28 46 53 4c 5f 4a 53 4f 4e 5f 45 5f 44 45  rr(FSL_JSON_E_DE
1d70: 4e 49 45 44 2c 0a 20 20 20 20 20 20 20 20 20 20  NIED,.          
1d80: 20 20 20 20 20 20 20 20 20 22 43 68 61 6e 67 69           "Changi
1d90: 6e 67 20 61 6e 6f 74 68 65 72 20 75 73 65 72 27  ng another user'
1da0: 73 20 64 61 74 61 20 72 65 71 75 69 72 65 73 20  s data requires 
1db0: 22 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ".              
1dc0: 20 20 20 20 20 22 27 61 27 20 6f 72 20 27 73 27       "'a' or 's'
1dd0: 20 70 72 69 76 69 6c 65 67 65 73 2e 22 29 3b 0a   privileges.");.
1de0: 20 20 20 20 20 20 67 6f 74 6f 20 65 72 72 6f 72        goto error
1df0: 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 20 20 2f 2a  ;.    }.  }.  /*
1e00: 20 63 68 65 63 6b 20 69 66 20 74 68 65 20 74 61   check if the ta
1e10: 72 67 65 74 20 75 69 64 20 63 75 72 72 65 6e 74  rget uid current
1e20: 6c 79 20 68 61 73 20 73 65 74 75 70 20 72 69 67  ly has setup rig
1e30: 68 74 73 2e 20 2a 2f 0a 20 20 74 67 74 48 61 64  hts. */.  tgtHad
1e40: 53 65 74 75 70 20 3d 20 64 62 5f 69 6e 74 28 30  Setup = db_int(0
1e50: 2c 22 53 45 4c 45 43 54 20 31 20 46 52 4f 4d 20  ,"SELECT 1 FROM 
1e60: 75 73 65 72 20 77 68 65 72 65 20 75 69 64 3d 25  user where uid=%
1e70: 64 22 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  d".             
1e80: 20 20 20 20 20 20 20 20 20 20 22 20 41 4e 44 20            " AND 
1e90: 63 61 70 20 47 4c 4f 42 20 27 2a 73 2a 27 22 2c  cap GLOB '*s*'",
1ea0: 20 75 69 64 29 3b 0a 0a 20 20 69 66 28 28 74 67   uid);..  if((tg
1eb0: 74 48 61 73 53 65 74 75 70 20 7c 7c 20 74 67 74  tHasSetup || tgt
1ec0: 48 61 64 53 65 74 75 70 29 20 26 26 20 21 67 2e  HadSetup) && !g.
1ed0: 70 65 72 6d 2e 53 65 74 75 70 29 7b 0a 20 20 20  perm.Setup){.   
1ee0: 20 2f 2a 0a 20 20 20 20 20 20 44 6f 20 6e 6f 74   /*.      Do not
1ef0: 20 61 6c 6c 6f 77 20 61 20 6e 6f 6e 2d 73 65 74   allow a non-set
1f00: 75 70 20 75 73 65 72 20 74 6f 20 73 65 74 20 6f  up user to set o
1f10: 72 20 72 65 6d 6f 76 65 20 73 65 74 75 70 0a 20  r remove setup. 
1f20: 20 20 20 20 20 70 72 69 76 69 6c 65 67 65 73 2e       privileges.
1f30: 20 73 65 74 75 70 2e 63 20 75 73 65 73 20 73 69   setup.c uses si
1f40: 6d 69 6c 61 72 20 6c 6f 67 69 63 2e 0a 20 20 20  milar logic..   
1f50: 20 2a 2f 0a 20 20 20 20 6a 73 6f 6e 5f 73 65 74   */.    json_set
1f60: 5f 65 72 72 28 46 53 4c 5f 4a 53 4f 4e 5f 45 5f  _err(FSL_JSON_E_
1f70: 44 45 4e 49 45 44 2c 0a 20 20 20 20 20 20 20 20  DENIED,.        
1f80: 20 20 20 20 20 20 20 20 20 22 4d 6f 64 69 66 79           "Modify
1f90: 69 6e 67 20 27 73 27 20 75 73 65 72 73 2f 70 72  ing 's' users/pr
1fa0: 69 76 69 6c 65 67 65 73 20 72 65 71 75 69 72 65  ivileges require
1fb0: 73 20 22 0a 20 20 20 20 20 20 20 20 20 20 20 20  s ".            
1fc0: 20 20 20 20 20 22 27 73 27 20 70 72 69 76 69 6c       "'s' privil
1fd0: 65 67 65 73 2e 22 29 3b 0a 20 20 20 20 67 6f 74  eges.");.    got
1fe0: 6f 20 65 72 72 6f 72 3b 0a 20 20 7d 0a 20 20 2f  o error;.  }.  /
1ff0: 2a 0a 20 20 20 20 50 6f 74 65 6e 74 69 61 6c 20  *.    Potential 
2000: 74 6f 64 6f 3a 20 64 6f 20 6e 6f 74 20 61 6c 6c  todo: do not all
2010: 6f 77 20 61 20 73 65 74 75 70 20 75 73 65 72 20  ow a setup user 
2020: 74 6f 20 72 65 6d 6f 76 65 20 27 73 27 20 66 72  to remove 's' fr
2030: 6f 6d 0a 20 20 20 20 68 69 6d 73 65 6c 66 2c 20  om.    himself, 
2040: 74 6f 20 61 76 6f 69 64 20 6c 6f 63 6b 69 6e 67  to avoid locking
2050: 20 68 69 6d 73 65 6c 66 20 6f 75 74 3f 0a 20 20   himself out?.  
2060: 2a 2f 0a 0a 20 20 62 6c 6f 62 5f 61 70 70 65 6e  */..  blob_appen
2070: 64 28 26 73 71 6c 2c 20 22 55 50 44 41 54 45 20  d(&sql, "UPDATE 
2080: 75 73 65 72 20 53 45 54 22 2c 2d 31 20 29 3b 0a  user SET",-1 );.
2090: 20 20 62 6c 6f 62 5f 61 70 70 65 6e 64 28 26 73    blob_append(&s
20a0: 71 6c 2c 20 22 20 6d 74 69 6d 65 3d 63 61 73 74  ql, " mtime=cast
20b0: 28 73 74 72 66 74 69 6d 65 28 27 25 73 27 29 20  (strftime('%s') 
20c0: 41 53 20 49 4e 54 45 47 45 52 29 22 2c 20 2d 31  AS INTEGER)", -1
20d0: 29 3b 0a 0a 20 20 69 66 28 28 75 69 64 3e 30 29  );..  if((uid>0)
20e0: 20 26 26 20 7a 4e 61 6d 65 4e 65 77 29 7b 0a 20   && zNameNew){. 
20f0: 20 20 20 2f 2a 20 43 68 65 63 6b 20 66 6f 72 20     /* Check for 
2100: 6e 61 6d 65 20 63 68 61 6e 67 65 2e 2e 2e 20 2a  name change... *
2110: 2f 0a 20 20 20 20 69 66 28 30 21 3d 73 74 72 63  /.    if(0!=strc
2120: 6d 70 28 7a 4e 61 6d 65 2c 7a 4e 61 6d 65 4e 65  mp(zName,zNameNe
2130: 77 29 29 7b 0a 20 20 20 20 20 20 69 66 28 20 28  w)){.      if( (
2140: 21 67 2e 70 65 72 6d 2e 41 64 6d 69 6e 20 26 26  !g.perm.Admin &&
2150: 20 21 67 2e 70 65 72 6d 2e 53 65 74 75 70 29 0a   !g.perm.Setup).
2160: 20 20 20 20 20 20 20 20 20 20 26 26 20 28 7a 4e            && (zN
2170: 61 6d 65 20 21 3d 20 7a 4e 61 6d 65 4e 65 77 29  ame != zNameNew)
2180: 29 7b 0a 20 20 20 20 20 20 20 20 6a 73 6f 6e 5f  ){.        json_
2190: 73 65 74 5f 65 72 72 28 20 46 53 4c 5f 4a 53 4f  set_err( FSL_JSO
21a0: 4e 5f 45 5f 44 45 4e 49 45 44 2c 0a 20 20 20 20  N_E_DENIED,.    
21b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
21c0: 20 20 22 4d 6f 64 69 66 79 69 6e 67 20 75 73 65    "Modifying use
21d0: 72 20 6e 61 6d 65 73 20 72 65 71 75 69 72 65 73  r names requires
21e0: 20 27 61 27 20 6f 72 20 27 73 27 20 70 72 69 76   'a' or 's' priv
21f0: 69 6c 65 67 65 73 2e 22 29 3b 0a 20 20 20 20 20  ileges.");.     
2200: 20 20 20 67 6f 74 6f 20 65 72 72 6f 72 3b 0a 20     goto error;. 
2210: 20 20 20 20 20 7d 0a 20 20 20 20 20 20 66 6f 72       }.      for
2220: 63 65 4c 6f 67 6f 75 74 20 3d 20 63 73 6f 6e 5f  ceLogout = cson_
2230: 76 61 6c 75 65 5f 74 72 75 65 28 29 0a 20 20 20  value_true().   
2240: 20 20 20 20 20 2f 2a 20 72 65 6d 69 6e 64 65 72       /* reminder
2250: 73 3a 20 31 29 20 64 6f 65 73 20 6e 6f 74 20 61  s: 1) does not a
2260: 6c 6c 6f 63 61 74 65 2e 0a 20 20 20 20 20 20 20  llocate..       
2270: 20 20 20 20 32 29 20 77 65 20 64 6f 20 74 68 69      2) we do thi
2280: 73 20 62 65 63 61 75 73 65 20 63 68 61 6e 67 69  s because changi
2290: 6e 67 20 61 20 6e 61 6d 65 0a 20 20 20 20 20 20  ng a name.      
22a0: 20 20 20 20 20 69 6e 76 61 6c 69 64 61 74 65 73       invalidates
22b0: 20 61 6e 79 20 6c 6f 67 69 6e 20 74 6f 6b 65 6e   any login token
22c0: 20 62 65 63 61 75 73 65 20 74 68 65 20 6f 6c 64   because the old
22d0: 20 6e 61 6d 65 0a 20 20 20 20 20 20 20 20 20 20   name.          
22e0: 20 69 73 20 70 61 72 74 20 6f 66 20 74 68 65 20   is part of the 
22f0: 74 6f 6b 65 6e 20 68 61 73 68 2e 0a 20 20 20 20  token hash..    
2300: 20 20 20 20 2a 2f 3b 0a 20 20 20 20 20 20 62 6c      */;.      bl
2310: 6f 62 5f 61 70 70 65 6e 64 5f 73 71 6c 28 26 73  ob_append_sql(&s
2320: 71 6c 2c 20 22 2c 20 6c 6f 67 69 6e 3d 25 51 22  ql, ", login=%Q"
2330: 2c 20 7a 4e 61 6d 65 4e 65 77 29 3b 0a 20 20 20  , zNameNew);.   
2340: 20 20 20 2b 2b 67 6f 74 46 69 65 6c 64 73 3b 0a     ++gotFields;.
2350: 20 20 20 20 7d 0a 20 20 7d 0a 0a 20 20 69 66 28      }.  }..  if(
2360: 20 7a 43 61 70 20 26 26 20 2a 7a 43 61 70 20 29   zCap && *zCap )
2370: 7b 0a 20 20 20 20 69 66 28 21 67 2e 70 65 72 6d  {.    if(!g.perm
2380: 2e 41 64 6d 69 6e 20 7c 7c 20 21 67 2e 70 65 72  .Admin || !g.per
2390: 6d 2e 53 65 74 75 70 29 7b 0a 20 20 20 20 20 20  m.Setup){.      
23a0: 2f 2a 20 77 65 20 22 63 6f 75 6c 64 22 20 61 72  /* we "could" ar
23b0: 67 75 61 62 6c 79 20 73 69 6c 65 6e 74 6c 79 20  guably silently 
23c0: 69 67 6e 6f 72 65 20 63 61 70 20 69 6e 20 74 68  ignore cap in th
23d0: 69 73 20 63 61 73 65 2e 20 2a 2f 0a 20 20 20 20  is case. */.    
23e0: 20 20 6a 73 6f 6e 5f 73 65 74 5f 65 72 72 28 46    json_set_err(F
23f0: 53 4c 5f 4a 53 4f 4e 5f 45 5f 44 45 4e 49 45 44  SL_JSON_E_DENIED
2400: 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,.              
2410: 20 20 20 20 20 22 43 68 61 6e 67 69 6e 67 20 63       "Changing c
2420: 61 70 61 62 69 6c 69 74 69 65 73 20 72 65 71 75  apabilities requ
2430: 69 72 65 73 20 27 61 27 20 6f 72 20 27 73 27 20  ires 'a' or 's' 
2440: 70 72 69 76 69 6c 65 67 65 73 2e 22 29 3b 0a 20  privileges.");. 
2450: 20 20 20 20 20 67 6f 74 6f 20 65 72 72 6f 72 3b       goto error;
2460: 0a 20 20 20 20 7d 0a 20 20 20 20 62 6c 6f 62 5f  .    }.    blob_
2470: 61 70 70 65 6e 64 5f 73 71 6c 28 26 73 71 6c 2c  append_sql(&sql,
2480: 20 22 2c 20 63 61 70 3d 25 51 22 2c 20 7a 43 61   ", cap=%Q", zCa
2490: 70 29 3b 0a 20 20 20 20 2b 2b 67 6f 74 46 69 65  p);.    ++gotFie
24a0: 6c 64 73 3b 0a 20 20 7d 0a 0a 20 20 69 66 28 20  lds;.  }..  if( 
24b0: 7a 50 57 20 26 26 20 2a 7a 50 57 20 29 7b 0a 20  zPW && *zPW ){. 
24c0: 20 20 20 69 66 28 21 67 2e 70 65 72 6d 2e 41 64     if(!g.perm.Ad
24d0: 6d 69 6e 20 26 26 20 21 67 2e 70 65 72 6d 2e 53  min && !g.perm.S
24e0: 65 74 75 70 20 26 26 20 21 67 2e 70 65 72 6d 2e  etup && !g.perm.
24f0: 50 61 73 73 77 6f 72 64 29 7b 0a 20 20 20 20 20  Password){.     
2500: 20 6a 73 6f 6e 5f 73 65 74 5f 65 72 72 28 20 46   json_set_err( F
2510: 53 4c 5f 4a 53 4f 4e 5f 45 5f 44 45 4e 49 45 44  SL_JSON_E_DENIED
2520: 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,.              
2530: 20 20 20 20 20 20 22 50 61 73 73 77 6f 72 64 20        "Password 
2540: 63 68 61 6e 67 65 20 72 65 71 75 69 72 65 73 20  change requires 
2550: 27 61 27 2c 20 27 73 27 2c 20 22 0a 20 20 20 20  'a', 's', ".    
2560: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2570: 22 6f 72 20 27 70 27 20 70 65 72 6d 69 73 73 69  "or 'p' permissi
2580: 6f 6e 73 2e 22 29 3b 0a 20 20 20 20 20 20 67 6f  ons.");.      go
2590: 74 6f 20 65 72 72 6f 72 3b 0a 20 20 20 20 7d 65  to error;.    }e
25a0: 6c 73 65 7b 0a 23 64 65 66 69 6e 65 20 54 52 59  lse{.#define TRY
25b0: 5f 4c 4f 47 49 4e 5f 47 52 4f 55 50 20 30 20 2f  _LOGIN_GROUP 0 /
25c0: 2a 20 6c 6f 67 69 6e 20 67 72 6f 75 70 20 73 75  * login group su
25d0: 70 70 6f 72 74 20 69 73 20 6e 6f 74 20 79 65 74  pport is not yet
25e0: 20 69 6d 70 6c 65 6d 65 6e 74 65 64 2e 20 2a 2f   implemented. */
25f0: 0a 23 69 66 20 21 54 52 59 5f 4c 4f 47 49 4e 5f  .#if !TRY_LOGIN_
2600: 47 52 4f 55 50 0a 20 20 20 20 20 20 63 68 61 72  GROUP.      char
2610: 20 2a 20 7a 50 57 48 61 73 68 20 3d 20 4e 55 4c   * zPWHash = NUL
2620: 4c 3b 0a 20 20 20 20 20 20 2b 2b 67 6f 74 46 69  L;.      ++gotFi
2630: 65 6c 64 73 3b 0a 20 20 20 20 20 20 7a 50 57 48  elds;.      zPWH
2640: 61 73 68 20 3d 20 73 68 61 31 5f 73 68 61 72 65  ash = sha1_share
2650: 64 5f 73 65 63 72 65 74 28 7a 50 57 2c 20 7a 4e  d_secret(zPW, zN
2660: 61 6d 65 4e 65 77 20 3f 20 7a 4e 61 6d 65 4e 65  ameNew ? zNameNe
2670: 77 20 3a 20 7a 4e 61 6d 65 2c 20 4e 55 4c 4c 29  w : zName, NULL)
2680: 3b 0a 20 20 20 20 20 20 62 6c 6f 62 5f 61 70 70  ;.      blob_app
2690: 65 6e 64 5f 73 71 6c 28 26 73 71 6c 2c 20 22 2c  end_sql(&sql, ",
26a0: 20 70 77 3d 25 51 22 2c 20 7a 50 57 48 61 73 68   pw=%Q", zPWHash
26b0: 29 3b 0a 20 20 20 20 20 20 66 72 65 65 28 7a 50  );.      free(zP
26c0: 57 48 61 73 68 29 3b 0a 23 65 6c 73 65 0a 20 20  WHash);.#else.  
26d0: 20 20 20 20 2b 2b 67 6f 74 46 69 65 6c 64 73 3b      ++gotFields;
26e0: 0a 20 20 20 20 20 20 62 6c 6f 62 5f 61 70 70 65  .      blob_appe
26f0: 6e 64 5f 73 71 6c 28 26 73 71 6c 2c 20 22 2c 20  nd_sql(&sql, ", 
2700: 70 77 3d 63 6f 61 6c 65 73 63 65 28 73 68 61 72  pw=coalesce(shar
2710: 65 64 5f 73 65 63 72 65 74 28 25 51 2c 25 51 2c  ed_secret(%Q,%Q,
2720: 22 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ".              
2730: 20 20 20 20 20 22 28 53 45 4c 45 43 54 20 76 61       "(SELECT va
2740: 6c 75 65 20 46 52 4f 4d 20 63 6f 6e 66 69 67 20  lue FROM config 
2750: 57 48 45 52 45 20 6e 61 6d 65 3d 27 70 72 6f 6a  WHERE name='proj
2760: 65 63 74 2d 63 6f 64 65 27 29 29 29 22 2c 0a 20  ect-code')))",. 
2770: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2780: 20 20 7a 50 57 2c 20 7a 4e 61 6d 65 4e 65 77 20    zPW, zNameNew 
2790: 3f 20 7a 4e 61 6d 65 4e 65 77 20 3a 20 7a 4e 61  ? zNameNew : zNa
27a0: 6d 65 29 3b 0a 20 20 20 20 20 20 2f 2a 20 73 68  me);.      /* sh
27b0: 61 72 65 64 5f 73 65 63 72 65 74 28 29 20 66 75  ared_secret() fu
27c0: 6e 63 20 69 73 20 75 6e 64 65 66 69 6e 65 64 3f  nc is undefined?
27d0: 20 2a 2f 0a 23 65 6e 64 69 66 0a 20 20 20 20 7d   */.#endif.    }
27e0: 0a 20 20 7d 0a 0a 20 20 69 66 28 20 7a 49 6e 66  .  }..  if( zInf
27f0: 6f 20 29 7b 0a 20 20 20 20 62 6c 6f 62 5f 61 70  o ){.    blob_ap
2800: 70 65 6e 64 5f 73 71 6c 28 26 73 71 6c 2c 20 22  pend_sql(&sql, "
2810: 2c 20 69 6e 66 6f 3d 25 51 22 2c 20 7a 49 6e 66  , info=%Q", zInf
2820: 6f 29 3b 0a 20 20 20 20 2b 2b 67 6f 74 46 69 65  o);.    ++gotFie
2830: 6c 64 73 3b 0a 20 20 7d 0a 0a 20 20 69 66 28 28  lds;.  }..  if((
2840: 67 2e 70 65 72 6d 2e 41 64 6d 69 6e 20 7c 7c 20  g.perm.Admin || 
2850: 67 2e 70 65 72 6d 2e 53 65 74 75 70 29 0a 20 20  g.perm.Setup).  
2860: 20 20 20 26 26 20 66 6f 72 63 65 4c 6f 67 6f 75     && forceLogou
2870: 74 20 26 26 20 63 73 6f 6e 5f 76 61 6c 75 65 5f  t && cson_value_
2880: 67 65 74 5f 62 6f 6f 6c 28 66 6f 72 63 65 4c 6f  get_bool(forceLo
2890: 67 6f 75 74 29 29 7b 0a 20 20 20 20 62 6c 6f 62  gout)){.    blob
28a0: 5f 61 70 70 65 6e 64 28 26 73 71 6c 2c 20 22 2c  _append(&sql, ",
28b0: 20 63 6f 6f 6b 69 65 3d 4e 55 4c 4c 2c 20 63 65   cookie=NULL, ce
28c0: 78 70 69 72 65 3d 4e 55 4c 4c 22 2c 20 2d 31 29  xpire=NULL", -1)
28d0: 3b 0a 20 20 20 20 2b 2b 67 6f 74 46 69 65 6c 64  ;.    ++gotField
28e0: 73 3b 0a 20 20 7d 0a 0a 20 20 69 66 28 21 67 6f  s;.  }..  if(!go
28f0: 74 46 69 65 6c 64 73 29 7b 0a 20 20 20 20 6a 73  tFields){.    js
2900: 6f 6e 5f 73 65 74 5f 65 72 72 28 20 46 53 4c 5f  on_set_err( FSL_
2910: 4a 53 4f 4e 5f 45 5f 4d 49 53 53 49 4e 47 5f 41  JSON_E_MISSING_A
2920: 52 47 53 2c 0a 20 20 20 20 20 20 20 20 20 20 20  RGS,.           
2930: 20 20 20 20 20 20 20 22 52 65 71 75 69 72 65 64         "Required
2940: 20 75 73 65 72 20 64 61 74 61 20 61 72 65 20 6d   user data are m
2950: 69 73 73 69 6e 67 2e 22 29 3b 0a 20 20 20 20 67  issing.");.    g
2960: 6f 74 6f 20 65 72 72 6f 72 3b 0a 20 20 7d 0a 20  oto error;.  }. 
2970: 20 61 73 73 65 72 74 28 75 69 64 3e 30 29 3b 0a   assert(uid>0);.
2980: 23 69 66 20 21 54 52 59 5f 4c 4f 47 49 4e 5f 47  #if !TRY_LOGIN_G
2990: 52 4f 55 50 0a 20 20 62 6c 6f 62 5f 61 70 70 65  ROUP.  blob_appe
29a0: 6e 64 5f 73 71 6c 28 26 73 71 6c 2c 20 22 20 57  nd_sql(&sql, " W
29b0: 48 45 52 45 20 75 69 64 3d 25 64 22 2c 20 75 69  HERE uid=%d", ui
29c0: 64 29 3b 0a 23 65 6c 73 65 20 2f 2a 20 6e 65 65  d);.#else /* nee
29d0: 64 20 6e 61 6d 65 20 66 6f 72 20 6c 6f 67 69 6e  d name for login
29e0: 20 67 72 6f 75 70 20 73 75 70 70 6f 72 74 20 3a   group support :
29f0: 2f 20 2a 2f 0a 20 20 62 6c 6f 62 5f 61 70 70 65  / */.  blob_appe
2a00: 6e 64 5f 73 71 6c 28 26 73 71 6c 2c 20 22 20 57  nd_sql(&sql, " W
2a10: 48 45 52 45 20 6c 6f 67 69 6e 3d 25 51 22 2c 20  HERE login=%Q", 
2a20: 7a 4e 61 6d 65 29 3b 0a 23 65 6e 64 69 66 0a 23  zName);.#endif.#
2a30: 69 66 20 30 0a 20 20 70 75 74 73 28 62 6c 6f 62  if 0.  puts(blob
2a40: 5f 73 74 72 28 26 73 71 6c 29 29 3b 0a 20 20 63  _str(&sql));.  c
2a50: 73 6f 6e 5f 6f 75 74 70 75 74 5f 46 49 4c 45 28  son_output_FILE(
2a60: 20 63 73 6f 6e 5f 6f 62 6a 65 63 74 5f 76 61 6c   cson_object_val
2a70: 75 65 28 70 55 73 65 72 29 2c 20 73 74 64 6f 75  ue(pUser), stdou
2a80: 74 2c 20 4e 55 4c 4c 20 29 3b 0a 23 65 6e 64 69  t, NULL );.#endi
2a90: 66 0a 20 20 64 62 5f 70 72 65 70 61 72 65 28 26  f.  db_prepare(&
2aa0: 71 2c 20 22 25 73 22 2c 20 62 6c 6f 62 5f 73 71  q, "%s", blob_sq
2ab0: 6c 5f 74 65 78 74 28 26 73 71 6c 29 29 3b 0a 20  l_text(&sql));. 
2ac0: 20 64 62 5f 65 78 65 63 28 26 71 29 3b 0a 20 20   db_exec(&q);.  
2ad0: 64 62 5f 66 69 6e 61 6c 69 7a 65 28 26 71 29 3b  db_finalize(&q);
2ae0: 0a 23 69 66 20 54 52 59 5f 4c 4f 47 49 4e 5f 47  .#if TRY_LOGIN_G
2af0: 52 4f 55 50 0a 20 20 69 66 28 20 7a 50 57 20 7c  ROUP.  if( zPW |
2b00: 7c 20 63 73 6f 6e 5f 76 61 6c 75 65 5f 67 65 74  | cson_value_get
2b10: 5f 62 6f 6f 6c 28 66 6f 72 63 65 4c 6f 67 6f 75  _bool(forceLogou
2b20: 74 29 20 29 7b 0a 20 20 20 20 42 6c 6f 62 20 67  t) ){.    Blob g
2b30: 72 6f 75 70 53 71 6c 20 3d 20 65 6d 70 74 79 5f  roupSql = empty_
2b40: 62 6c 6f 62 3b 0a 20 20 20 20 63 68 61 72 20 2a  blob;.    char *
2b50: 20 7a 45 72 72 20 3d 20 4e 55 4c 4c 3b 0a 20 20   zErr = NULL;.  
2b60: 20 20 62 6c 6f 62 5f 61 70 70 65 6e 64 5f 73 71    blob_append_sq
2b70: 6c 28 26 67 72 6f 75 70 53 71 6c 2c 0a 20 20 20  l(&groupSql,.   
2b80: 20 20 20 22 49 4e 53 45 52 54 20 49 4e 54 4f 20     "INSERT INTO 
2b90: 75 73 65 72 28 6c 6f 67 69 6e 29 22 0a 20 20 20  user(login)".   
2ba0: 20 20 20 22 20 20 53 45 4c 45 43 54 20 25 51 20     "  SELECT %Q 
2bb0: 57 48 45 52 45 20 4e 4f 54 20 45 58 49 53 54 53  WHERE NOT EXISTS
2bc0: 28 53 45 4c 45 43 54 20 31 20 46 52 4f 4d 20 75  (SELECT 1 FROM u
2bd0: 73 65 72 20 57 48 45 52 45 20 6c 6f 67 69 6e 3d  ser WHERE login=
2be0: 25 51 29 3b 22 2c 0a 20 20 20 20 20 20 7a 4e 61  %Q);",.      zNa
2bf0: 6d 65 2c 20 7a 4e 61 6d 65 0a 20 20 20 20 29 3b  me, zName.    );
2c00: 0a 20 20 20 20 62 6c 6f 62 5f 61 70 70 65 6e 64  .    blob_append
2c10: 28 26 67 72 6f 75 70 53 71 6c 2c 20 62 6c 6f 62  (&groupSql, blob
2c20: 5f 73 74 72 28 26 73 71 6c 29 2c 20 62 6c 6f 62  _str(&sql), blob
2c30: 5f 73 69 7a 65 28 26 73 71 6c 29 29 3b 0a 20 20  _size(&sql));.  
2c40: 20 20 6c 6f 67 69 6e 5f 67 72 6f 75 70 5f 73 71    login_group_sq
2c50: 6c 28 62 6c 6f 62 5f 73 74 72 28 26 67 72 6f 75  l(blob_str(&grou
2c60: 70 53 71 6c 29 2c 20 4e 55 4c 4c 2c 20 4e 55 4c  pSql), NULL, NUL
2c70: 4c 2c 20 26 7a 45 72 72 29 3b 0a 20 20 20 20 62  L, &zErr);.    b
2c80: 6c 6f 62 5f 72 65 73 65 74 28 26 67 72 6f 75 70  lob_reset(&group
2c90: 53 71 6c 29 3b 0a 20 20 20 20 69 66 28 20 7a 45  Sql);.    if( zE
2ca0: 72 72 20 29 7b 0a 20 20 20 20 20 20 6a 73 6f 6e  rr ){.      json
2cb0: 5f 73 65 74 5f 65 72 72 28 20 46 53 4c 5f 4a 53  _set_err( FSL_JS
2cc0: 4f 4e 5f 45 5f 55 4e 4b 4e 4f 57 4e 2c 0a 20 20  ON_E_UNKNOWN,.  
2cd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2ce0: 20 20 22 52 65 70 6f 2d 67 72 6f 75 70 20 75 70    "Repo-group up
2cf0: 64 61 74 65 20 61 74 20 6c 65 61 73 74 20 70 61  date at least pa
2d00: 72 74 69 61 6c 6c 79 20 66 61 69 6c 65 64 3a 20  rtially failed: 
2d10: 25 73 22 2c 0a 20 20 20 20 20 20 20 20 20 20 20  %s",.           
2d20: 20 20 20 20 20 20 20 20 20 7a 45 72 72 29 3b 0a           zErr);.
2d30: 20 20 20 20 20 20 66 72 65 65 28 7a 45 72 72 29        free(zErr)
2d40: 3b 0a 20 20 20 20 20 20 67 6f 74 6f 20 65 72 72  ;.      goto err
2d50: 6f 72 3b 0a 20 20 20 20 7d 0a 20 20 7d 0a 23 65  or;.    }.  }.#e
2d60: 6e 64 69 66 20 2f 2a 20 54 52 59 5f 4c 4f 47 49  ndif /* TRY_LOGI
2d70: 4e 5f 47 52 4f 55 50 20 2a 2f 0a 0a 23 75 6e 64  N_GROUP */..#und
2d80: 65 66 20 54 52 59 5f 4c 4f 47 49 4e 5f 47 52 4f  ef TRY_LOGIN_GRO
2d90: 55 50 0a 0a 20 20 66 72 65 65 28 20 7a 4e 61 6d  UP..  free( zNam
2da0: 65 46 72 65 65 20 29 3b 0a 20 20 62 6c 6f 62 5f  eFree );.  blob_
2db0: 72 65 73 65 74 28 26 73 71 6c 29 3b 0a 20 20 72  reset(&sql);.  r
2dc0: 65 74 75 72 6e 20 30 3b 0a 0a 20 20 65 72 72 6f  eturn 0;..  erro
2dd0: 72 3a 0a 20 20 61 73 73 65 72 74 28 30 20 21 3d  r:.  assert(0 !=
2de0: 20 67 2e 6a 73 6f 6e 2e 72 65 73 75 6c 74 43 6f   g.json.resultCo
2df0: 64 65 29 3b 0a 20 20 66 72 65 65 28 7a 4e 61 6d  de);.  free(zNam
2e00: 65 46 72 65 65 29 3b 0a 20 20 62 6c 6f 62 5f 72  eFree);.  blob_r
2e10: 65 73 65 74 28 26 73 71 6c 29 3b 0a 20 20 72 65  eset(&sql);.  re
2e20: 74 75 72 6e 20 67 2e 6a 73 6f 6e 2e 72 65 73 75  turn g.json.resu
2e30: 6c 74 43 6f 64 65 3b 0a 7d 0a 0a 0a 2f 2a 0a 2a  ltCode;.}.../*.*
2e40: 2a 20 49 6d 70 6c 20 6f 66 20 2f 6a 73 6f 6e 2f  * Impl of /json/
2e50: 75 73 65 72 2f 73 61 76 65 2e 0a 2a 2f 0a 73 74  user/save..*/.st
2e60: 61 74 69 63 20 63 73 6f 6e 5f 76 61 6c 75 65 20  atic cson_value 
2e70: 2a 20 6a 73 6f 6e 5f 75 73 65 72 5f 73 61 76 65  * json_user_save
2e80: 28 29 7b 0a 20 20 2f 2a 20 74 72 79 20 74 6f 20  (){.  /* try to 
2e90: 67 65 74 20 75 73 65 72 20 69 6e 66 6f 20 66 72  get user info fr
2ea0: 6f 6d 20 47 45 54 2f 43 4c 49 20 61 72 67 73 20  om GET/CLI args 
2eb0: 61 6e 64 20 63 6f 6e 73 74 72 75 63 74 0a 20 20  and construct.  
2ec0: 20 20 20 61 20 4a 53 4f 4e 20 66 6f 72 6d 20 6f     a JSON form o
2ed0: 66 20 69 74 2e 2e 2e 20 2a 2f 0a 20 20 63 73 6f  f it... */.  cso
2ee0: 6e 5f 6f 62 6a 65 63 74 20 2a 20 75 20 3d 20 63  n_object * u = c
2ef0: 73 6f 6e 5f 6e 65 77 5f 6f 62 6a 65 63 74 28 29  son_new_object()
2f00: 3b 0a 20 20 63 68 61 72 20 63 6f 6e 73 74 20 2a  ;.  char const *
2f10: 20 73 74 72 20 3d 20 4e 55 4c 4c 3b 0a 20 20 63   str = NULL;.  c
2f20: 68 61 72 20 62 20 3d 20 2d 31 3b 0a 20 20 69 6e  har b = -1;.  in
2f30: 74 20 69 20 3d 20 2d 31 3b 0a 20 20 69 6e 74 20  t i = -1;.  int 
2f40: 75 69 64 20 3d 20 2d 31 3b 0a 20 20 63 73 6f 6e  uid = -1;.  cson
2f50: 5f 76 61 6c 75 65 20 2a 20 70 61 79 6c 6f 61 64  _value * payload
2f60: 20 3d 20 4e 55 4c 4c 3b 0a 20 20 2f 2a 20 53 74   = NULL;.  /* St
2f70: 72 69 6e 67 20 70 72 6f 70 65 72 74 69 65 73 2e  ring properties.
2f80: 2e 2e 20 2a 2f 0a 23 64 65 66 69 6e 65 20 50 52  .. */.#define PR
2f90: 4f 50 28 4c 4b 2c 53 4b 29 20 73 74 72 20 3d 20  OP(LK,SK) str = 
2fa0: 6a 73 6f 6e 5f 66 69 6e 64 5f 6f 70 74 69 6f 6e  json_find_option
2fb0: 5f 63 73 74 72 28 4c 4b 2c 4e 55 4c 4c 2c 53 4b  _cstr(LK,NULL,SK
2fc0: 29 3b 20 20 20 20 20 5c 0a 20 20 69 66 28 73 74  );     \.  if(st
2fd0: 72 29 7b 20 63 73 6f 6e 5f 6f 62 6a 65 63 74 5f  r){ cson_object_
2fe0: 73 65 74 28 75 2c 20 4c 4b 2c 20 6a 73 6f 6e 5f  set(u, LK, json_
2ff0: 6e 65 77 5f 73 74 72 69 6e 67 28 73 74 72 29 29  new_string(str))
3000: 3b 20 7d 20 28 76 6f 69 64 29 30 0a 20 20 50 52  ; } (void)0.  PR
3010: 4f 50 28 22 6e 61 6d 65 22 2c 22 6e 22 29 3b 0a  OP("name","n");.
3020: 20 20 50 52 4f 50 28 22 70 61 73 73 77 6f 72 64    PROP("password
3030: 22 2c 22 70 22 29 3b 0a 20 20 50 52 4f 50 28 22  ","p");.  PROP("
3040: 69 6e 66 6f 22 2c 22 69 22 29 3b 0a 20 20 50 52  info","i");.  PR
3050: 4f 50 28 22 63 61 70 61 62 69 6c 69 74 69 65 73  OP("capabilities
3060: 22 2c 22 63 22 29 3b 0a 23 75 6e 64 65 66 20 50  ","c");.#undef P
3070: 52 4f 50 0a 20 20 2f 2a 20 42 6f 6f 6c 65 61 6e  ROP.  /* Boolean
3080: 20 70 72 6f 70 65 72 74 69 65 73 2e 2e 2e 20 2a   properties... *
3090: 2f 0a 23 64 65 66 69 6e 65 20 50 52 4f 50 28 4c  /.#define PROP(L
30a0: 4b 2c 44 46 4c 54 29 20 62 20 3d 20 6a 73 6f 6e  K,DFLT) b = json
30b0: 5f 66 69 6e 64 5f 6f 70 74 69 6f 6e 5f 62 6f 6f  _find_option_boo
30c0: 6c 28 4c 4b 2c 4e 55 4c 4c 2c 4e 55 4c 4c 2c 44  l(LK,NULL,NULL,D
30d0: 46 4c 54 29 3b 20 20 20 20 20 5c 0a 20 20 69 66  FLT);     \.  if
30e0: 28 44 46 4c 54 21 3d 62 29 7b 20 63 73 6f 6e 5f  (DFLT!=b){ cson_
30f0: 6f 62 6a 65 63 74 5f 73 65 74 28 75 2c 20 4c 4b  object_set(u, LK
3100: 2c 20 63 73 6f 6e 5f 76 61 6c 75 65 5f 6e 65 77  , cson_value_new
3110: 5f 62 6f 6f 6c 28 62 29 29 3b 20 7d 20 28 76 6f  _bool(b)); } (vo
3120: 69 64 29 30 0a 20 20 50 52 4f 50 28 22 66 6f 72  id)0.  PROP("for
3130: 63 65 4c 6f 67 6f 75 74 22 2c 2d 31 29 3b 0a 23  ceLogout",-1);.#
3140: 75 6e 64 65 66 20 50 52 4f 50 0a 0a 23 64 65 66  undef PROP..#def
3150: 69 6e 65 20 50 52 4f 50 28 4c 4b 2c 44 46 4c 54  ine PROP(LK,DFLT
3160: 29 20 69 20 3d 20 6a 73 6f 6e 5f 66 69 6e 64 5f  ) i = json_find_
3170: 6f 70 74 69 6f 6e 5f 69 6e 74 28 4c 4b 2c 4e 55  option_int(LK,NU
3180: 4c 4c 2c 4e 55 4c 4c 2c 44 46 4c 54 29 3b 20 20  LL,NULL,DFLT);  
3190: 20 5c 0a 20 20 69 66 28 44 46 4c 54 20 21 3d 20   \.  if(DFLT != 
31a0: 69 29 7b 20 63 73 6f 6e 5f 6f 62 6a 65 63 74 5f  i){ cson_object_
31b0: 73 65 74 28 75 2c 20 4c 4b 2c 20 63 73 6f 6e 5f  set(u, LK, cson_
31c0: 76 61 6c 75 65 5f 6e 65 77 5f 69 6e 74 65 67 65  value_new_intege
31d0: 72 28 69 29 29 3b 20 7d 20 28 76 6f 69 64 29 30  r(i)); } (void)0
31e0: 0a 20 20 50 52 4f 50 28 22 75 69 64 22 2c 2d 39  .  PROP("uid",-9
31f0: 39 29 3b 0a 23 75 6e 64 65 66 20 50 52 4f 50 0a  9);.#undef PROP.
3200: 20 20 69 66 28 20 67 2e 6a 73 6f 6e 2e 72 65 71    if( g.json.req
3210: 50 61 79 6c 6f 61 64 2e 6f 20 29 7b 0a 20 20 20  Payload.o ){.   
3220: 20 63 73 6f 6e 5f 6f 62 6a 65 63 74 5f 6d 65 72   cson_object_mer
3230: 67 65 28 20 75 2c 20 67 2e 6a 73 6f 6e 2e 72 65  ge( u, g.json.re
3240: 71 50 61 79 6c 6f 61 64 2e 6f 2c 20 43 53 4f 4e  qPayload.o, CSON
3250: 5f 4d 45 52 47 45 5f 4e 4f 5f 52 45 43 55 52 53  _MERGE_NO_RECURS
3260: 45 20 29 3b 0a 20 20 7d 0a 20 20 6a 73 6f 6e 5f  E );.  }.  json_
3270: 75 73 65 72 5f 75 70 64 61 74 65 5f 66 72 6f 6d  user_update_from
3280: 5f 6a 73 6f 6e 28 20 75 20 29 3b 0a 20 20 69 66  _json( u );.  if
3290: 28 21 67 2e 6a 73 6f 6e 2e 72 65 73 75 6c 74 43  (!g.json.resultC
32a0: 6f 64 65 29 7b 0a 20 20 20 20 75 69 64 20 3d 20  ode){.    uid = 
32b0: 63 73 6f 6e 5f 76 61 6c 75 65 5f 67 65 74 5f 69  cson_value_get_i
32c0: 6e 74 65 67 65 72 28 20 63 73 6f 6e 5f 6f 62 6a  nteger( cson_obj
32d0: 65 63 74 5f 67 65 74 28 75 2c 20 22 75 69 64 22  ect_get(u, "uid"
32e0: 29 20 29 3b 0a 20 20 20 20 61 73 73 65 72 74 28  ) );.    assert(
32f0: 28 75 69 64 3e 30 29 20 26 26 20 22 53 6f 6d 65  (uid>0) && "Some
3300: 74 68 69 6e 67 20 77 65 6e 74 20 77 72 6f 6e 67  thing went wrong
3310: 20 69 6e 20 6a 73 6f 6e 5f 75 73 65 72 5f 75 70   in json_user_up
3320: 64 61 74 65 5f 66 72 6f 6d 5f 6a 73 6f 6e 28 29  date_from_json()
3330: 22 29 3b 0a 20 20 20 20 70 61 79 6c 6f 61 64 20  ");.    payload 
3340: 3d 20 6a 73 6f 6e 5f 6c 6f 61 64 5f 75 73 65 72  = json_load_user
3350: 5f 62 79 5f 69 64 28 75 69 64 29 3b 0a 20 20 7d  _by_id(uid);.  }
3360: 0a 20 20 63 73 6f 6e 5f 66 72 65 65 5f 6f 62 6a  .  cson_free_obj
3370: 65 63 74 28 75 29 3b 0a 20 20 72 65 74 75 72 6e  ect(u);.  return
3380: 20 70 61 79 6c 6f 61 64 3b 0a 7d 0a 23 65 6e 64   payload;.}.#end
3390: 69 66 20 2f 2a 20 46 4f 53 53 49 4c 5f 45 4e 41  if /* FOSSIL_ENA
33a0: 42 4c 45 5f 4a 53 4f 4e 20 2a 2f 0a              BLE_JSON */.