Changes On Branch ssh-shared-account
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch ssh-shared-account Excluding Merge-Ins

This is equivalent to a diff from 087cae847d to f38f76cf01

2013-07-20
09:41
Need to retrain vi. Leaf check-in: f38f76cf01 user: amb tags: ssh-shared-account
09:38
Print the Fossil user if different from URL user. check-in: 4d67ad13ca user: amb tags: ssh-shared-account
08:40
Alternative approach to allow multiple SSH users to share the same SSH account while maintaining separate Fossil identities. check-in: e3510cef23 user: amb tags: ssh-shared-account
2013-07-18
07:28
Needed coding style clean up that was missed. Leaf check-in: 087cae847d user: amb tags: ssh-transport-changes
05:45
Perhaps a bit premature at this point. Need additional feedback. check-in: 059f50864b user: amb tags: ssh-transport-changes

Changes to src/checkin.c.

1350
1351
1352
1353
1354
1355
1356

1357
1358
1359
1360
1361
1362
1363
    if( sCiInfo.zBrClr==0 && sCiInfo.zColor==0 ){
      sCiInfo.zBrClr = "#fec084";  /* Orange */
    }
  }
  sCiInfo.zDateOvrd = find_option("date-override",0,1);
  sCiInfo.zUserOvrd = find_option("user-override",0,1);
  db_must_be_within_tree();

  noSign = db_get_boolean("omitsign", 0)|noSign;
  if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; }
  useCksum = db_get_boolean("repo-cksum", 1);
  outputManifest = db_get_boolean("manifest", 0);
  verify_all_options();

  /* Escape special characters in tags and put all tags in sorted order */







>







1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
    if( sCiInfo.zBrClr==0 && sCiInfo.zColor==0 ){
      sCiInfo.zBrClr = "#fec084";  /* Orange */
    }
  }
  sCiInfo.zDateOvrd = find_option("date-override",0,1);
  sCiInfo.zUserOvrd = find_option("user-override",0,1);
  db_must_be_within_tree();
  clone_ssh_db_options();
  noSign = db_get_boolean("omitsign", 0)|noSign;
  if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; }
  useCksum = db_get_boolean("repo-cksum", 1);
  outputManifest = db_get_boolean("manifest", 0);
  verify_all_options();

  /* Escape special characters in tags and put all tags in sorted order */

Changes to src/clone.c.

93
94
95
96
97
98
99

100
101
102
103
104
105
106
**
** Options:
**    --admin-user|-A USERNAME   Make USERNAME the administrator
**    --private                  Also clone private branches 
**    --ssl-identity=filename    Use the SSL identity if requested by the server
**    --ssh-fossil|-f /fossil    Use this path as remote fossil command
**    --ssh-command|-c 'command' Use this SSH command

