Fossil SCM

another patch version for ssh improvement from Andy Bradford.

mgagnon 2013-07-10 21:33 UTC trunk
Commit a8c37c2c48e88875f2e79b33c7a31b07b0f5ba7d
+18
--- src/cgi.c
+++ src/cgi.c
@@ -1493,5 +1493,23 @@
14931493
cgi_set_status(304,"Not Modified");
14941494
cgi_reset_content();
14951495
cgi_reply();
14961496
fossil_exit(0);
14971497
}
1498
+
1499
+/*
1500
+** Check to see if the remote client is SSH and return
1501
+** its IP or return default
1502
+*/
1503
+const char *cgi_ssh_remote_addr(const char *zDefault){
1504
+ char *zIndex;
1505
+ const char *zSshConn = fossil_getenv("SSH_CONNECTION");
1506
+
1507
+ if( zSshConn && zSshConn[0] ){
1508
+ char *zSshClient = mprintf("%s",zSshConn);
1509
+ if( zIndex = strchr(zSshClient,' ') ){
1510
+ zSshClient[zIndex-zSshClient] = '\0';
1511
+ return zSshClient;
1512
+ }
1513
+ }
1514
+ return zDefault;
1515
+}
14981516
--- src/cgi.c
+++ src/cgi.c
@@ -1493,5 +1493,23 @@
1493 cgi_set_status(304,"Not Modified");
1494 cgi_reset_content();
1495 cgi_reply();
1496 fossil_exit(0);
1497 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1498
--- src/cgi.c
+++ src/cgi.c
@@ -1493,5 +1493,23 @@
1493 cgi_set_status(304,"Not Modified");
1494 cgi_reset_content();
1495 cgi_reply();
1496 fossil_exit(0);
1497 }
1498
1499 /*
1500 ** Check to see if the remote client is SSH and return
1501 ** its IP or return default
1502 */
1503 const char *cgi_ssh_remote_addr(const char *zDefault){
1504 char *zIndex;
1505 const char *zSshConn = fossil_getenv("SSH_CONNECTION");
1506
1507 if( zSshConn && zSshConn[0] ){
1508 char *zSshClient = mprintf("%s",zSshConn);
1509 if( zIndex = strchr(zSshClient,' ') ){
1510 zSshClient[zIndex-zSshClient] = '\0';
1511 return zSshClient;
1512 }
1513 }
1514 return zDefault;
1515 }
1516
--- src/clone.c
+++ src/clone.c
@@ -103,10 +103,11 @@
103103
const char *zDefaultUser; /* Optional name of the default user */
104104
int nErr = 0;
105105
int bPrivate = 0; /* Also clone private branches */
106106
107107
if( find_option("private",0,0)!=0 ) bPrivate = SYNC_PRIVATE;
108
+ sync_ssh_options();
108109
url_proxy_options();
109110
if( g.argc < 4 ){
110111
usage("?OPTIONS? FILE-OR-URL NEW-REPOSITORY");
111112
}
112113
db_open_config(0);
@@ -152,10 +153,11 @@
152153
}
153154
db_multi_exec(
154155
"REPLACE INTO config(name,value,mtime)"
155156
" VALUES('server-code', lower(hex(randomblob(20))), now());"
156157
);
158
+ sync_ssh_db_options();
157159
url_enable_proxy(0);
158160
url_get_password_if_needed();
159161
g.xlinkClusterOnly = 1;
160162
nErr = client_sync(SYNC_CLONE | bPrivate,CONFIGSET_ALL,0);
161163
g.xlinkClusterOnly = 0;
162164
--- src/clone.c
+++ src/clone.c
@@ -103,10 +103,11 @@
103 const char *zDefaultUser; /* Optional name of the default user */
104 int nErr = 0;
105 int bPrivate = 0; /* Also clone private branches */
106
107 if( find_option("private",0,0)!=0 ) bPrivate = SYNC_PRIVATE;
 
108 url_proxy_options();
109 if( g.argc < 4 ){
110 usage("?OPTIONS? FILE-OR-URL NEW-REPOSITORY");
111 }
112 db_open_config(0);
@@ -152,10 +153,11 @@
152 }
153 db_multi_exec(
154 "REPLACE INTO config(name,value,mtime)"
155 " VALUES('server-code', lower(hex(randomblob(20))), now());"
156 );
 