**
** See also: init
*/
void clone_cmd(void){
  char *zPassword;
  const char *zDefaultUser;   /* Optional name of the default user */
  int nErr = 0;







>







93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
**
** Options:
**    --admin-user|-A USERNAME   Make USERNAME the administrator
**    --private                  Also clone private branches 
**    --ssl-identity=filename    Use the SSL identity if requested by the server
**    --ssh-fossil|-f /fossil    Use this path as remote fossil command
**    --ssh-command|-c 'command' Use this SSH command
**    --ssh-fossil-user|-l user  Fossil user to use for SSH if different.
**
** See also: init
*/
void clone_cmd(void){
  char *zPassword;
  const char *zDefaultUser;   /* Optional name of the default user */
  int nErr = 0;
155
156
157
158
159
160
161

162
163
164
165
166
167
168
    }
    db_multi_exec(
      "REPLACE INTO config(name,value,mtime)"
      " VALUES('server-code', lower(hex(randomblob(20))), now());"
    );
    url_enable_proxy(0);
    url_get_password_if_needed();

    g.xlinkClusterOnly = 1;
    nErr = client_sync(SYNC_CLONE | bPrivate,CONFIGSET_ALL,0);
    g.xlinkClusterOnly = 0;
    verify_cancel();
    db_end_transaction(0);
    db_close(1);
    if( nErr ){







>







156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
    }
    db_multi_exec(
      "REPLACE INTO config(name,value,mtime)"
      " VALUES('server-code', lower(hex(randomblob(20))), now());"
    );
    url_enable_proxy(0);
    url_get_password_if_needed();
    clone_ssh_db_options();
    g.xlinkClusterOnly = 1;
    nErr = client_sync(SYNC_CLONE | bPrivate,CONFIGSET_ALL,0);
    g.xlinkClusterOnly = 0;
    verify_cancel();
    db_end_transaction(0);
    db_close(1);
    if( nErr ){
182
183
184
185
186
187
188

189
190
191
192
193
194
195
196




197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212




213


/*
** Look for SSH clone command line options and setup in globals.
*/
void clone_ssh_options(void){
  const char *zSshFossilCmd;  /* Path to remote fossil command for SSH */
  const char *zSshCmd;        /* SSH command string */


  zSshFossilCmd = find_option("ssh-fossil","f",1);
  if( zSshFossilCmd && zSshFossilCmd[0] ){
    g.zSshFossilCmd = mprintf("%s", zSshFossilCmd);
  }
  zSshCmd = find_option("ssh-command","c",1);
  if( zSshCmd && zSshCmd[0] ){
    g.zSshCmd = mprintf("%s", zSshCmd);




  }
}

/*
** Set SSH options discovered in global variables (set from command line 
** options).  If not found, attempt to retrieve from database if present.
*/
void clone_ssh_db_options(void){
  if( g.zSshFossilCmd && g.zSshFossilCmd[0] ){
    db_set("ssh-fossil", g.zSshFossilCmd, 0);
  }else{
    g.zSshFossilCmd = db_get("ssh-fossil","fossil");
  }
  if( g.zSshCmd && g.zSshCmd[0] ){
    db_set("ssh-command", g.zSshCmd, 0);
  }




}








>








>
>
>
>











|




>
>
>
>
|
>
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225

/*
** Look for SSH clone command line options and setup in globals.
*/
void clone_ssh_options(void){
  const char *zSshFossilCmd;  /* Path to remote fossil command for SSH */
  const char *zSshCmd;        /* SSH command string */
  const char *zFossilUser;    /* Fossil user if login specified for SSH */

  zSshFossilCmd = find_option("ssh-fossil","f",1);
  if( zSshFossilCmd && zSshFossilCmd[0] ){
    g.zSshFossilCmd = mprintf("%s", zSshFossilCmd);
  }
  zSshCmd = find_option("ssh-command","c",1);
  if( zSshCmd && zSshCmd[0] ){
    g.zSshCmd = mprintf("%s", zSshCmd);
  }
  zFossilUser = find_option("ssh-fossil-user","l",1);
  if( zFossilUser && zFossilUser[0] ){
    g.zFossilUser = mprintf("%s", zFossilUser);
  }
}

/*
** Set SSH options discovered in global variables (set from command line 
** options).  If not found, attempt to retrieve from database if present.
*/
void clone_ssh_db_options(void){
  if( g.zSshFossilCmd && g.zSshFossilCmd[0] ){
    db_set("ssh-fossil", g.zSshFossilCmd, 0);
  }else{
    g.zSshFossilCmd = db_get("ssh-fossil", "fossil");
  }
  if( g.zSshCmd && g.zSshCmd[0] ){
    db_set("ssh-command", g.zSshCmd, 0);
  }
  if( g.zFossilUser && g.zFossilUser[0] ){
    db_set("ssh-fossil-user", g.zFossilUser, 0);
  }else{
    g.zFossilUser = db_get("ssh-fossil-user", 0);
  }
}

Changes to src/db.c.

2126
2127
2128
2129
2130
2131
2132

2133
2134
2135
2136
2137
2138
2139
  { "pgp-command",   0,               40, 0, "gpg --clearsign -o " },
  { "proxy",         0,               32, 0, "off"                 },
  { "relative-paths",0,                0, 0, "on"                  },
  { "repo-cksum",    0,                0, 0, "on"                  },
  { "self-register", 0,                0, 0, "off"                 },
  { "ssh-command",   0,               40, 0, ""                    },
  { "ssh-fossil",    0,               40, 0, ""                    },

  { "ssl-ca-location",0,              40, 0, ""                    },
  { "ssl-identity",  0,               40, 0, ""                    },
#ifdef FOSSIL_ENABLE_TCL
  { "tcl",           0,                0, 0, "off"                 },
  { "tcl-setup",     0,               40, 0, ""                    },
#endif
  { "th1-setup",     0,               40, 0, ""                    },







>







2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
  { "pgp-command",   0,               40, 0, "gpg --clearsign -o " },
  { "proxy",         0,               32, 0, "off"                 },
  { "relative-paths",0,                0, 0, "on"                  },
  { "repo-cksum",    0,                0, 0, "on"                  },
  { "self-register", 0,                0, 0, "off"                 },
  { "ssh-command",   0,               40, 0, ""                    },
  { "ssh-fossil",    0,               40, 0, ""                    },
  { "ssh-fossil-user",  0,            40, 0, ""                    },
  { "ssl-ca-location",0,              40, 0, ""                    },
  { "ssl-identity",  0,               40, 0, ""                    },
#ifdef FOSSIL_ENABLE_TCL
  { "tcl",           0,                0, 0, "off"                 },
  { "tcl-setup",     0,               40, 0, ""                    },
#endif
  { "th1-setup",     0,               40, 0, ""                    },
2298
2299
2300
2301
2302
2303
2304


2305
2306
2307
2308
2309
2310
2311
**                     "Anonymous" in e.g. ticketing system. On the other hand
**                     users can not be deleted. Default: off.
**
**    ssh-command      Command used to talk to a remote machine with
**                     the "ssh://" protocol.
**
**    ssh-fossil       Remote fossil command to run with the "ssh://" protocol.


**
**    ssl-ca-location  The full pathname to a file containing PEM encoded
**                     CA root certificates, or a directory of certificates
**                     with filenames formed from the certificate hashes as
**                     required by OpenSSL.
**                     If set, this will override the OS default list of
**                     OpenSSL CAs. If unset, the default list will be used.







>
>







2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
**                     "Anonymous" in e.g. ticketing system. On the other hand
**                     users can not be deleted. Default: off.
**
**    ssh-command      Command used to talk to a remote machine with
**                     the "ssh://" protocol.
**
**    ssh-fossil       Remote fossil command to run with the "ssh://" protocol.
**
**    ssh-fossil-user  Fossil user to use instead of the URL user.
**
**    ssl-ca-location  The full pathname to a file containing PEM encoded
**                     CA root certificates, or a directory of certificates
**                     with filenames formed from the certificate hashes as
**                     required by OpenSSL.
**                     If set, this will override the OS default list of
**                     OpenSSL CAs. If unset, the default list will be used.

Changes to src/http.c.

37
38
39
40
41
42
43

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
  Blob nonce;          /* The nonce */
  const char *zLogin;  /* The user login name */
  const char *zPw;     /* The user password */
  Blob pw;             /* The nonce with user password appended */
  Blob sig;            /* The signature field */

  blob_zero(pLogin);

  if( g.urlUser==0 || fossil_strcmp(g.urlUser, "anonymous")==0 ){
     return;  /* If no login card for users "nobody" and "anonymous" */
  }
  blob_zero(&nonce);
  blob_zero(&pw);
  sha1sum_blob(pPayload, &nonce);
  blob_copy(&pw, &nonce);
  zLogin = g.urlUser;
  if( g.urlPasswd ){
    zPw = g.urlPasswd;
  }else if( g.cgiOutput ){
    /* Password failure while doing a sync from the web interface */
    cgi_printf("*** incorrect or missing password for user %h\n", zLogin);
    zPw = 0;
  }else{







>
|
|





|







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
  Blob nonce;          /* The nonce */
  const char *zLogin;  /* The user login name */
  const char *zPw;     /* The user password */
  Blob pw;             /* The nonce with user password appended */
  Blob sig;            /* The signature field */

  blob_zero(pLogin);
  if( g.urlUser==0 && g.zFossilUser==0 || 
      fossil_strcmp(g.urlUser, "anonymous")==0 ){
    return;  /* If no login card for users "nobody" and "anonymous" */
  }
  blob_zero(&nonce);
  blob_zero(&pw);
  sha1sum_blob(pPayload, &nonce);
  blob_copy(&pw, &nonce);
  zLogin = url_or_fossil_user();
  if( g.urlPasswd ){
    zPw = g.urlPasswd;
  }else if( g.cgiOutput ){
    /* Password failure while doing a sync from the web interface */
    cgi_printf("*** incorrect or missing password for user %h\n", zLogin);
    zPw = 0;
  }else{
85
86
87
88
89
90
91

92

93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
** Construct an appropriate HTTP request header.  Write the header
** into pHdr.  This routine initializes the pHdr blob.  pPayload is
** the complete payload (including the login card) already compressed.
*/
static void http_build_header(Blob *pPayload, Blob *pHdr){
  int i;
  const char *zSep;



  blob_zero(pHdr);
  i = strlen(g.urlPath);
  if( i>0 && g.urlPath[i-1]=='/' ){
    zSep = "";
  }else{
    zSep = "/";
  }
  blob_appendf(pHdr, "POST %s%sxfer/xfer HTTP/1.0\r\n", g.urlPath, zSep);
  if( g.urlProxyAuth ){
    blob_appendf(pHdr, "Proxy-Authorization: %s\r\n", g.urlProxyAuth);
  }
  if( g.urlPasswd && g.urlUser && g.urlPasswd[0]=='#' ){
    char *zCredentials = mprintf("%s:%s", g.urlUser, &g.urlPasswd[1]);
    char *zEncoded = encode64(zCredentials, -1);
    blob_appendf(pHdr, "Authorization: Basic %s\r\n", zEncoded);
    fossil_free(zEncoded);
    fossil_free(zCredentials);
  }
  blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname);
  blob_appendf(pHdr, "User-Agent: Fossil/" RELEASE_VERSION 







>

>











|
|







86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
** Construct an appropriate HTTP request header.  Write the header
** into pHdr.  This routine initializes the pHdr blob.  pPayload is
** the complete payload (including the login card) already compressed.
*/
static void http_build_header(Blob *pPayload, Blob *pHdr){
  int i;
  const char *zSep;
  const char *zLogin;

  zLogin = url_or_fossil_user();
  blob_zero(pHdr);
  i = strlen(g.urlPath);
  if( i>0 && g.urlPath[i-1]=='/' ){
    zSep = "";
  }else{
    zSep = "/";
  }
  blob_appendf(pHdr, "POST %s%sxfer/xfer HTTP/1.0\r\n", g.urlPath, zSep);
  if( g.urlProxyAuth ){
    blob_appendf(pHdr, "Proxy-Authorization: %s\r\n", g.urlProxyAuth);
  }
  if( g.urlPasswd && zLogin && g.urlPasswd[0]=='#' ){
    char *zCredentials = mprintf("%s:%s", zLogin, &g.urlPasswd[1]);
    char *zEncoded = encode64(zCredentials, -1);
    blob_appendf(pHdr, "Authorization: Basic %s\r\n", zEncoded);
    fossil_free(zEncoded);
    fossil_free(zCredentials);
  }
  blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname);
  blob_appendf(pHdr, "User-Agent: Fossil/" RELEASE_VERSION 

Changes to src/http_transport.c.

121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
    blob_appendf(&zCmd, " -p %d", g.urlPort);
#endif
  }
  fossil_force_newline();
  fossil_print("%s", blob_str(&zCmd));  /* Show the base of the SSH command */
  if( g.urlUser && g.urlUser[0] ){
    zHost = mprintf("%s@%s", g.urlUser, g.urlName);
#ifdef __MINGW32__
    /* Only win32 (and specifically PLINK.EXE) support the -pw option */
    if( g.urlPasswd && g.urlPasswd[0] ){
      Blob pw;
      blob_zero(&pw);
      if( g.urlPasswd[0]=='*' ){
        char *zPrompt;
        zPrompt = mprintf("Password for [%s]: ", zHost);
        prompt_for_password(zPrompt, &pw, 0);
        free(zPrompt);
      }else{
        blob_init(&pw, g.urlPasswd, -1);
      }
      blob_append(&zCmd, " -pw ", -1);
      shell_escape(&zCmd, blob_str(&pw));
      blob_reset(&pw);
      fossil_print(" -pw ********");  /* Do not show the password text */
    }
#endif
  }else{
    zHost = mprintf("%s", g.urlName);
  }
  n = blob_size(&zCmd);
  blob_append(&zCmd, " ", 1);
  shell_escape(&zCmd, zHost);
  if( g.zSshFossilCmd && g.zSshFossilCmd[0] ){







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







121
122
123
124
125
126
127



















128
129
130
131
132
133
134
    blob_appendf(&zCmd, " -p %d", g.urlPort);
#endif
  }
  fossil_force_newline();
  fossil_print("%s", blob_str(&zCmd));  /* Show the base of the SSH command */
  if( g.urlUser && g.urlUser[0] ){
    zHost = mprintf("%s@%s", g.urlUser, g.urlName);



















  }else{
    zHost = mprintf("%s", g.urlName);
  }
  n = blob_size(&zCmd);
  blob_append(&zCmd, " ", 1);
  shell_escape(&zCmd, zHost);
  if( g.zSshFossilCmd && g.zSshFossilCmd[0] ){

Changes to src/main.c.

134
135
136
137
138
139
140

141
142
143
144
145
146
147
  int fSqlPrint;          /* True if -sqlprint flag is present */
  int fQuiet;             /* True if -quiet flag is present */
  int fHttpTrace;         /* Trace outbound HTTP requests */
  int fSystemTrace;       /* Trace calls to fossil_system(), --systemtrace */
  int fSshTrace;          /* Trace the SSH setup traffic */
  char *zSshFossilCmd;    /* Path to remoe fossil command for SSH */
  char *zSshCmd;          /* SSH command string */

  int fNoSync;            /* Do not do an autosync ever.  --nosync */
  char *zPath;            /* Name of webpage being served */
  char *zExtra;           /* Extra path information past the webpage name */
  char *zBaseURL;         /* Full text of the URL being served */
  char *zTop;             /* Parent directory of zPath */
  const char *zContentType;  /* The content type of the input HTTP request */
  int iErrPriority;       /* Priority of current error message */







>







134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
  int fSqlPrint;          /* True if -sqlprint flag is present */
  int fQuiet;             /* True if -quiet flag is present */
  int fHttpTrace;         /* Trace outbound HTTP requests */
  int fSystemTrace;       /* Trace calls to fossil_system(), --systemtrace */
  int fSshTrace;          /* Trace the SSH setup traffic */
  char *zSshFossilCmd;    /* Path to remoe fossil command for SSH */
  char *zSshCmd;          /* SSH command string */
  char *zFossilUser;      /* Fossil user if different from URL user */
  int fNoSync;            /* Do not do an autosync ever.  --nosync */
  char *zPath;            /* Name of webpage being served */
  char *zExtra;           /* Extra path information past the webpage name */
  char *zBaseURL;         /* Full text of the URL being served */
  char *zTop;             /* Parent directory of zPath */
  const char *zContentType;  /* The content type of the input HTTP request */
  int iErrPriority;       /* Priority of current error message */
578
579
580
581
582
583
584

585
586
587
588
589
590
591
    g.fQuiet = find_option("quiet", 0, 0)!=0;
    g.fSqlTrace = find_option("sqltrace", 0, 0)!=0;
    g.fSqlStats = find_option("sqlstats", 0, 0)!=0;
    g.fSystemTrace = find_option("systemtrace", 0, 0)!=0;
    g.fSshTrace = find_option("sshtrace", 0, 0)!=0;
    g.zSshFossilCmd = 0;
    g.zSshCmd = 0;

    if( g.fSqlTrace ) g.fSqlStats = 1;
    g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
    g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
    g.zLogin = find_option("user", "U", 1);
    g.zSSLIdentity = find_option("ssl-identity", 0, 1);
    if( find_option("utc",0,0) ) g.fTimeFormat = 1;
    if( find_option("localtime",0,0) ) g.fTimeFormat = 2;







>







579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
    g.fQuiet = find_option("quiet", 0, 0)!=0;
    g.fSqlTrace = find_option("sqltrace", 0, 0)!=0;
    g.fSqlStats = find_option("sqlstats", 0, 0)!=0;
    g.fSystemTrace = find_option("systemtrace", 0, 0)!=0;
    g.fSshTrace = find_option("sshtrace", 0, 0)!=0;
    g.zSshFossilCmd = 0;
    g.zSshCmd = 0;
    g.zFossilUser = 0;
    if( g.fSqlTrace ) g.fSqlStats = 1;
    g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
    g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
    g.zLogin = find_option("user", "U", 1);
    g.zSSLIdentity = find_option("ssl-identity", 0, 1);
    if( find_option("utc",0,0) ) g.fTimeFormat = 1;
    if( find_option("localtime",0,0) ) g.fTimeFormat = 2;

Changes to src/sync.c.

47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69


70
71
72
73
74
75
76
77
      return 0;   /* Autosync is completely off */
    }
  }else{
    /* Autosync defaults on.  To make it default off, "return" here. */
  }
  url_parse(0, URL_REMEMBER);
  if( g.urlProtocol==0 ) return 0;  
  if( g.urlUser!=0 && g.urlPasswd==0 ){
    g.urlPasswd = unobscure(db_get("last-sync-pw", 0));
  }
#if 0 /* Disabled for now */
  if( (flags & AUTOSYNC_PULL)!=0 && db_get_boolean("auto-shun",1) ){
    /* When doing an automatic pull, also automatically pull shuns from
    ** the server if pull_shuns is enabled.
    **
    ** TODO:  What happens if the shun list gets really big? 
    ** Maybe the shunning list should only be pulled on every 10th
    ** autosync, or something?
    */
    configSync = CONFIGSET_SHUN;
  }
#endif
  if( find_option("verbose","v",0)!=0 ) flags |= SYNC_VERBOSE;


  fossil_print("Autosync:  %s\n", g.urlCanonical);
  url_enable_proxy("via proxy: ");
  rc = client_sync(flags, configSync, 0);
  if( rc ) fossil_warning("Autosync failed");
  return rc;
}

/*







|















>
>
|







47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
      return 0;   /* Autosync is completely off */
    }
  }else{
    /* Autosync defaults on.  To make it default off, "return" here. */
  }
  url_parse(0, URL_REMEMBER);
  if( g.urlProtocol==0 ) return 0;  
  if( ( g.urlUser!=0 || g.zFossilUser!=0 ) && g.urlPasswd==0 ){
    g.urlPasswd = unobscure(db_get("last-sync-pw", 0));
  }
#if 0 /* Disabled for now */
  if( (flags & AUTOSYNC_PULL)!=0 && db_get_boolean("auto-shun",1) ){
    /* When doing an automatic pull, also automatically pull shuns from
    ** the server if pull_shuns is enabled.
    **
    ** TODO:  What happens if the shun list gets really big? 
    ** Maybe the shunning list should only be pulled on every 10th
    ** autosync, or something?
    */
    configSync = CONFIGSET_SHUN;
  }
#endif
  if( find_option("verbose","v",0)!=0 ) flags |= SYNC_VERBOSE;
  ( g.zFossilUser && g.zFossilUser[0] ) ?
    fossil_print("Autosync: (%s) %s\n", g.zFossilUser, g.urlCanonical) :
    fossil_print("Autosync:  %s\n", g.urlCanonical);
  url_enable_proxy("via proxy: ");
  rc = client_sync(flags, configSync, 0);
  if( rc ) fossil_warning("Autosync failed");
  return rc;
}

/*
100
101
102
103
104
105
106

107
108
109
110
111
112
113
114


115
116


117
118


119
120
121
122
123
124
125
126
  db_find_and_open_repository(0, 0);
  db_open_config(0);
  if( g.argc==2 ){
    if( db_get_boolean("auto-shun",1) ) configSync = CONFIGSET_SHUN;
  }else if( g.argc==3 ){
    zUrl = g.argv[2];
  }

  url_parse(zUrl, urlFlags);
  if( g.urlProtocol==0 ){
    if( urlOptional ) fossil_exit(0);
    usage("URL");
  }
  user_select();
  if( g.argc==2 ){
    if( ((*pSyncFlags) & (SYNC_PUSH|SYNC_PULL))==(SYNC_PUSH|SYNC_PULL) ){


      fossil_print("Sync with %s\n", g.urlCanonical);
    }else if( (*pSyncFlags) & SYNC_PUSH ){


      fossil_print("Push to %s\n", g.urlCanonical);
    }else if( (*pSyncFlags) & SYNC_PULL ){


      fossil_print("Pull from %s\n", g.urlCanonical);
    }
  }
  url_enable_proxy("via proxy: ");
  *pConfigFlags |= configSync;
}

/*







>








>
>
|

>
>
|

>
>
|







102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
  db_find_and_open_repository(0, 0);
  db_open_config(0);
  if( g.argc==2 ){
    if( db_get_boolean("auto-shun",1) ) configSync = CONFIGSET_SHUN;
  }else if( g.argc==3 ){
    zUrl = g.argv[2];
  }
  clone_ssh_db_options();
  url_parse(zUrl, urlFlags);
  if( g.urlProtocol==0 ){
    if( urlOptional ) fossil_exit(0);
    usage("URL");
  }
  user_select();
  if( g.argc==2 ){
    if( ((*pSyncFlags) & (SYNC_PUSH|SYNC_PULL))==(SYNC_PUSH|SYNC_PULL) ){
      ( g.zFossilUser && g.zFossilUser[0] ) ? 
        fossil_print("Sync with (%s) %s\n", g.zFossilUser, g.urlCanonical) :
        fossil_print("Sync with %s\n", g.urlCanonical);
    }else if( (*pSyncFlags) & SYNC_PUSH ){
      ( g.zFossilUser && g.zFossilUser[0] ) ? 
        fossil_print("Push to (%s) %s\n", g.zFossilUser, g.urlCanonical) :
        fossil_print("Push to %s\n", g.urlCanonical);
    }else if( (*pSyncFlags) & SYNC_PULL ){
      ( g.zFossilUser && g.zFossilUser[0] ) ? 
        fossil_print("Pull from (%s) %s\n", g.zFossilUser, g.urlCanonical) :
        fossil_print("Pull from %s\n", g.urlCanonical);
    }
  }
  url_enable_proxy("via proxy: ");
  *pConfigFlags |= configSync;
}

/*

Changes to src/url.c.

195
196
197
198
199
200
201

202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
    file_canonical_name(zFile, &cfile, 0);
    free(zFile);
    g.urlProtocol = "file";
    g.urlPath = "";
    g.urlName = mprintf("%b", &cfile);
    g.urlCanonical = mprintf("file://%T", g.urlName);
    blob_reset(&cfile);

  }else if( g.urlUser!=0 && g.urlPasswd==0 && (urlFlags & URL_PROMPT_PW) ){
    url_prompt_for_password();
    bPrompted = 1;
  }
  if( urlFlags & URL_REMEMBER ){
    if( bSetUrl ){
      db_set("last-sync-url", g.urlCanonical, 0);
    }
    if( !bPrompted && g.urlPasswd && g.urlUser ){
      db_set("last-sync-pw", obscure(g.urlPasswd), 0);
    }
  }
}

/*
** COMMAND: test-urlparser







>
|







|







195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
    file_canonical_name(zFile, &cfile, 0);
    free(zFile);
    g.urlProtocol = "file";
    g.urlPath = "";
    g.urlName = mprintf("%b", &cfile);
    g.urlCanonical = mprintf("file://%T", g.urlName);
    blob_reset(&cfile);
  }else if( ( g.urlUser!=0 || g.zFossilUser!=0 )
            && g.urlPasswd==0 && (urlFlags & URL_PROMPT_PW) ){
    url_prompt_for_password();
    bPrompted = 1;
  }
  if( urlFlags & URL_REMEMBER ){
    if( bSetUrl ){
      db_set("last-sync-url", g.urlCanonical, 0);
    }
    if( !bPrompted && g.urlPasswd && ( g.urlUser || g.zFossilUser ) ){
      db_set("last-sync-pw", obscure(g.urlPasswd), 0);
    }
  }
}

/*
** COMMAND: test-urlparser
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
*/
void url_prompt_for_password(void){
  if( g.urlIsFile ) return;
  if( isatty(fileno(stdin))
   && (g.urlFlags & URL_PROMPT_PW)!=0
   && (g.urlFlags & URL_PROMPTED)==0
  ){
    char *zPrompt = mprintf("\rpassword for %s: ", g.urlUser);
    Blob x;
    fossil_force_newline();
    prompt_for_password(zPrompt, &x, 0);
    free(zPrompt);
    g.urlPasswd = mprintf("%b", &x);
    blob_reset(&x);
    g.urlFlags |= URL_PROMPTED;

    if( g.urlPasswd[0]
     && (g.urlFlags & (URL_REMEMBER|URL_ASK_REMEMBER_PW))!=0
    ){
      char c;
      prompt_user("remember password (Y/n)? ", &x);
      c = blob_str(&x)[0];
      blob_reset(&x);
      if( c!='n' && c!='N' ){
        g.urlFlags |= URL_REMEMBER_PW;
        if( g.urlFlags & URL_REMEMBER ){
          db_set("last-sync-pw", obscure(g.urlPasswd), 0);
        }
      }
    }
  }else{
    fossil_fatal("missing or incorrect password for user \"%s\"",
                 g.urlUser);
  }
}