157 url_enable_proxy(0);
158 url_get_password_if_needed();
159 g.xlinkClusterOnly = 1;
160 nErr = client_sync(SYNC_CLONE | bPrivate,CONFIGSET_ALL,0);
161 g.xlinkClusterOnly = 0;
162
--- src/clone.c
+++ src/clone.c
@@ -103,10 +103,11 @@
103 const char *zDefaultUser; /* Optional name of the default user */
104 int nErr = 0;
105 int bPrivate = 0; /* Also clone private branches */
106
107 if( find_option("private",0,0)!=0 ) bPrivate = SYNC_PRIVATE;
108 sync_ssh_options();
109 url_proxy_options();
110 if( g.argc < 4 ){
111 usage("?OPTIONS? FILE-OR-URL NEW-REPOSITORY");
112 }
113 db_open_config(0);
@@ -152,10 +153,11 @@
153 }
154 db_multi_exec(
155 "REPLACE INTO config(name,value,mtime)"
156 " VALUES('server-code', lower(hex(randomblob(20))), now());"
157 );
158 sync_ssh_db_options();
159 url_enable_proxy(0);
160 url_get_password_if_needed();
161 g.xlinkClusterOnly = 1;
162 nErr = client_sync(SYNC_CLONE | bPrivate,CONFIGSET_ALL,0);
163 g.xlinkClusterOnly = 0;
164
+2 -2
--- src/http.c
+++ src/http.c
@@ -42,12 +42,12 @@
4242
4343
blob_zero(pLogin);
4444
if( g.urlUser==0 || fossil_strcmp(g.urlUser, "anonymous")==0 ){
4545
return; /* If no login card for users "nobody" and "anonymous" */
4646
}
47
- if( g.urlIsSsh ){
48
- return; /* If no login card for SSH: */
47
+ if( g.urlIsSsh && g.fSshFossilCmd==0 ){
48
+ return; /* If no login card for SSH: */
4949
}
5050
blob_zero(&nonce);
5151
blob_zero(&pw);
5252
sha1sum_blob(pPayload, &nonce);
5353
blob_copy(&pw, &nonce);
5454
--- src/http.c
+++ src/http.c
@@ -42,12 +42,12 @@
42
43 blob_zero(pLogin);
44 if( g.urlUser==0 || fossil_strcmp(g.urlUser, "anonymous")==0 ){
45 return; /* If no login card for users "nobody" and "anonymous" */
46 }
47 if( g.urlIsSsh ){
48 return; /* If no login card for SSH: */
49 }
50 blob_zero(&nonce);
51 blob_zero(&pw);
52 sha1sum_blob(pPayload, &nonce);
53 blob_copy(&pw, &nonce);
54
--- src/http.c
+++ src/http.c
@@ -42,12 +42,12 @@
42
43 blob_zero(pLogin);
44 if( g.urlUser==0 || fossil_strcmp(g.urlUser, "anonymous")==0 ){
45 return; /* If no login card for users "nobody" and "anonymous" */
46 }
47 if( g.urlIsSsh && g.fSshFossilCmd==0 ){
48 return; /* If no login card for SSH: */
49 }
50 blob_zero(&nonce);
51 blob_zero(&pw);
52 sha1sum_blob(pPayload, &nonce);
53 blob_copy(&pw, &nonce);
54
--- src/http_transport.c
+++ src/http_transport.c
@@ -173,85 +173,83 @@
173173
}
174174
fossil_free(zIn);
175175
}
176176
177177
/*
178
-** Global initialization of the transport layer
179
-*/
180
-void transport_global_startup(void){
181
- if( g.urlIsSsh ){
182
- /* Only SSH requires a global initialization. For SSH we need to create
183
- ** and run an SSH command to talk to the remote machine.
184
- */
185
- const char *zSsh; /* The base SSH command */
186
- Blob zCmd; /* The SSH command */
187
- char *zHost; /* The host name to contact */
188
- int n; /* Size of prefix string */
189
-
190
- zSsh = db_get("ssh-command", zDefaultSshCmd);
191
- blob_init(&zCmd, zSsh, -1);
192
- if( g.urlPort!=g.urlDfltPort ){
193
-#ifdef __MINGW32__
194
- blob_appendf(&zCmd, " -P %d", g.urlPort);
195
-#else
196
- blob_appendf(&zCmd, " -p %d", g.urlPort);
197
-#endif
198
- }
199
- fossil_force_newline();
200
- fossil_print("%s", blob_str(&zCmd)); /* Show the base of the SSH command */
201
- if( g.urlUser && g.urlUser[0] ){
202
- zHost = mprintf("%s@%s", g.urlUser, g.urlName);
203
-#ifdef __MINGW32__
204
- /* Only win32 (and specifically PLINK.EXE) support the -pw option */
205
- if( g.urlPasswd && g.urlPasswd[0] ){
206
- Blob pw;
207
- blob_zero(&pw);
208
- if( g.urlPasswd[0]=='*' ){
209
- char *zPrompt;
210
- zPrompt = mprintf("Password for [%s]: ", zHost);
211
- prompt_for_password(zPrompt, &pw, 0);
212
- free(zPrompt);
213
- }else{
214
- blob_init(&pw, g.urlPasswd, -1);
215
- }
216
- blob_append(&zCmd, " -pw ", -1);
217
- shell_escape(&zCmd, blob_str(&pw));
218
- blob_reset(&pw);
219
- fossil_print(" -pw ********"); /* Do not show the password text */
220
- }
221
-#endif
222
- }else{
223
- zHost = mprintf("%s", g.urlName);
224
- }
225
- n = blob_size(&zCmd);
226
- blob_append(&zCmd, " ", 1);
227
- shell_escape(&zCmd, zHost);
228
- if( g.urlShell ){
229
- blob_appendf(&zCmd, " %s", g.urlShell);
230
- }else{
231
-#if defined(FOSSIL_ENABLE_SSH_FAR_SIDE)
232
- /* The following works. But only if the fossil on the remote side
233
- ** is recent enough to support the test-ssh-far-side command. That
234
- ** command was added on 2013-02-06. We will leave this turned off
235
- ** until most fossil servers have upgraded to that version or a later
236
- ** version. The sync will still work as long as the shell on the far
237
- ** side is bash and not tcsh. And if the default far side shell is
238
- ** tcsh, then the shell=/bin/bash query parameter can be used as a
239
- ** work-around. Enable this code after about a year...
240
- */
241
- blob_appendf(&zCmd, " exec %s test-ssh-far-side", g.urlFossil);
242
-#endif
243
- }
244
- fossil_print("%s\n", blob_str(&zCmd)+n); /* Show tail of SSH command */
245
- free(zHost);
246
- popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid);
247
- if( sshPid==0 ){
248
- fossil_fatal("cannot start ssh tunnel using [%b]", &zCmd);
249
- }
250
- blob_reset(&zCmd);
178
+** SSH initialization of the transport layer
179
+*/
180
+int transport_ssh_open(void){
181
+ /* For SSH we need to create and run an SSH http
182
+ ** to talk to the remote machine.
183
+ */
184
+ const char *zSsh; /* The base SSH command */
185
+ Blob zCmd; /* The SSH command */
186
+ char *zHost; /* The host name to contact */
187
+ char *zPath; /* The path to the remote file for SSH */
188
+ int n; /* Size of prefix string */
189
+
190
+ zSsh = db_get("ssh-command", zDefaultSshCmd);
191
+ blob_init(&zCmd, zSsh, -1);
192
+ if( g.urlPort!=g.urlDfltPort ){
193
+#ifdef __MINGW32__
194
+ blob_appendf(&zCmd, " -P %d", g.urlPort);
195
+#else
196
+ blob_appendf(&zCmd, " -p %d", g.urlPort);
197
+#endif
198
+ }
199
+ fossil_force_newline();
200
+ fossil_print("%s", blob_str(&zCmd)); /* Show the base of the SSH command */
201
+ if( g.urlUser && g.urlUser[0] ){
202
+ zHost = mprintf("%s@%s", g.urlUser, g.urlName);
203
+#ifdef __MINGW32__
204
+ /* Only win32 (and specifically PLINK.EXE) support the -pw option */
205
+ if( g.urlPasswd && g.urlPasswd[0] ){
206
+ Blob pw;
207
+ blob_zero(&pw);
208
+ if( g.urlPasswd[0]=='*' ){
209
+ char *zPrompt;
210
+ zPrompt = mprintf("Password for [%s]: ", zHost);
211
+ prompt_for_password(zPrompt, &pw, 0);
212
+ free(zPrompt);
213
+ }else{
214
+ blob_init(&pw, g.urlPasswd, -1);
215
+ }
216
+ blob_append(&zCmd, " -pw ", -1);
217
+ shell_escape(&zCmd, blob_str(&pw));
218
+ blob_reset(&pw);
219
+ fossil_print(" -pw ********"); /* Do not show the password text */
220
+ }
221
+#endif
222
+ }else{
223
+ zHost = mprintf("%s", g.urlName);
224
+ }
225
+ n = blob_size(&zCmd);
226
+ blob_append(&zCmd, " ", 1);
227
+ shell_escape(&zCmd, zHost);
228
+ if( g.urlShell ){
229
+ blob_appendf(&zCmd, " %s", g.urlShell);
230
+ }
231
+ if( g.fSshFossilCmd && g.fSshFossilCmd[0] ){
232
+ blob_append(&zCmd, " ", 1);
233
+ shell_escape(&zCmd, g.fSshFossilCmd);
234
+ blob_appendf(&zCmd, " %s ", g.fSshHttpCmd);
235
+ if( g.urlPath && g.urlPath[0] ){
236
+ zPath = mprintf("%s", g.urlPath);
237
+ shell_escape(&zCmd, zPath);
238
+ }
239
+ }
240
+ fossil_print("%s\n", blob_str(&zCmd)+n); /* Show tail of SSH command */
241
+ free(zHost);
242
+ popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid);
243
+ if( sshPid==0 ){
244
+ socket_set_errmsg("cannot start ssh tunnel using [%b]", &zCmd);
245
+ }
246
+ blob_reset(&zCmd);
247
+ if( g.fSshFossilCmd==0 ){
251248
transport_ssh_startup();
252249
}
250
+ return sshPid==0;
253251
}
254252
255253
/*
256254
** COMMAND: test-ssh-far-side
257255
**
@@ -287,11 +285,17 @@
287285
** Return the number of errors.
288286
*/
289287
int transport_open(void){
290288
int rc = 0;
291289
if( transport.isOpen==0 ){
292
- if( g.urlIsSsh ){
290
+ if( g.urlIsSsh && g.fSshFossilCmd ){
291
+ rc = transport_ssh_open();
292
+ if( rc==0 ) transport.isOpen = 1;
293
+ }else if( g.urlIsSsh ){
294
+ if( sshPid==0 ){
295
+ rc = transport_ssh_open();
296
+ }
293297
Blob cmd;
294298
blob_zero(&cmd);
295299
shell_escape(&cmd, g.urlFossil);
296300
blob_append(&cmd, " test-http ", -1);
297301
shell_escape(&cmd, g.urlPath);
@@ -339,12 +343,14 @@
339343
transport.iCursor = 0;
340344
if( transport.pLog ){
341345
fclose(transport.pLog);
342346
transport.pLog = 0;
343347
}
344
- if( g.urlIsSsh ){
345
- /* No-op */
348
+ if( g.urlIsSsh && g.fSshFossilCmd ){
349
+ transport_ssh_close();
350
+ }else if( g.urlIsSsh ){
351
+ /* no-op */
346352
}else if( g.urlIsHttps ){
347353
#ifdef FOSSIL_ENABLE_SSL
348354
ssl_close();
349355
#endif
350356
}else if( g.urlIsFile ){
@@ -582,19 +588,23 @@
582588
if( g.fSshTrace ) printf("Got line: [%s]\n", &transport.pBuf[iStart]);
583589
return &transport.pBuf[iStart];
584590
}
585591
586592
void transport_global_shutdown(void){
587
- if( g.urlIsSsh && sshPid ){
588
- /*printf("Closing SSH tunnel: ");*/
589
- fflush(stdout);
590
- pclose2(sshIn, sshOut, sshPid);
591
- sshPid = 0;
592
- }
593
+ transport_ssh_close();
593594
if( g.urlIsHttps ){
594595
#ifdef FOSSIL_ENABLE_SSL
595596
ssl_global_shutdown();
596597
#endif
597598
}else{
598599
socket_global_shutdown();
599600
}
600601
}
602
+
603
+void transport_ssh_close(void){
604
+ if( g.urlIsSsh && sshPid ){
605
+ /*printf("Closing SSH tunnel: ");*/
606
+ fflush(stdout);
607
+ pclose2(sshIn, sshOut, sshPid);
608
+ sshPid = 0;
609
+ }
610
+}
601611
--- src/http_transport.c
+++ src/http_transport.c
@@ -173,85 +173,83 @@
173 }
174 fossil_free(zIn);
175 }
176
177 /*
178 ** Global initialization of the transport layer
179 */
180 void transport_global_startup(void){
181 if( g.urlIsSsh ){
182 /* Only SSH requires a global initialization. For SSH we need to create
183 ** and run an SSH command to talk to the remote machine.
184 */
185 const char *zSsh; /* The base SSH command */
186 Blob zCmd; /* The SSH command */
187 char *zHost; /* The host name to contact */
188 int n; /* Size of prefix string */
189
190 zSsh = db_get("ssh-command", zDefaultSshCmd);
191 blob_init(&zCmd, zSsh, -1);
192 if( g.urlPort!=g.urlDfltPort ){
193 #ifdef __MINGW32__
194 blob_appendf(&zCmd, " -P %d", g.urlPort);
195 #else
196 blob_appendf(&zCmd, " -p %d", g.urlPort);
197 #endif
198 }
199 fossil_force_newline();
200 fossil_print("%s", blob_str(&zCmd)); /* Show the base of the SSH command */
201 if( g.urlUser && g.urlUser[0] ){
202 zHost = mprintf("%s@%s", g.urlUser, g.urlName);
203 #ifdef __MINGW32__
204 /* Only win32 (and specifically PLINK.EXE) support the -pw option */
205 if( g.urlPasswd && g.urlPasswd[0] ){
206 Blob pw;
207 blob_zero(&pw);
208 if( g.urlPasswd[0]=='*' ){
209 char *zPrompt;
210 zPrompt = mprintf("Password for [%s]: ", zHost);
211 prompt_for_password(zPrompt, &pw, 0);
212 free(zPrompt);
213 }else{
214 blob_init(&pw, g.urlPasswd, -1);
215 }
216 blob_append(&zCmd, " -pw ", -1);
217 shell_escape(&zCmd, blob_str(&pw));
218 blob_reset(&pw);
219 fossil_print(" -pw ********"); /* Do not show the password text */
220 }
221 #endif
222 }else{
223 zHost = mprintf("%s", g.urlName);
224 }
225 n = blob_size(&zCmd);
226 blob_append(&zCmd, " ", 1);
227 shell_escape(&zCmd, zHost);
228 if( g.urlShell ){
229 blob_appendf(&zCmd, " %s", g.urlShell);
230 }else{
231 #if defined(FOSSIL_ENABLE_SSH_FAR_SIDE)
232 /* The following works. But only if the fossil on the remote side
233 ** is recent enough to support the test-ssh-far-side command. That
234 ** command was added on 2013-02-06. We will leave this turned off
235 ** until most fossil servers have upgraded to that version or a later
236 ** version. The sync will still work as long as the shell on the far
237 ** side is bash and not tcsh. And if the default far side shell is
238 ** tcsh, then the shell=/bin/bash query parameter can be used as a
239 ** work-around. Enable this code after about a year...
240 */
241 blob_appendf(&zCmd, " exec %s test-ssh-far-side", g.urlFossil);
242 #endif
243 }
244 fossil_print("%s\n", blob_str(&zCmd)+n); /* Show tail of SSH command */
245 free(zHost);
246 popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid);
247 if( sshPid==0 ){
248 fossil_fatal("cannot start ssh tunnel using [%b]", &zCmd);
249 }
250 blob_reset(&zCmd);
251 transport_ssh_startup();
252 }
 
253 }
254
255 /*
256 ** COMMAND: test-ssh-far-side
257 **
@@ -287,11 +285,17 @@
287 ** Return the number of errors.
288 */
289 int transport_open(void){
290 int rc = 0;
291 if( transport.isOpen==0 ){
292 if( g.urlIsSsh ){
 
 
 
 
 
 
293 Blob cmd;
294 blob_zero(&cmd);
295 shell_escape(&cmd, g.urlFossil);
296 blob_append(&cmd, " test-http ", -1);
297 shell_escape(&cmd, g.urlPath);
@@ -339,12 +343,14 @@
339 transport.iCursor = 0;
340 if( transport.pLog ){
341 fclose(transport.pLog);
342 transport.pLog = 0;
343 }
344 if( g.urlIsSsh ){
345 /* No-op */
 
 
346 }else if( g.urlIsHttps ){
347 #ifdef FOSSIL_ENABLE_SSL
348 ssl_close();
349 #endif
350 }else if( g.urlIsFile ){
@@ -582,19 +588,23 @@
582 if( g.fSshTrace ) printf("Got line: [%s]\n", &transport.pBuf[iStart]);
583 return &transport.pBuf[iStart];
584 }
585
586 void transport_global_shutdown(void){
587 if( g.urlIsSsh && sshPid ){
588 /*printf("Closing SSH tunnel: ");*/
589 fflush(stdout);
590 pclose2(sshIn, sshOut, sshPid);
591 sshPid = 0;
592 }
593 if( g.urlIsHttps ){
594 #ifdef FOSSIL_ENABLE_SSL
595 ssl_global_shutdown();
596 #endif
597 }else{
598 socket_global_shutdown();
599 }
600 }
 
 
 
 
 
 
 
 
 
601
--- src/http_transport.c
+++ src/http_transport.c
@@ -173,85 +173,83 @@
173 }
174 fossil_free(zIn);
175 }
176
177 /*
178 ** SSH initialization of the transport layer
179 */
180 int transport_ssh_open(void){
181 /* For SSH we need to create and run an SSH http
182 ** to talk to the remote machine.
183 */
184 const char *zSsh; /* The base SSH command */
185 Blob zCmd; /* The SSH command */
186 char *zHost; /* The host name to contact */
187 char *zPath; /* The path to the remote file for SSH */
188 int n; /* Size of prefix string */
189
190 zSsh = db_get("ssh-command", zDefaultSshCmd);
191 blob_init(&zCmd, zSsh, -1);
192 if( g.urlPort!=g.urlDfltPort ){
193 #ifdef __MINGW32__
194 blob_appendf(&zCmd, " -P %d", g.urlPort);
195 #else
196 blob_appendf(&zCmd, " -p %d", g.urlPort);
197 #endif
198 }
199 fossil_force_newline();
200 fossil_print("%s", blob_str(&zCmd)); /* Show the base of the SSH command */
201 if( g.urlUser && g.urlUser[0] ){
202 zHost = mprintf("%s@%s", g.urlUser, g.urlName);
203 #ifdef __MINGW32__
204 /* Only win32 (and specifically PLINK.EXE) support the -pw option */
205 if( g.urlPasswd && g.urlPasswd[0] ){
206 Blob pw;
207 blob_zero(&pw);
208 if( g.urlPasswd[0]=='*' ){
209 char *zPrompt;
210 zPrompt = mprintf("Password for [%s]: ", zHost);
211 prompt_for_password(zPrompt, &pw, 0);
212 free(zPrompt);
213 }else{
214 blob_init(&pw, g.urlPasswd, -1);
215 }
216 blob_append(&zCmd, " -pw ", -1);
217 shell_escape(&zCmd, blob_str(&pw));
218 blob_reset(&pw);
219 fossil_print(" -pw ********"); /* Do not show the password text */
220 }
221 #endif
222 }else{
223 zHost = mprintf("%s", g.urlName);
224 }
225 n = blob_size(&zCmd);
226 blob_append(&zCmd, " ", 1);
227 shell_escape(&zCmd, zHost);
228 if( g.urlShell ){
229 blob_appendf(&zCmd, " %s", g.urlShell);
230 }
231 if( g.fSshFossilCmd && g.fSshFossilCmd[0] ){
232 blob_append(&zCmd, " ", 1);
233 shell_escape(&zCmd, g.fSshFossilCmd);
234 blob_appendf(&zCmd, " %s ", g.fSshHttpCmd);
235 if( g.urlPath && g.urlPath[0] ){
236 zPath = mprintf("%s", g.urlPath);
237 shell_escape(&zCmd, zPath);
238 }
239 }
240 fossil_print("%s\n", blob_str(&zCmd)+n); /* Show tail of SSH command */
241 free(zHost);
242 popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid);
243 if( sshPid==0 ){
244 socket_set_errmsg("cannot start ssh tunnel using [%b]", &zCmd);
245 }
246 blob_reset(&zCmd);
247 if( g.fSshFossilCmd==0 ){
 
 
 
248 transport_ssh_startup();
249 }
250 return sshPid==0;
251 }
252
253 /*
254 ** COMMAND: test-ssh-far-side
255 **
@@ -287,11 +285,17 @@
285 ** Return the number of errors.
286 */
287 int transport_open(void){
288 int rc = 0;
289 if( transport.isOpen==0 ){
290 if( g.urlIsSsh && g.fSshFossilCmd ){
291 rc = transport_ssh_open();
292 if( rc==0 ) transport.isOpen = 1;
293 }else if( g.urlIsSsh ){
294 if( sshPid==0 ){
295 rc = transport_ssh_open();
296 }
297 Blob cmd;
298 blob_zero(&cmd);
299 shell_escape(&cmd, g.urlFossil);
300 blob_append(&cmd, " test-http ", -1);
301 shell_escape(&cmd, g.urlPath);
@@ -339,12 +343,14 @@
343 transport.iCursor = 0;
344 if( transport.pLog ){
345 fclose(transport.pLog);
346 transport.pLog = 0;
347 }
348 if( g.urlIsSsh && g.fSshFossilCmd ){
349 transport_ssh_close();
350 }else if( g.urlIsSsh ){
351 /* no-op */
352 }else if( g.urlIsHttps ){
353 #ifdef FOSSIL_ENABLE_SSL
354 ssl_close();
355 #endif
356 }else if( g.urlIsFile ){
@@ -582,19 +588,23 @@
588 if( g.fSshTrace ) printf("Got line: [%s]\n", &transport.pBuf[iStart]);
589 return &transport.pBuf[iStart];
590 }
591
592 void transport_global_shutdown(void){
593 transport_ssh_close();
 
 
 
 
 
594 if( g.urlIsHttps ){
595 #ifdef FOSSIL_ENABLE_SSL
596 ssl_global_shutdown();
597 #endif
598 }else{
599 socket_global_shutdown();
600 }
601 }
602
603 void transport_ssh_close(void){
604 if( g.urlIsSsh && sshPid ){
605 /*printf("Closing SSH tunnel: ");*/
606 fflush(stdout);
607 pclose2(sshIn, sshOut, sshPid);
608 sshPid = 0;
609 }
610 }
611
+11 -2
--- src/main.c
+++ src/main.c
@@ -134,10 +134,13 @@
134134
int fSqlPrint; /* True if -sqlprint flag is present */
135135
int fQuiet; /* True if -quiet flag is present */
136136
int fHttpTrace; /* Trace outbound HTTP requests */
137137
int fSystemTrace; /* Trace calls to fossil_system(), --systemtrace */
138138
int fSshTrace; /* Trace the SSH setup traffic */
139
+ char *fSshFossilCmd; /* Path to remoe fossil command for SSH */
140
+ char *fSshHttpCmd; /* Which http command to use for SSH */
141
+ char *fSshCmd; /* SSH command string */
139142
int fNoSync; /* Do not do an autosync ever. --nosync */
140143
char *zPath; /* Name of webpage being served */
141144
char *zExtra; /* Extra path information past the webpage name */
142145
char *zBaseURL; /* Full text of the URL being served */
143146
char *zTop; /* Parent directory of zPath */
@@ -578,10 +581,13 @@
578581
g.fQuiet = find_option("quiet", 0, 0)!=0;
579582
g.fSqlTrace = find_option("sqltrace", 0, 0)!=0;
580583
g.fSqlStats = find_option("sqlstats", 0, 0)!=0;
581584
g.fSystemTrace = find_option("systemtrace", 0, 0)!=0;
582585
g.fSshTrace = find_option("sshtrace", 0, 0)!=0;
586
+ g.fSshFossilCmd = 0;
587
+ g.fSshHttpCmd = 0;
588
+ g.fSshCmd = 0;
583589
if( g.fSqlTrace ) g.fSqlStats = 1;
584590
g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
585591
g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
586592
g.zLogin = find_option("user", "U", 1);
587593
g.zSSLIdentity = find_option("ssl-identity", 0, 1);
@@ -623,10 +629,11 @@
623629
"%s: could be any of:%s\n"
624630
"%s: use \"help\" for more information\n",
625631
g.argv[0], zCmdName, g.argv[0], blob_str(&couldbe), g.argv[0]);
626632
fossil_exit(1);
627633
}
634
+ signal(SIGPIPE,SIG_IGN);
628635
atexit( fossil_atexit );
629636
aCommand[idx].xFunc();
630637
fossil_exit(0);
631638
/*NOT_REACHED*/
632639
return 0;
@@ -1685,10 +1692,13 @@
16851692
}else{
16861693
g.httpIn = stdin;
16871694
g.httpOut = stdout;
16881695
zIpAddr = 0;
16891696
}
1697
+ if( zIpAddr==0 ){
1698
+ zIpAddr = cgi_ssh_remote_addr(0);
1699
+ }
16901700
find_server_repository(0);
16911701
g.zRepositoryName = enter_chroot_jail(g.zRepositoryName);
16921702
cgi_handle_http_request(zIpAddr);
16931703
process_one_web_page(zNotFound, glob_create(zFileGlob));
16941704
}
@@ -1701,17 +1711,16 @@
17011711
*/
17021712
void cmd_test_http(void){
17031713
Th_InitTraceLog();
17041714
login_set_capabilities("sx", 0);
17051715
g.useLocalauth = 1;
1706
- cgi_set_parameter("REMOTE_ADDR", "127.0.0.1");
17071716
g.httpIn = stdin;
17081717
g.httpOut = stdout;
17091718
find_server_repository(0);
17101719
g.cgiOutput = 1;
17111720
g.fullHttpReply = 1;
1712
- cgi_handle_http_request(0);
1721
+ cgi_handle_http_request(cgi_ssh_remote_addr("127.0.0.1"));
17131722
process_one_web_page(0, 0);
17141723
}
17151724
17161725
#if !defined(_WIN32)
17171726
#if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
17181727
--- src/main.c
+++ src/main.c
@@ -134,10 +134,13 @@
134 int fSqlPrint; /* True if -sqlprint flag is present */
135 int fQuiet; /* True if -quiet flag is present */
136 int fHttpTrace; /* Trace outbound HTTP requests */
137 int fSystemTrace; /* Trace calls to fossil_system(), --systemtrace */
138 int fSshTrace; /* Trace the SSH setup traffic */
 
 
 
139 int fNoSync; /* Do not do an autosync ever. --nosync */
140 char *zPath; /* Name of webpage being served */
141 char *zExtra; /* Extra path information past the webpage name */
142 char *zBaseURL; /* Full text of the URL being served */
143 char *zTop; /* Parent directory of zPath */
@@ -578,10 +581,13 @@
578 g.fQuiet = find_option("quiet", 0, 0)!=0;
579 g.fSqlTrace = find_option("sqltrace", 0, 0)!=0;
580 g.fSqlStats = find_option("sqlstats", 0, 0)!=0;
581 g.fSystemTrace = find_option("systemtrace", 0, 0)!=0;
582 g.fSshTrace = find_option("sshtrace", 0, 0)!=0;
 
 
 
583 if( g.fSqlTrace ) g.fSqlStats = 1;
584 g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
585 g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
586 g.zLogin = find_option("user", "U", 1);
587 g.zSSLIdentity = find_option("ssl-identity", 0, 1);
@@ -623,10 +629,11 @@
623 "%s: could be any of:%s\n"
624 "%s: use \"help\" for more information\n",
625 g.argv[0], zCmdName, g.argv[0], blob_str(&couldbe), g.argv[0]);
626 fossil_exit(1);
627 }
 