/*
** Remember the URL if requested.
*/
void url_remember(void){







<
<
<
<
<
<
<

>



<
|
<
<
<








|







411
412
413
414
415
416
417







418
419
420
421
422

423



424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
*/
void url_prompt_for_password(void){
  if( g.urlIsFile ) return;
  if( isatty(fileno(stdin))
   && (g.urlFlags & URL_PROMPT_PW)!=0
   && (g.urlFlags & URL_PROMPTED)==0
  ){







    g.urlFlags |= URL_PROMPTED;
    g.urlPasswd = prompt_for_user_password(url_or_fossil_user());
    if( g.urlPasswd[0]
     && (g.urlFlags & (URL_REMEMBER|URL_ASK_REMEMBER_PW))!=0
    ){

      if( save_password_prompt() ){



        g.urlFlags |= URL_REMEMBER_PW;
        if( g.urlFlags & URL_REMEMBER ){
          db_set("last-sync-pw", obscure(g.urlPasswd), 0);
        }
      }
    }
  }else{
    fossil_fatal("missing or incorrect password for user \"%s\"",
                 url_or_fossil_user() );
  }
}

/*
** Remember the URL if requested.
*/
void url_remember(void){

Changes to src/user.c.

126
127
128
129
130
131
132


































133
134
135
136
137
138
139
      fossil_print("Passphrases do not match.  Try again...\n");
    }else{
      break;
    }
  }
  blob_reset(&secondTry);
}



































/*
** Prompt the user to enter a single line of text.
*/
void prompt_user(const char *zPrompt, Blob *pIn){
  char *z;
  char zLine[1000];







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
      fossil_print("Passphrases do not match.  Try again...\n");
    }else{
      break;
    }
  }
  blob_reset(&secondTry);
}

/*
** Prompt to save Fossil user password
*/
int save_password_prompt(){
  Blob x;
  char c;
  prompt_user("remember password (Y/n)? ", &x);
  c = blob_str(&x)[0];
  blob_reset(&x);
  return ( c!='n' && c!='N' );
}

/*
** Prompt for Fossil user password
*/
char *prompt_for_user_password(const char *zUser){
  char *zPrompt = mprintf("\rpassword for %s: ", zUser);
  char *zPw;
  Blob x;
  fossil_force_newline();
  prompt_for_password(zPrompt, &x, 0);
  free(zPrompt);
  zPw = mprintf("%b", &x);
  blob_reset(&x);
  return zPw;
}

/*
** Return Fossil user if defined or URL user
*/
const char *url_or_fossil_user(void){
  return ( g.zFossilUser && g.zFossilUser[0] ) ? g.zFossilUser : g.urlUser;
}

/*
** Prompt the user to enter a single line of text.
*/
void prompt_user(const char *zPrompt, Blob *pIn){
  char *z;
  char zLine[1000];
317
318
319
320
321
322
323


324
325
326
327
328
329
330
**
**   (6)  Try the LOGNAME environment variable.
**
**   (7)  Try the USERNAME environment variable.
**
**   (8)  Check if the user can be extracted from the remote URL.
**


** The user name is stored in g.zLogin.  The uid is in g.userUid.
*/
void user_select(void){
  if( g.userUid ) return;
  if( g.zLogin ){
    if( attempt_user(g.zLogin)==0 ){
      fossil_fatal("no such user: %s", g.zLogin);







>
>







351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
**
**   (6)  Try the LOGNAME environment variable.
**
**   (7)  Try the USERNAME environment variable.
**
**   (8)  Check if the user can be extracted from the remote URL.
**
**   (9)  Check if the user was supplied as SSH command-line option.
**
** The user name is stored in g.zLogin.  The uid is in g.userUid.
*/
void user_select(void){
  if( g.userUid ) return;
  if( g.zLogin ){
    if( attempt_user(g.zLogin)==0 ){
      fossil_fatal("no such user: %s", g.zLogin);
343
344
345
346
347
348
349


350
351
352
353
354
355
356

  if( attempt_user(fossil_getenv("LOGNAME")) ) return;

  if( attempt_user(fossil_getenv("USERNAME")) ) return;

  url_parse(0, 0);
  if( g.urlUser && attempt_user(g.urlUser) ) return;



  fossil_print(
    "Cannot figure out who you are!  Consider using the --user\n"
    "command line option, setting your USER environment variable,\n"
    "or setting a default user with \"fossil user default USER\".\n"
  );
  fossil_fatal("cannot determine user");







>
>







379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394

  if( attempt_user(fossil_getenv("LOGNAME")) ) return;

  if( attempt_user(fossil_getenv("USERNAME")) ) return;

  url_parse(0, 0);
  if( g.urlUser && attempt_user(g.urlUser) ) return;

  if( g.zFossilUser && attempt_user(g.zFossilUser) ) return;

  fossil_print(
    "Cannot figure out who you are!  Consider using the --user\n"
    "command line option, setting your USER environment variable,\n"
    "or setting a default user with \"fossil user default USER\".\n"
  );
  fossil_fatal("cannot determine user");

Changes to src/xfer.c.

1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
  int nArtifactRcvd = 0;  /* Total artifacts received */
  const char *zOpType = 0;/* Push, Pull, Sync, Clone */

  if( db_get_boolean("dont-push", 0) ) syncFlags &= ~SYNC_PUSH;
  if( (syncFlags & (SYNC_PUSH|SYNC_PULL|SYNC_CLONE))==0 
     && configRcvMask==0 && configSendMask==0 ) return 0;

  clone_ssh_db_options();
  transport_stats(0, 0, 1);
  socket_global_init();
  memset(&xfer, 0, sizeof(xfer));
  xfer.pIn = &recv;
  xfer.pOut = &send;
  xfer.mxSend = db_get_int("max-upload", 250000);
  xfer.maxTime = -1;







<







1334
1335
1336
1337
1338
1339
1340

1341
1342
1343
1344
1345
1346
1347
  int nArtifactRcvd = 0;  /* Total artifacts received */
  const char *zOpType = 0;/* Push, Pull, Sync, Clone */

  if( db_get_boolean("dont-push", 0) ) syncFlags &= ~SYNC_PUSH;
  if( (syncFlags & (SYNC_PUSH|SYNC_PULL|SYNC_CLONE))==0 
     && configRcvMask==0 && configSendMask==0 ) return 0;


  transport_stats(0, 0, 1);
  socket_global_init();
  memset(&xfer, 0, sizeof(xfer));
  xfer.pIn = &recv;
  xfer.pOut = &send;
  xfer.mxSend = db_get_int("max-upload", 250000);
  xfer.maxTime = -1;