628 atexit( fossil_atexit );
629 aCommand[idx].xFunc();
630 fossil_exit(0);
631 /*NOT_REACHED*/
632 return 0;
@@ -1685,10 +1692,13 @@
1685 }else{
1686 g.httpIn = stdin;
1687 g.httpOut = stdout;
1688 zIpAddr = 0;
1689 }
 
 
 
1690 find_server_repository(0);
1691 g.zRepositoryName = enter_chroot_jail(g.zRepositoryName);
1692 cgi_handle_http_request(zIpAddr);
1693 process_one_web_page(zNotFound, glob_create(zFileGlob));
1694 }
@@ -1701,17 +1711,16 @@
1701 */
1702 void cmd_test_http(void){
1703 Th_InitTraceLog();
1704 login_set_capabilities("sx", 0);
1705 g.useLocalauth = 1;
1706 cgi_set_parameter("REMOTE_ADDR", "127.0.0.1");
1707 g.httpIn = stdin;
1708 g.httpOut = stdout;
1709 find_server_repository(0);
1710 g.cgiOutput = 1;
1711 g.fullHttpReply = 1;
1712 cgi_handle_http_request(0);
1713 process_one_web_page(0, 0);
1714 }
1715
1716 #if !defined(_WIN32)
1717 #if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
1718
--- src/main.c
+++ src/main.c
@@ -134,10 +134,13 @@
134 int fSqlPrint; /* True if -sqlprint flag is present */
135 int fQuiet; /* True if -quiet flag is present */
136 int fHttpTrace; /* Trace outbound HTTP requests */
137 int fSystemTrace; /* Trace calls to fossil_system(), --systemtrace */
138 int fSshTrace; /* Trace the SSH setup traffic */
139 char *fSshFossilCmd; /* Path to remoe fossil command for SSH */
140 char *fSshHttpCmd; /* Which http command to use for SSH */
141 char *fSshCmd; /* SSH command string */
142 int fNoSync; /* Do not do an autosync ever. --nosync */
143 char *zPath; /* Name of webpage being served */
144 char *zExtra; /* Extra path information past the webpage name */
145 char *zBaseURL; /* Full text of the URL being served */
146 char *zTop; /* Parent directory of zPath */
@@ -578,10 +581,13 @@
581 g.fQuiet = find_option("quiet", 0, 0)!=0;
582 g.fSqlTrace = find_option("sqltrace", 0, 0)!=0;
583 g.fSqlStats = find_option("sqlstats", 0, 0)!=0;
584 g.fSystemTrace = find_option("systemtrace", 0, 0)!=0;
585 g.fSshTrace = find_option("sshtrace", 0, 0)!=0;
586 g.fSshFossilCmd = 0;
587 g.fSshHttpCmd = 0;
588 g.fSshCmd = 0;
589 if( g.fSqlTrace ) g.fSqlStats = 1;
590 g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
591 g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
592 g.zLogin = find_option("user", "U", 1);
593 g.zSSLIdentity = find_option("ssl-identity", 0, 1);
@@ -623,10 +629,11 @@
629 "%s: could be any of:%s\n"
630 "%s: use \"help\" for more information\n",
631 g.argv[0], zCmdName, g.argv[0], blob_str(&couldbe), g.argv[0]);
632 fossil_exit(1);
633 }
634 signal(SIGPIPE,SIG_IGN);
635 atexit( fossil_atexit );
636 aCommand[idx].xFunc();
637 fossil_exit(0);
638 /*NOT_REACHED*/
639 return 0;
@@ -1685,10 +1692,13 @@
1692 }else{
1693 g.httpIn = stdin;
1694 g.httpOut = stdout;
1695 zIpAddr = 0;
1696 }
1697 if( zIpAddr==0 ){
1698 zIpAddr = cgi_ssh_remote_addr(0);
1699 }
1700 find_server_repository(0);
1701 g.zRepositoryName = enter_chroot_jail(g.zRepositoryName);
1702 cgi_handle_http_request(zIpAddr);
1703 process_one_web_page(zNotFound, glob_create(zFileGlob));
1704 }
@@ -1701,17 +1711,16 @@
1711 */
1712 void cmd_test_http(void){
1713 Th_InitTraceLog();
1714 login_set_capabilities("sx", 0);
1715 g.useLocalauth = 1;
 
1716 g.httpIn = stdin;
1717 g.httpOut = stdout;
1718 find_server_repository(0);
1719 g.cgiOutput = 1;
1720 g.fullHttpReply = 1;
1721 cgi_handle_http_request(cgi_ssh_remote_addr("127.0.0.1"));
1722 process_one_web_page(0, 0);
1723 }
1724
1725 #if !defined(_WIN32)
1726 #if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
1727
+42
--- src/sync.c
+++ src/sync.c
@@ -147,10 +147,11 @@
147147
*/
148148
void pull_cmd(void){
149149
unsigned configFlags = 0;
150150
unsigned syncFlags = SYNC_PULL;
151151
process_sync_args(&configFlags, &syncFlags);
152
+ sync_ssh_options();
152153
client_sync(syncFlags, configFlags, 0);
153154
}
154155
155156
/*
156157
** COMMAND: push
@@ -176,10 +177,11 @@
176177
*/
177178
void push_cmd(void){
178179
unsigned configFlags = 0;
179180
unsigned syncFlags = SYNC_PUSH;
180181
process_sync_args(&configFlags, &syncFlags);
182
+ sync_ssh_options();
181183
if( db_get_boolean("dont-push",0) ){
182184
fossil_fatal("pushing is prohibited: the 'dont-push' option is set");
183185
}
184186
client_sync(syncFlags, 0, 0);
185187
}
@@ -214,11 +216,13 @@
214216
*/
215217
void sync_cmd(void){
216218
unsigned configFlags = 0;
217219
unsigned syncFlags = SYNC_PUSH|SYNC_PULL;
218220
process_sync_args(&configFlags, &syncFlags);
221
+ sync_ssh_options();
219222
if( db_get_boolean("dont-push",0) ) syncFlags &= ~SYNC_PUSH;
223
+ sync_ssh_db_options();
220224
client_sync(syncFlags, configFlags, 0);
221225
if( (syncFlags & SYNC_PUSH)==0 ){
222226
fossil_warning("pull only: the 'dont-push' option is set");
223227
}
224228
}
@@ -257,5 +261,43 @@
257261
}else{
258262
url_parse(zUrl, 0);
259263
fossil_print("%s\n", g.urlCanonical);
260264
}
261265
}
266
+
267
+void sync_ssh_options(void){
268
+ const char *zSshFossilCmd; /* Path to remote fossil command for SSH */
269
+ const char *zSshHttpCmd; /* Name of remote HTTP command for SSH */
270
+ const char *zSshCmd; /* Name of remote HTTP command for SSH */
271
+
272
+ zSshFossilCmd = find_option("sshfossilcmd","f",1);
273
+ if( zSshFossilCmd && zSshFossilCmd[0] ){
274
+ g.fSshFossilCmd = mprintf("%s", zSshFossilCmd);
275
+ }
276
+ zSshHttpCmd = find_option("sshhttpcmd","h",1);
277
+ if( zSshHttpCmd && zSshHttpCmd[0] ){
278
+ g.fSshHttpCmd = mprintf("%s", zSshHttpCmd);
279
+ if( zSshFossilCmd==0 ){
280
+ g.fSshFossilCmd = "fossil";
281
+ }
282
+ }
283
+ zSshCmd = find_option("sshcmd","s",1);
284
+ if( zSshCmd && zSshCmd[0] ){
285
+ g.fSshCmd = mprintf("%s", zSshCmd);
286
+ }
287
+}
288
+
289
+void sync_ssh_db_options(void){
290
+ if( g.fSshFossilCmd && g.fSshFossilCmd[0] ){
291
+ db_set("last-ssh-fossil-cmd", g.fSshFossilCmd, 0);
292
+ }else{
293
+ g.fSshFossilCmd = db_get("last-ssh-fossil-cmd", 0);
294
+ }
295
+ if( g.fSshHttpCmd && g.fSshHttpCmd[0] ){
296
+ db_set("last-ssh-http-cmd", g.fSshHttpCmd, 0);
297
+ }else{
298
+ g.fSshHttpCmd = db_get("last-ssh-http-cmd", "test-http");
299
+ }
300
+ if( g.fSshCmd && g.fSshCmd[0] ){
301
+ db_set("ssh-command", g.fSshCmd, 0);
302
+ }
303
+}
262304
--- src/sync.c
+++ src/sync.c
@@ -147,10 +147,11 @@
147 */
148 void pull_cmd(void){
149 unsigned configFlags = 0;
150 unsigned syncFlags = SYNC_PULL;
151 process_sync_args(&configFlags, &syncFlags);
 
152 client_sync(syncFlags, configFlags, 0);
153 }
154
155 /*
156 ** COMMAND: push
@@ -176,10 +177,11 @@
176 */
177 void push_cmd(void){
178 unsigned configFlags = 0;
179 unsigned syncFlags = SYNC_PUSH;
180 process_sync_args(&configFlags, &syncFlags);
 
181 if( db_get_boolean("dont-push",0) ){
182 fossil_fatal("pushing is prohibited: the 'dont-push' option is set");
183 }
184 client_sync(syncFlags, 0, 0);
185 }
@@ -214,11 +216,13 @@
214 */
215 void sync_cmd(void){
216 unsigned configFlags = 0;
217 unsigned syncFlags = SYNC_PUSH|SYNC_PULL;
218 process_sync_args(&configFlags, &syncFlags);
 
219 if( db_get_boolean("dont-push",0) ) syncFlags &= ~SYNC_PUSH;
 
220 client_sync(syncFlags, configFlags, 0);
221 if( (syncFlags & SYNC_PUSH)==0 ){
222 fossil_warning("pull only: the 'dont-push' option is set");
223 }
224 }
@@ -257,5 +261,43 @@
257 }else{
258 url_parse(zUrl, 0);
259 fossil_print("%s\n", g.urlCanonical);
260 }
261 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
262
--- src/sync.c
+++ src/sync.c
@@ -147,10 +147,11 @@
147 */
148 void pull_cmd(void){
149 unsigned configFlags = 0;
150 unsigned syncFlags = SYNC_PULL;
151 process_sync_args(&configFlags, &syncFlags);
152 sync_ssh_options();
153 client_sync(syncFlags, configFlags, 0);
154 }
155
156 /*
157 ** COMMAND: push
@@ -176,10 +177,11 @@
177 */
178 void push_cmd(void){
179 unsigned configFlags = 0;
180 unsigned syncFlags = SYNC_PUSH;
181 process_sync_args(&configFlags, &syncFlags);
182 sync_ssh_options();
183 if( db_get_boolean("dont-push",0) ){
184 fossil_fatal("pushing is prohibited: the 'dont-push' option is set");
185 }
186 client_sync(syncFlags, 0, 0);
187 }
@@ -214,11 +216,13 @@
216 */
217 void sync_cmd(void){
218 unsigned configFlags = 0;
219 unsigned syncFlags = SYNC_PUSH|SYNC_PULL;
220 process_sync_args(&configFlags, &syncFlags);
221 sync_ssh_options();
222 if( db_get_boolean("dont-push",0) ) syncFlags &= ~SYNC_PUSH;
223 sync_ssh_db_options();
224 client_sync(syncFlags, configFlags, 0);
225 if( (syncFlags & SYNC_PUSH)==0 ){
226 fossil_warning("pull only: the 'dont-push' option is set");
227 }
228 }
@@ -257,5 +261,43 @@
261 }else{
262 url_parse(zUrl, 0);
263 fossil_print("%s\n", g.urlCanonical);
264 }
265 }
266
267 void sync_ssh_options(void){
268 const char *zSshFossilCmd; /* Path to remote fossil command for SSH */
269 const char *zSshHttpCmd; /* Name of remote HTTP command for SSH */
270 const char *zSshCmd; /* Name of remote HTTP command for SSH */
271
272 zSshFossilCmd = find_option("sshfossilcmd","f",1);
273 if( zSshFossilCmd && zSshFossilCmd[0] ){
274 g.fSshFossilCmd = mprintf("%s", zSshFossilCmd);
275 }
276 zSshHttpCmd = find_option("sshhttpcmd","h",1);
277 if( zSshHttpCmd && zSshHttpCmd[0] ){
278 g.fSshHttpCmd = mprintf("%s", zSshHttpCmd);
279 if( zSshFossilCmd==0 ){
280 g.fSshFossilCmd = "fossil";
281 }
282 }
283 zSshCmd = find_option("sshcmd","s",1);
284 if( zSshCmd && zSshCmd[0] ){
285 g.fSshCmd = mprintf("%s", zSshCmd);
286 }
287 }
288
289 void sync_ssh_db_options(void){
290 if( g.fSshFossilCmd && g.fSshFossilCmd[0] ){
291 db_set("last-ssh-fossil-cmd", g.fSshFossilCmd, 0);
292 }else{
293 g.fSshFossilCmd = db_get("last-ssh-fossil-cmd", 0);
294 }
295 if( g.fSshHttpCmd && g.fSshHttpCmd[0] ){
296 db_set("last-ssh-http-cmd", g.fSshHttpCmd, 0);
297 }else{
298 g.fSshHttpCmd = db_get("last-ssh-http-cmd", "test-http");
299 }
300 if( g.fSshCmd && g.fSshCmd[0] ){
301 db_set("ssh-command", g.fSshCmd, 0);
302 }
303 }
304
+21 -4
--- src/timeline.c
+++ src/timeline.c
@@ -273,12 +273,14 @@
273273
const char *zBgClr = db_column_text(pQuery, 6);
274274
const char *zDate = db_column_text(pQuery, 2);
275275
const char *zType = db_column_text(pQuery, 7);
276276
const char *zUser = db_column_text(pQuery, 4);
277277
const char *zTagList = db_column_text(pQuery, 8);
278
+ const char *zLogin = db_column_text(pQuery, 12);
278279
int tagid = db_column_int(pQuery, 9);
279280
const char *zDispUser = zUser && zUser[0] ? zUser : "anonymous";
281
+ const char *zDispLogin;
280282
const char *zBr = 0; /* Branch */
281283
int commentColumn = 3; /* Column containing comment text */
282284
int modPending; /* Pending moderation */
283285
char zTime[8];
284286
@@ -408,16 +410,26 @@
408410
blob_reset(&comment);
409411
410412
/* Generate the "user: USERNAME" at the end of the comment, together
411413
** with a hyperlink to another timeline for that user.
412414
*/
415
+ zDispLogin = "";
416
+ if( g.perm.Admin ){
417
+ if( zLogin && zLogin[0] ){
418
+ if( fossil_strcmp(zLogin, zUser)!=0 ){
419
+ zDispLogin = mprintf(" [%s]", zLogin);
420
+ }
421
+ }else{
422
+ zDispLogin = " [unknown]";
423
+ }
424
+ }
413425
if( zTagList && zTagList[0]==0 ) zTagList = 0;
414426
if( g.perm.Hyperlink && fossil_strcmp(zDispUser, zThisUser)!=0 ){
415427
char *zLink = mprintf("%R/timeline?u=%h&c=%t&nd", zDispUser, zDate);
416
- @ (user: %z(href("%z",zLink))%h(zDispUser)</a>%s(zTagList?",":"\051")
428
+ @ (user: %z(href("%z",zLink))%h(zDispUser)%h(zDispLogin)</a>%s(zTagList?",":"\051")
417429
}else{
418
- @ (user: %h(zDispUser)%s(zTagList?",":"\051")
430
+ @ (user: %h(zDispUser)%h(zDispLogin)%s(zTagList?",":"\051")
419431
}
420432
421433
/* Generate a "detail" link for tags. */
422434
if( (zType[0]=='g' || zType[0]=='w' || zType[0]=='t') && g.perm.Hyperlink ){
423435
@ [%z(href("%R/info/%S",zUuid))details</a>]
@@ -852,11 +864,12 @@
852864
@ bgcolor TEXT,
853865
@ etype TEXT,
854866
@ taglist TEXT,
855867
@ tagid INTEGER,
856868
@ short TEXT,
857
- @ sortby REAL
869
+ @ sortby REAL,
870
+ @ login TEXT
858871
@ )
859872
;
860873
db_multi_exec(zSql);
861874
}
862875
@@ -879,13 +892,17 @@
879892
@ (SELECT group_concat(substr(tagname,5), ', ') FROM tag, tagxref
880893
@ WHERE tagname GLOB 'sym-*' AND tag.tagid=tagxref.tagid
881894
@ AND tagxref.rid=blob.rid AND tagxref.tagtype>0) AS tags,
882895
@ tagid AS tagid,
883896
@ brief AS brief,
884
- @ event.mtime AS mtime
897
+ @ event.mtime AS mtime,
898
+ @ login AS login
885899
@ FROM event CROSS JOIN blob
900
+ @ CROSS JOIN rcvfrom CROSS JOIN user
886901
@ WHERE blob.rid=event.objid
902
+ @ AND blob.rcvid = rcvfrom.rcvid
903
+ @ AND rcvfrom.uid = user.uid
887904
;
888905
if( zBase==0 ){
889906
zBase = mprintf(zBaseSql, TAG_BRANCH, TAG_BRANCH);
890907
}
891908
return zBase;
892909
--- src/timeline.c
+++ src/timeline.c
@@ -273,12 +273,14 @@
273 const char *zBgClr = db_column_text(pQuery, 6);
274 const char *zDate = db_column_text(pQuery, 2);
275 const char *zType = db_column_text(pQuery, 7);
276 const char *zUser = db_column_text(pQuery, 4);
277 const char *zTagList = db_column_text(pQuery, 8);
 
278 int tagid = db_column_int(pQuery, 9);
279 const char *zDispUser = zUser && zUser[0] ? zUser : "anonymous";
 
280 const char *zBr = 0; /* Branch */
281 int commentColumn = 3; /* Column containing comment text */
282 int modPending; /* Pending moderation */
283 char zTime[8];
284
@@ -408,16 +410,26 @@
408 blob_reset(&comment);
409
410 /* Generate the "user: USERNAME" at the end of the comment, together
411 ** with a hyperlink to another timeline for that user.
412 */
 
 
 
 
 
 
 
 
 
 
413 if( zTagList && zTagList[0]==0 ) zTagList = 0;
414 if( g.perm.Hyperlink && fossil_strcmp(zDispUser, zThisUser)!=0 ){
415 char *zLink = mprintf("%R/timeline?u=%h&c=%t&nd", zDispUser, zDate);
416 @ (user: %z(href("%z",zLink))%h(zDispUser)</a>%s(zTagList?",":"\051")
417 }else{
418 @ (user: %h(zDispUser)%s(zTagList?",":"\051")
419 }
420
421 /* Generate a "detail" link for tags. */
422 if( (zType[0]=='g' || zType[0]=='w' || zType[0]=='t') && g.perm.Hyperlink ){
423 @ [%z(href("%R/info/%S",zUuid))details</a>]
@@ -852,11 +864,12 @@
852 @ bgcolor TEXT,
853 @ etype TEXT,
854 @ taglist TEXT,
855 @ tagid INTEGER,
856 @ short TEXT,
857 @ sortby REAL
 
858 @ )
859 ;
860 db_multi_exec(zSql);
861 }
862
@@ -879,13 +892,17 @@
879 @ (SELECT group_concat(substr(tagname,5), ', ') FROM tag, tagxref
880 @ WHERE tagname GLOB 'sym-*' AND tag.tagid=tagxref.tagid
881 @ AND tagxref.rid=blob.rid AND tagxref.tagtype>0) AS tags,
882 @ tagid AS tagid,
883 @ brief AS brief,
884 @ event.mtime AS mtime
 
885 @ FROM event CROSS JOIN blob
 
886 @ WHERE blob.rid=event.objid
 
 
887 ;
888 if( zBase==0 ){
889 zBase = mprintf(zBaseSql, TAG_BRANCH, TAG_BRANCH);
890 }
891 return zBase;
892
--- src/timeline.c
+++ src/timeline.c
@@ -273,12 +273,14 @@
273 const char *zBgClr = db_column_text(pQuery, 6);
274 const char *zDate = db_column_text(pQuery, 2);
275 const char *zType = db_column_text(pQuery, 7);
276 const char *zUser = db_column_text(pQuery, 4);
277 const char *zTagList = db_column_text(pQuery, 8);
278 const char *zLogin = db_column_text(pQuery, 12);
279 int tagid = db_column_int(pQuery, 9);
280 const char *zDispUser = zUser && zUser[0] ? zUser : "anonymous";
281 const char *zDispLogin;
282 const char *zBr = 0; /* Branch */
283 int commentColumn = 3; /* Column containing comment text */
284 int modPending; /* Pending moderation */
285 char zTime[8];
286
@@ -408,16 +410,26 @@
410 blob_reset(&comment);
411
412 /* Generate the "user: USERNAME" at the end of the comment, together
413 ** with a hyperlink to another timeline for that user.
414 */
415 zDispLogin = "";
416 if( g.perm.Admin ){
417 if( zLogin && zLogin[0] ){
418 if( fossil_strcmp(zLogin, zUser)!=0 ){
419 zDispLogin = mprintf(" [%s]", zLogin);
420 }
421 }else{
422 zDispLogin = " [unknown]";
423 }
424 }
425 if( zTagList && zTagList[0]==0 ) zTagList = 0;
426 if( g.perm.Hyperlink && fossil_strcmp(zDispUser, zThisUser)!=0 ){
427 char *zLink = mprintf("%R/timeline?u=%h&c=%t&nd", zDispUser, zDate);
428 @ (user: %z(href("%z",zLink))%h(zDispUser)%h(zDispLogin)</a>%s(zTagList?",":"\051")
429 }else{
430 @ (user: %h(zDispUser)%h(zDispLogin)%s(zTagList?",":"\051")
431 }
432
433 /* Generate a "detail" link for tags. */
434 if( (zType[0]=='g' || zType[0]=='w' || zType[0]=='t') && g.perm.Hyperlink ){
435 @ [%z(href("%R/info/%S",zUuid))details</a>]
@@ -852,11 +864,12 @@
864 @ bgcolor TEXT,
865 @ etype TEXT,
866 @ taglist TEXT,
867 @ tagid INTEGER,
868 @ short TEXT,
869 @ sortby REAL,
870 @ login TEXT
871 @ )
872 ;
873 db_multi_exec(zSql);
874 }
875
@@ -879,13 +892,17 @@
892 @ (SELECT group_concat(substr(tagname,5), ', ') FROM tag, tagxref
893 @ WHERE tagname GLOB 'sym-*' AND tag.tagid=tagxref.tagid
894 @ AND tagxref.rid=blob.rid AND tagxref.tagtype>0) AS tags,
895 @ tagid AS tagid,
896 @ brief AS brief,
897 @ event.mtime AS mtime,
898 @ login AS login
899 @ FROM event CROSS JOIN blob
900 @ CROSS JOIN rcvfrom CROSS JOIN user
901 @ WHERE blob.rid=event.objid
902 @ AND blob.rcvid = rcvfrom.rcvid
903 @ AND rcvfrom.uid = user.uid
904 ;
905 if( zBase==0 ){
906 zBase = mprintf(zBaseSql, TAG_BRANCH, TAG_BRANCH);
907 }
908 return zBase;
909
+1 -2
--- src/url.c
+++ src/url.c
@@ -439,11 +439,11 @@
439439
/*
440440
** Prompt the user for the password for g.urlUser. Store the result
441441
** in g.urlPasswd.
442442
*/
443443
void url_prompt_for_password(void){
444
- if( g.urlIsSsh || g.urlIsFile ) return;
444
+ if( g.urlIsSsh && g.fSshFossilCmd==0 || g.urlIsFile ) return;
445445
if( isatty(fileno(stdin))
446446
&& (g.urlFlags & URL_PROMPT_PW)!=0
447447
&& (g.urlFlags & URL_PROMPTED)==0
448448
){
449449
char *zPrompt = mprintf("\rpassword for %s: ", g.urlUser);
@@ -490,10 +490,9 @@
490490
*/
491491
void url_get_password_if_needed(void){
492492
if( (g.urlUser && g.urlUser[0])
493493
&& (g.urlPasswd==0 || g.urlPasswd[0]==0)
494494
&& isatty(fileno(stdin))
495
- && g.urlIsSsh==0
496495
){
497496
url_prompt_for_password();
498497
}
499498
}
500499
--- src/url.c
+++ src/url.c
@@ -439,11 +439,11 @@
439 /*
440 ** Prompt the user for the password for g.urlUser. Store the result
441 ** in g.urlPasswd.
442 */
443 void url_prompt_for_password(void){
444 if( g.urlIsSsh || g.urlIsFile ) return;
445 if( isatty(fileno(stdin))
446 && (g.urlFlags & URL_PROMPT_PW)!=0
447 && (g.urlFlags & URL_PROMPTED)==0
448 ){
449 char *zPrompt = mprintf("\rpassword for %s: ", g.urlUser);
@@ -490,10 +490,9 @@
490 */
491 void url_get_password_if_needed(void){
492 if( (g.urlUser && g.urlUser[0])
493 && (g.urlPasswd==0 || g.urlPasswd[0]==0)
494 && isatty(fileno(stdin))
495 && g.urlIsSsh==0
496 ){
497 url_prompt_for_password();
498 }
499 }
500
--- src/url.c
+++ src/url.c
@@ -439,11 +439,11 @@
439 /*
440 ** Prompt the user for the password for g.urlUser. Store the result
441 ** in g.urlPasswd.
442 */
443 void url_prompt_for_password(void){
444 if( g.urlIsSsh && g.fSshFossilCmd==0 || g.urlIsFile ) return;
445 if( isatty(fileno(stdin))
446 && (g.urlFlags & URL_PROMPT_PW)!=0
447 && (g.urlFlags & URL_PROMPTED)==0
448 ){
449 char *zPrompt = mprintf("\rpassword for %s: ", g.urlUser);
@@ -490,10 +490,9 @@
490 */
491 void url_get_password_if_needed(void){
492 if( (g.urlUser && g.urlUser[0])
493 && (g.urlPasswd==0 || g.urlPasswd[0]==0)
494 && isatty(fileno(stdin))
 
495 ){
496 url_prompt_for_password();
497 }
498 }
499
+2 -2
--- src/xfer.c
+++ src/xfer.c
@@ -1336,10 +1336,11 @@
13361336
13371337
if( db_get_boolean("dont-push", 0) ) syncFlags &= ~SYNC_PUSH;
13381338
if( (syncFlags & (SYNC_PUSH|SYNC_PULL|SYNC_CLONE))==0
13391339
&& configRcvMask==0 && configSendMask==0 ) return 0;
13401340
1341
+ sync_ssh_db_options();
13411342
transport_stats(0, 0, 1);
13421343
socket_global_init();
13431344
memset(&xfer, 0, sizeof(xfer));
13441345
xfer.pIn = &recv;
13451346
xfer.pOut = &send;
@@ -1387,11 +1388,10 @@
13871388
blob_appendf(&send, "push %s %s\n", zSCode, zPCode);
13881389
nCardSent++;
13891390
if( (syncFlags & SYNC_PULL)==0 ) zOpType = "Push";
13901391
}
13911392
manifest_crosslink_begin();
1392
- transport_global_startup();
13931393
if( syncFlags & SYNC_VERBOSE ){
13941394
fossil_print(zLabelFormat, "", "Bytes", "Cards", "Artifacts", "Deltas");
13951395
}
13961396
13971397
while( go ){
@@ -1483,11 +1483,11 @@
14831483
xfer.nFileSent = 0;
14841484
xfer.nDeltaSent = 0;
14851485
xfer.nGimmeSent = 0;
14861486
xfer.nIGotSent = 0;
14871487
if( syncFlags & SYNC_VERBOSE ){
1488
- fossil_print("waiting for server...");
1488
+ fossil_print("waiting for server...\n");
14891489
}
14901490
fflush(stdout);
14911491
if( http_exchange(&send, &recv, (syncFlags & SYNC_CLONE)==0 || nCycle>0,
14921492
MAX_REDIRECTS) ){
14931493
nErr++;
14941494
--- src/xfer.c
+++ src/xfer.c
@@ -1336,10 +1336,11 @@
1336
1337 if( db_get_boolean("dont-push", 0) ) syncFlags &= ~SYNC_PUSH;
1338 if( (syncFlags & (SYNC_PUSH|SYNC_PULL|SYNC_CLONE))==0
1339 && configRcvMask==0 && configSendMask==0 ) return 0;
1340
 
1341 transport_stats(0, 0, 1);
1342 socket_global_init();
1343 memset(&xfer, 0, sizeof(xfer));
1344 xfer.pIn = &recv;
1345 xfer.pOut = &send;
@@ -1387,11 +1388,10 @@
1387 blob_appendf(&send, "push %s %s\n", zSCode, zPCode);
1388 nCardSent++;
1389 if( (syncFlags & SYNC_PULL)==0 ) zOpType = "Push";
1390 }
1391 manifest_crosslink_begin();
1392 transport_global_startup();
1393 if( syncFlags & SYNC_VERBOSE ){
1394 fossil_print(zLabelFormat, "", "Bytes", "Cards", "Artifacts", "Deltas");
1395 }
1396
1397 while( go ){
@@ -1483,11 +1483,11 @@
1483 xfer.nFileSent = 0;
1484 xfer.nDeltaSent = 0;
1485 xfer.nGimmeSent = 0;
1486 xfer.nIGotSent = 0;
1487 if( syncFlags & SYNC_VERBOSE ){
1488 fossil_print("waiting for server...");
1489 }
1490 fflush(stdout);
1491 if( http_exchange(&send, &recv, (syncFlags & SYNC_CLONE)==0 || nCycle>0,
1492 MAX_REDIRECTS) ){
1493 nErr++;
1494
--- src/xfer.c
+++ src/xfer.c
@@ -1336,10 +1336,11 @@
1336
1337 if( db_get_boolean("dont-push", 0) ) syncFlags &= ~SYNC_PUSH;
1338 if( (syncFlags & (SYNC_PUSH|SYNC_PULL|SYNC_CLONE))==0
1339 && configRcvMask==0 && configSendMask==0 ) return 0;
1340
1341 sync_ssh_db_options();
1342 transport_stats(0, 0, 1);
1343 socket_global_init();
1344 memset(&xfer, 0, sizeof(xfer));
1345 xfer.pIn = &recv;
1346 xfer.pOut = &send;
@@ -1387,11 +1388,10 @@
1388 blob_appendf(&send, "push %s %s\n", zSCode, zPCode);
1389 nCardSent++;
1390 if( (syncFlags & SYNC_PULL)==0 ) zOpType = "Push";
1391 }
1392 manifest_crosslink_begin();
 
1393 if( syncFlags & SYNC_VERBOSE ){
1394 fossil_print(zLabelFormat, "", "Bytes", "Cards", "Artifacts", "Deltas");
1395 }
1396
1397 while( go ){
@@ -1483,11 +1483,11 @@
1483 xfer.nFileSent = 0;
1484 xfer.nDeltaSent = 0;
1485 xfer.nGimmeSent = 0;
1486 xfer.nIGotSent = 0;
1487 if( syncFlags & SYNC_VERBOSE ){
1488 fossil_print("waiting for server...\n");
1489 }
1490 fflush(stdout);
1491 if( http_exchange(&send, &recv, (syncFlags & SYNC_CLONE)==0 || nCycle>0,
1492 MAX_REDIRECTS) ){
1493 nErr++;
1494

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button