Fossil SCM

Updated to include all the latest changes (for which we hold clear title) from the trunk.

drh 2010-01-21 22:06 clear-title merge
Commit 390b4146053df5abc53db66fc36795117e42953b
+14 -1
--- src/add.c
+++ src/add.c
@@ -52,13 +52,20 @@
5252
fossil_warning("cannot add %s", zPath);
5353
}else{
5454
if( !file_is_simple_pathname(zPath) ){
5555
fossil_fatal("filename contains illegal characters: %s", zPath);
5656
}
57
+#ifdef __MINGW32__
58
+ if( db_exists("SELECT 1 FROM vfile WHERE pathname LIKE %Q", zPath) ){
59
+ db_multi_exec("UPDATE vfile SET deleted=0 WHERE pathname LIKE %Q", zPath);
60
+ }
61
+#else
5762
if( db_exists("SELECT 1 FROM vfile WHERE pathname=%Q", zPath) ){
5863
db_multi_exec("UPDATE vfile SET deleted=0 WHERE pathname=%Q", zPath);
59
- }else{
64
+ }
65
+#endif
66
+ else{
6067
db_multi_exec(
6168
"INSERT INTO vfile(vid,deleted,rid,mrid,pathname)"
6269
"VALUES(%d,0,0,0,%Q)", vid, zPath);
6370
}
6471
printf("ADDED %s\n", zPath);
@@ -142,10 +149,16 @@
142149
db_begin_transaction();
143150
if( !file_tree_name(g.zRepositoryName, &repo, 0) ){
144151
blob_zero(&repo);
145152
}
146153
db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
154
+#ifdef __MINGW32__
155
+ db_multi_exec(
156
+ "CREATE INDEX IF NOT EXISTS vfile_pathname "
157
+ " ON vfile(pathname COLLATE nocase)"
158
+ );
159
+#endif
147160
for(i=2; i<g.argc; i++){
148161
char *zName;
149162
int isDir;
150163
151164
zName = mprintf("%/", g.argv[i]);
152165
--- src/add.c
+++ src/add.c
@@ -52,13 +52,20 @@
52 fossil_warning("cannot add %s", zPath);
53 }else{
54 if( !file_is_simple_pathname(zPath) ){
55 fossil_fatal("filename contains illegal characters: %s", zPath);
56 }
 
 
 
 
 
57 if( db_exists("SELECT 1 FROM vfile WHERE pathname=%Q", zPath) ){
58 db_multi_exec("UPDATE vfile SET deleted=0 WHERE pathname=%Q", zPath);
59 }else{
 
 
60 db_multi_exec(
61 "INSERT INTO vfile(vid,deleted,rid,mrid,pathname)"
62 "VALUES(%d,0,0,0,%Q)", vid, zPath);
63 }
64 printf("ADDED %s\n", zPath);
@@ -142,10 +149,16 @@
142 db_begin_transaction();
143 if( !file_tree_name(g.zRepositoryName, &repo, 0) ){
144 blob_zero(&repo);
145 }
146 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
 
 
 
 
 
 
147 for(i=2; i<g.argc; i++){
148 char *zName;
149 int isDir;
150
151 zName = mprintf("%/", g.argv[i]);
152
--- src/add.c
+++ src/add.c
@@ -52,13 +52,20 @@
52 fossil_warning("cannot add %s", zPath);
53 }else{
54 if( !file_is_simple_pathname(zPath) ){
55 fossil_fatal("filename contains illegal characters: %s", zPath);
56 }
57 #ifdef __MINGW32__
58 if( db_exists("SELECT 1 FROM vfile WHERE pathname LIKE %Q", zPath) ){
59 db_multi_exec("UPDATE vfile SET deleted=0 WHERE pathname LIKE %Q", zPath);
60 }
61 #else
62 if( db_exists("SELECT 1 FROM vfile WHERE pathname=%Q", zPath) ){
63 db_multi_exec("UPDATE vfile SET deleted=0 WHERE pathname=%Q", zPath);
64 }
65 #endif
66 else{
67 db_multi_exec(
68 "INSERT INTO vfile(vid,deleted,rid,mrid,pathname)"
69 "VALUES(%d,0,0,0,%Q)", vid, zPath);
70 }
71 printf("ADDED %s\n", zPath);
@@ -142,10 +149,16 @@
149 db_begin_transaction();
150 if( !file_tree_name(g.zRepositoryName, &repo, 0) ){
151 blob_zero(&repo);
152 }
153 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
154 #ifdef __MINGW32__
155 db_multi_exec(
156 "CREATE INDEX IF NOT EXISTS vfile_pathname "
157 " ON vfile(pathname COLLATE nocase)"
158 );
159 #endif
160 for(i=2; i<g.argc; i++){
161 char *zName;
162 int isDir;
163
164 zName = mprintf("%/", g.argv[i]);
165
+14 -1
--- src/add.c
+++ src/add.c
@@ -52,13 +52,20 @@
5252
fossil_warning("cannot add %s", zPath);
5353
}else{
5454
if( !file_is_simple_pathname(zPath) ){
5555
fossil_fatal("filename contains illegal characters: %s", zPath);
5656
}
57
+#ifdef __MINGW32__
58
+ if( db_exists("SELECT 1 FROM vfile WHERE pathname LIKE %Q", zPath) ){
59
+ db_multi_exec("UPDATE vfile SET deleted=0 WHERE pathname LIKE %Q", zPath);
60
+ }
61
+#else
5762
if( db_exists("SELECT 1 FROM vfile WHERE pathname=%Q", zPath) ){
5863
db_multi_exec("UPDATE vfile SET deleted=0 WHERE pathname=%Q", zPath);
59
- }else{
64
+ }
65
+#endif
66
+ else{
6067
db_multi_exec(
6168
"INSERT INTO vfile(vid,deleted,rid,mrid,pathname)"
6269
"VALUES(%d,0,0,0,%Q)", vid, zPath);
6370
}
6471
printf("ADDED %s\n", zPath);
@@ -142,10 +149,16 @@
142149
db_begin_transaction();
143150
if( !file_tree_name(g.zRepositoryName, &repo, 0) ){
144151
blob_zero(&repo);
145152
}
146153
db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
154
+#ifdef __MINGW32__
155
+ db_multi_exec(
156
+ "CREATE INDEX IF NOT EXISTS vfile_pathname "
157
+ " ON vfile(pathname COLLATE nocase)"
158
+ );
159
+#endif
147160
for(i=2; i<g.argc; i++){
148161
char *zName;
149162
int isDir;
150163
151164
zName = mprintf("%/", g.argv[i]);
152165
--- src/add.c
+++ src/add.c
@@ -52,13 +52,20 @@
52 fossil_warning("cannot add %s", zPath);
53 }else{
54 if( !file_is_simple_pathname(zPath) ){
55 fossil_fatal("filename contains illegal characters: %s", zPath);
56 }
 
 
 
 
 
57 if( db_exists("SELECT 1 FROM vfile WHERE pathname=%Q", zPath) ){
58 db_multi_exec("UPDATE vfile SET deleted=0 WHERE pathname=%Q", zPath);
59 }else{
 
 
60 db_multi_exec(
61 "INSERT INTO vfile(vid,deleted,rid,mrid,pathname)"
62 "VALUES(%d,0,0,0,%Q)", vid, zPath);
63 }
64 printf("ADDED %s\n", zPath);
@@ -142,10 +149,16 @@
142 db_begin_transaction();
143 if( !file_tree_name(g.zRepositoryName, &repo, 0) ){
144 blob_zero(&repo);
145 }
146 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
 
 
 
 
 
 
147 for(i=2; i<g.argc; i++){
148 char *zName;
149 int isDir;
150
151 zName = mprintf("%/", g.argv[i]);
152
--- src/add.c
+++ src/add.c
@@ -52,13 +52,20 @@
52 fossil_warning("cannot add %s", zPath);
53 }else{
54 if( !file_is_simple_pathname(zPath) ){
55 fossil_fatal("filename contains illegal characters: %s", zPath);
56 }
57 #ifdef __MINGW32__
58 if( db_exists("SELECT 1 FROM vfile WHERE pathname LIKE %Q", zPath) ){
59 db_multi_exec("UPDATE vfile SET deleted=0 WHERE pathname LIKE %Q", zPath);
60 }
61 #else
62 if( db_exists("SELECT 1 FROM vfile WHERE pathname=%Q", zPath) ){
63 db_multi_exec("UPDATE vfile SET deleted=0 WHERE pathname=%Q", zPath);
64 }
65 #endif
66 else{
67 db_multi_exec(
68 "INSERT INTO vfile(vid,deleted,rid,mrid,pathname)"
69 "VALUES(%d,0,0,0,%Q)", vid, zPath);
70 }
71 printf("ADDED %s\n", zPath);
@@ -142,10 +149,16 @@
149 db_begin_transaction();
150 if( !file_tree_name(g.zRepositoryName, &repo, 0) ){
151 blob_zero(&repo);
152 }
153 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
154 #ifdef __MINGW32__
155 db_multi_exec(
156 "CREATE INDEX IF NOT EXISTS vfile_pathname "
157 " ON vfile(pathname COLLATE nocase)"
158 );
159 #endif
160 for(i=2; i<g.argc; i++){
161 char *zName;
162 int isDir;
163
164 zName = mprintf("%/", g.argv[i]);
165
--- src/configure.c
+++ src/configure.c
@@ -445,24 +445,29 @@
445445
db_end_transaction(0);
446446
}else
447447
if( strncmp(zMethod, "pull", n)==0 || strncmp(zMethod, "push", n)==0 ){
448448
int mask;
449449
const char *zServer;
450
+ const char *zPw;
450451
url_proxy_options();
451452
if( g.argc!=4 && g.argc!=5 ){
452453
usage("pull AREA ?URL?");
453454
}
454455
mask = find_area(g.argv[3]);
455456
if( g.argc==5 ){
456457
zServer = g.argv[4];
458
+ zPw = 0;
459
+ g.dontKeepUrl = 1;
457460
}else{
458461
zServer = db_get("last-sync-url", 0);
459462
if( zServer==0 ){
460463
fossil_fatal("no server specified");
461464
}
465
+ zPw = db_get("last-sync-pw", 0);
462466
}
463467
url_parse(zServer);
468
+ if( g.urlPasswd==0 && zPw ) g.urlPasswd = mprintf("%s", zPw);
464469
user_select();
465470
if( strncmp(zMethod, "push", n)==0 ){
466471
client_sync(0,0,0,0,mask);
467472
}else{
468473
client_sync(0,0,0,mask,0);
469474
--- src/configure.c
+++ src/configure.c
@@ -445,24 +445,29 @@
445 db_end_transaction(0);
446 }else
447 if( strncmp(zMethod, "pull", n)==0 || strncmp(zMethod, "push", n)==0 ){
448 int mask;
449 const char *zServer;
 
450 url_proxy_options();
451 if( g.argc!=4 && g.argc!=5 ){
452 usage("pull AREA ?URL?");
453 }
454 mask = find_area(g.argv[3]);
455 if( g.argc==5 ){
456 zServer = g.argv[4];
 
 
457 }else{
458 zServer = db_get("last-sync-url", 0);
459 if( zServer==0 ){
460 fossil_fatal("no server specified");
461 }
 
462 }
463 url_parse(zServer);
 
464 user_select();
465 if( strncmp(zMethod, "push", n)==0 ){
466 client_sync(0,0,0,0,mask);
467 }else{
468 client_sync(0,0,0,mask,0);
469
--- src/configure.c
+++ src/configure.c
@@ -445,24 +445,29 @@
445 db_end_transaction(0);
446 }else
447 if( strncmp(zMethod, "pull", n)==0 || strncmp(zMethod, "push", n)==0 ){
448 int mask;
449 const char *zServer;
450 const char *zPw;
451 url_proxy_options();
452 if( g.argc!=4 && g.argc!=5 ){
453 usage("pull AREA ?URL?");
454 }
455 mask = find_area(g.argv[3]);
456 if( g.argc==5 ){
457 zServer = g.argv[4];
458 zPw = 0;
459 g.dontKeepUrl = 1;
460 }else{
461 zServer = db_get("last-sync-url", 0);
462 if( zServer==0 ){
463 fossil_fatal("no server specified");
464 }
465 zPw = db_get("last-sync-pw", 0);
466 }
467 url_parse(zServer);
468 if( g.urlPasswd==0 && zPw ) g.urlPasswd = mprintf("%s", zPw);
469 user_select();
470 if( strncmp(zMethod, "push", n)==0 ){
471 client_sync(0,0,0,0,mask);
472 }else{
473 client_sync(0,0,0,mask,0);
474
+1 -1
--- src/db.c
+++ src/db.c
@@ -1492,11 +1492,11 @@
14921492
** 127.0.0.1 be authenticated by password. If
14931493
** false, all HTTP requests from localhost have
14941494
** unrestricted access to the repository.
14951495
**
14961496
** mtime-changes Use file modification times (mtimes) to detect when
1497
-** files have been modified.
1497
+** files have been modified. (Default "on".)
14981498
**
14991499
** pgp-command Command used to clear-sign manifests at check-in.
15001500
** The default is "gpg --clearsign -o ".
15011501
**
15021502
** proxy URL of the HTTP proxy. If undefined or "off" then
15031503
--- src/db.c
+++ src/db.c
@@ -1492,11 +1492,11 @@
1492 ** 127.0.0.1 be authenticated by password. If
1493 ** false, all HTTP requests from localhost have
1494 ** unrestricted access to the repository.
1495 **
1496 ** mtime-changes Use file modification times (mtimes) to detect when
1497 ** files have been modified.
1498 **
1499 ** pgp-command Command used to clear-sign manifests at check-in.
1500 ** The default is "gpg --clearsign -o ".
1501 **
1502 ** proxy URL of the HTTP proxy. If undefined or "off" then
1503
--- src/db.c
+++ src/db.c
@@ -1492,11 +1492,11 @@
1492 ** 127.0.0.1 be authenticated by password. If
1493 ** false, all HTTP requests from localhost have
1494 ** unrestricted access to the repository.
1495 **
1496 ** mtime-changes Use file modification times (mtimes) to detect when
1497 ** files have been modified. (Default "on".)
1498 **
1499 ** pgp-command Command used to clear-sign manifests at check-in.
1500 ** The default is "gpg --clearsign -o ".
1501 **
1502 ** proxy URL of the HTTP proxy. If undefined or "off" then
1503
+1 -1
--- src/db.c
+++ src/db.c
@@ -1492,11 +1492,11 @@
14921492
** 127.0.0.1 be authenticated by password. If
14931493
** false, all HTTP requests from localhost have
14941494
** unrestricted access to the repository.
14951495
**
14961496
** mtime-changes Use file modification times (mtimes) to detect when
1497
-** files have been modified.
1497
+** files have been modified. (Default "on".)
14981498
**
14991499
** pgp-command Command used to clear-sign manifests at check-in.
15001500
** The default is "gpg --clearsign -o ".
15011501
**
15021502
** proxy URL of the HTTP proxy. If undefined or "off" then
15031503
--- src/db.c
+++ src/db.c
@@ -1492,11 +1492,11 @@
1492 ** 127.0.0.1 be authenticated by password. If
1493 ** false, all HTTP requests from localhost have
1494 ** unrestricted access to the repository.
1495 **
1496 ** mtime-changes Use file modification times (mtimes) to detect when
1497 ** files have been modified.
1498 **
1499 ** pgp-command Command used to clear-sign manifests at check-in.
1500 ** The default is "gpg --clearsign -o ".
1501 **
1502 ** proxy URL of the HTTP proxy. If undefined or "off" then
1503
--- src/db.c
+++ src/db.c
@@ -1492,11 +1492,11 @@
1492 ** 127.0.0.1 be authenticated by password. If
1493 ** false, all HTTP requests from localhost have
1494 ** unrestricted access to the repository.
1495 **
1496 ** mtime-changes Use file modification times (mtimes) to detect when
1497 ** files have been modified. (Default "on".)
1498 **
1499 ** pgp-command Command used to clear-sign manifests at check-in.
1500 ** The default is "gpg --clearsign -o ".
1501 **
1502 ** proxy URL of the HTTP proxy. If undefined or "off" then
1503
+69 -57
--- src/file.c
+++ src/file.c
@@ -27,33 +27,91 @@
2727
#include <sys/types.h>
2828
#include <sys/stat.h>
2929
#include <unistd.h>
3030
#include "file.h"
3131
32
+/*
33
+** The file status information from the most recent stat() call.
34
+*/
35
+static struct stat fileStat;
36
+static int fileStatValid = 0;
37
+
38
+/*
39
+** Fill in the fileStat variable for the file named zFilename.
40
+** If zFilename==0, then use the previous value of fileStat if
41
+** there is a previous value.
42
+**
43
+** Return the number of errors. No error messages are generated.
44
+*/
45
+static int getStat(const char *zFilename){
46
+ if( zFilename==0 ){
47
+ if( fileStatValid==0 ) return 1;
48
+ }else{
49
+ if( stat(zFilename, &fileStat)!=0 ) return 1;
50
+ fileStatValid = 1;
51
+ }
52
+ return 0;
53
+}
54
+
3255
3356
/*
3457
** Return the size of a file in bytes. Return -1 if the file does not
35
-** exist.
58
+** exist. If zFilename is NULL, return the size of the most recently
59
+** stat-ed file.
3660
*/
3761
i64 file_size(const char *zFilename){
38
- struct stat buf;
39
- if( stat(zFilename, &buf)!=0 ){
40
- return -1;
41
- }
42
- return buf.st_size;
62
+ return getStat(zFilename) ? -1 : fileStat.st_size;
4363
}
4464
4565
/*
4666
** Return the modification time for a file. Return -1 if the file
47
-** does not exist.
67
+** does not exist. If zFilename is NULL return the size of the most
68
+** recently stat-ed file.
4869
*/
4970
i64 file_mtime(const char *zFilename){
50
- struct stat buf;
51
- if( stat(zFilename, &buf)!=0 ){
52
- return -1;
71
+ return getStat(zFilename) ? -1 : fileStat.st_mtime;
72
+}
73
+
74
+/*
75
+** Return TRUE if the named file is an ordinary file. Return false
76
+** for directories, devices, fifos, symlinks, etc.
77
+*/
78
+int file_isfile(const char *zFilename){
79
+ return getStat(zFilename) ? 0 : S_ISREG(fileStat.st_mode);
80
+}
81
+
82
+/*
83
+** Return TRUE if the named file is an executable. Return false
84
+** for directories, devices, fifos, symlinks, etc.
85
+*/
86
+int file_isexe(const char *zFilename){
87
+ if( getStat(zFilename) || !S_ISREG(fileStat.st_mode) ) return 0;
88
+#ifdef __MINGW32__
89
+ return ((S_IXUSR)&fileStat.st_mode)!=0;
90
+#else
91
+ return ((S_IXUSR|S_IXGRP|S_IXOTH)&fileStat.st_mode)!=0;
92
+#endif
93
+}
94
+
95
+
96
+/*
97
+** Return 1 if zFilename is a directory. Return 0 if zFilename
98
+** does not exist. Return 2 if zFilename exists but is something
99
+** other than a directory.
100
+*/
101
+int file_isdir(const char *zFilename){
102
+ int rc;
103
+
104
+ if( zFilename ){
105
+ char *zFN = mprintf("%s", zFilename);
106
+ file_simplify_name(zFN, strlen(zFN));
107
+ rc = getStat(zFN);
108
+ free(zFN);
109
+ }else{
110
+ rc = getStat(0);
53111
}
54
- return buf.st_mtime;
112
+ return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2);
55113
}
56114
57115
/*
58116
** Return the tail of a file pathname. The tail is the last component
59117
** of the path. For example, the tail of "/a/b/c.d" is "c.d".
@@ -83,39 +141,10 @@
83141
}
84142
fclose(in);
85143
fclose(out);
86144
}
87145
88
-/*
89
-** Return TRUE if the named file is an ordinary file. Return false
90
-** for directories, devices, fifos, symlinks, etc.
91
-*/
92
-int file_isfile(const char *zFilename){
93
- struct stat buf;
94
- if( stat(zFilename, &buf)!=0 ){
95
- return 0;
96
- }
97
- return S_ISREG(buf.st_mode);
98
-}
99
-
100
-/*
101
-** Return TRUE if the named file is an executable. Return false
102
-** for directories, devices, fifos, symlinks, etc.
103
-*/
104
-int file_isexe(const char *zFilename){
105
- struct stat buf;
106
- if( stat(zFilename, &buf)!=0 ){
107
- return 0;
108
- }
109
- if( !S_ISREG(buf.st_mode) ) return 0;
110
-#ifdef __MINGW32__
111
- return ((S_IXUSR)&buf.st_mode)!=0;
112
-#else
113
- return ((S_IXUSR|S_IXGRP|S_IXOTH)&buf.st_mode)!=0;
114
-#endif
115
-}
116
-
117146
/*
118147
** Set or clear the execute bit on a file.
119148
*/
120149
void file_setexe(const char *zFilename, int onoff){
121150
#ifndef __MINGW32__
@@ -131,27 +160,10 @@
131160
}
132161
}
133162
#endif
134163
}
135164
136
-/*
137
-** Return 1 if zFilename is a directory. Return 0 if zFilename
138
-** does not exist. Return 2 if zFilename exists but is something
139
-** other than a directory.
140
-*/
141
-int file_isdir(const char *zFilename){
142
- struct stat buf;
143
- int rc;
144
- char *zFN;
145
-
146
- zFN = mprintf("%s", zFilename);
147
- file_simplify_name(zFN, strlen(zFN));
148
- rc = stat(zFN, &buf);
149
- free(zFN);
150
- return rc!=0 ? 0 : (S_ISDIR(buf.st_mode) ? 1 : 2);
151
-}
152
-
153165
/*
154166
** Create the directory named in the argument, if it does not already
155167
** exist. If forceFlag is 1, delete any prior non-directory object
156168
** with the same name.
157169
**
158170
--- src/file.c
+++ src/file.c
@@ -27,33 +27,91 @@
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <unistd.h>
30 #include "file.h"
31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
33 /*
34 ** Return the size of a file in bytes. Return -1 if the file does not
35 ** exist.
 
36 */
37 i64 file_size(const char *zFilename){
38 struct stat buf;
39 if( stat(zFilename, &buf)!=0 ){
40 return -1;
41 }
42 return buf.st_size;
43 }
44
45 /*
46 ** Return the modification time for a file. Return -1 if the file
47 ** does not exist.
 
48 */
49 i64 file_mtime(const char *zFilename){
50 struct stat buf;
51 if( stat(zFilename, &buf)!=0 ){
52 return -1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53 }
54 return buf.st_mtime;
55 }
56
57 /*
58 ** Return the tail of a file pathname. The tail is the last component
59 ** of the path. For example, the tail of "/a/b/c.d" is "c.d".
@@ -83,39 +141,10 @@
83 }
84 fclose(in);
85 fclose(out);
86 }
87
88 /*
89 ** Return TRUE if the named file is an ordinary file. Return false
90 ** for directories, devices, fifos, symlinks, etc.
91 */
92 int file_isfile(const char *zFilename){
93 struct stat buf;
94 if( stat(zFilename, &buf)!=0 ){
95 return 0;
96 }
97 return S_ISREG(buf.st_mode);
98 }
99
100 /*
101 ** Return TRUE if the named file is an executable. Return false
102 ** for directories, devices, fifos, symlinks, etc.
103 */
104 int file_isexe(const char *zFilename){
105 struct stat buf;
106 if( stat(zFilename, &buf)!=0 ){
107 return 0;
108 }
109 if( !S_ISREG(buf.st_mode) ) return 0;
110 #ifdef __MINGW32__
111 return ((S_IXUSR)&buf.st_mode)!=0;
112 #else
113 return ((S_IXUSR|S_IXGRP|S_IXOTH)&buf.st_mode)!=0;
114 #endif
115 }
116
117 /*
118 ** Set or clear the execute bit on a file.
119 */
120 void file_setexe(const char *zFilename, int onoff){
121 #ifndef __MINGW32__
@@ -131,27 +160,10 @@
131 }
132 }
133 #endif
134 }
135
136 /*
137 ** Return 1 if zFilename is a directory. Return 0 if zFilename
138 ** does not exist. Return 2 if zFilename exists but is something
139 ** other than a directory.
140 */
141 int file_isdir(const char *zFilename){
142 struct stat buf;
143 int rc;
144 char *zFN;
145
146 zFN = mprintf("%s", zFilename);
147 file_simplify_name(zFN, strlen(zFN));
148 rc = stat(zFN, &buf);
149 free(zFN);
150 return rc!=0 ? 0 : (S_ISDIR(buf.st_mode) ? 1 : 2);
151 }
152
153 /*
154 ** Create the directory named in the argument, if it does not already
155 ** exist. If forceFlag is 1, delete any prior non-directory object
156 ** with the same name.
157 **
158
--- src/file.c
+++ src/file.c
@@ -27,33 +27,91 @@
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <unistd.h>
30 #include "file.h"
31
32 /*
33 ** The file status information from the most recent stat() call.
34 */
35 static struct stat fileStat;
36 static int fileStatValid = 0;
37
38 /*
39 ** Fill in the fileStat variable for the file named zFilename.
40 ** If zFilename==0, then use the previous value of fileStat if
41 ** there is a previous value.
42 **
43 ** Return the number of errors. No error messages are generated.
44 */
45 static int getStat(const char *zFilename){
46 if( zFilename==0 ){
47 if( fileStatValid==0 ) return 1;
48 }else{
49 if( stat(zFilename, &fileStat)!=0 ) return 1;
50 fileStatValid = 1;
51 }
52 return 0;
53 }
54
55
56 /*
57 ** Return the size of a file in bytes. Return -1 if the file does not
58 ** exist. If zFilename is NULL, return the size of the most recently
59 ** stat-ed file.
60 */
61 i64 file_size(const char *zFilename){
62 return getStat(zFilename) ? -1 : fileStat.st_size;
 
 
 
 
63 }
64
65 /*
66 ** Return the modification time for a file. Return -1 if the file
67 ** does not exist. If zFilename is NULL return the size of the most
68 ** recently stat-ed file.
69 */
70 i64 file_mtime(const char *zFilename){
71 return getStat(zFilename) ? -1 : fileStat.st_mtime;
72 }
73
74 /*
75 ** Return TRUE if the named file is an ordinary file. Return false
76 ** for directories, devices, fifos, symlinks, etc.
77 */
78 int file_isfile(const char *zFilename){
79 return getStat(zFilename) ? 0 : S_ISREG(fileStat.st_mode);
80 }
81
82 /*
83 ** Return TRUE if the named file is an executable. Return false
84 ** for directories, devices, fifos, symlinks, etc.
85 */
86 int file_isexe(const char *zFilename){
87 if( getStat(zFilename) || !S_ISREG(fileStat.st_mode) ) return 0;
88 #ifdef __MINGW32__
89 return ((S_IXUSR)&fileStat.st_mode)!=0;
90 #else
91 return ((S_IXUSR|S_IXGRP|S_IXOTH)&fileStat.st_mode)!=0;
92 #endif
93 }
94
95
96 /*
97 ** Return 1 if zFilename is a directory. Return 0 if zFilename
98 ** does not exist. Return 2 if zFilename exists but is something
99 ** other than a directory.
100 */
101 int file_isdir(const char *zFilename){
102 int rc;
103
104 if( zFilename ){
105 char *zFN = mprintf("%s", zFilename);
106 file_simplify_name(zFN, strlen(zFN));
107 rc = getStat(zFN);
108 free(zFN);
109 }else{
110 rc = getStat(0);
111 }
112 return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2);
113 }
114
115 /*
116 ** Return the tail of a file pathname. The tail is the last component
117 ** of the path. For example, the tail of "/a/b/c.d" is "c.d".
@@ -83,39 +141,10 @@
141 }
142 fclose(in);
143 fclose(out);
144 }
145
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146 /*
147 ** Set or clear the execute bit on a file.
148 */
149 void file_setexe(const char *zFilename, int onoff){
150 #ifndef __MINGW32__
@@ -131,27 +160,10 @@
160 }
161 }
162 #endif
163 }
164
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165 /*
166 ** Create the directory named in the argument, if it does not already
167 ** exist. If forceFlag is 1, delete any prior non-directory object
168 ** with the same name.
169 **
170
+10 -18
--- src/http.c
+++ src/http.c
@@ -44,33 +44,25 @@
4444
const char *zLogin; /* The user login name */
4545
const char *zPw; /* The user password */
4646
Blob pw; /* The nonce with user password appended */
4747
Blob sig; /* The signature field */
4848
49
+ blob_zero(pLogin);
50
+ if( g.urlUser==0 || strcmp(g.urlUser, "anonymous")==0 ){
51
+ return; /* If no login card for users "nobody" and "anonymous" */
52
+ }
4953
blob_zero(&nonce);
5054
blob_zero(&pw);
5155
sha1sum_blob(pPayload, &nonce);
5256
blob_copy(&pw, &nonce);
53
- blob_zero(pLogin);
54
- if( g.urlUser==0 ){
55
- user_select();
56
- zPw = db_text("", "SELECT pw FROM user WHERE uid=%d", g.userUid);
57
- zLogin = g.zLogin;
58
- }else{
59
- if( g.urlPasswd==0 ){
60
- if( strcmp(g.urlUser,"anonymous")!=0 ){
61
- char *zPrompt = mprintf("password for %s: ", g.urlUser);
62
- Blob x;
63
- prompt_for_password(zPrompt, &x, 0);
64
- free(zPrompt);
65
- g.urlPasswd = blob_str(&x);
66
- }else{
67
- g.urlPasswd = "";
68
- }
69
- }
57
+ zLogin = g.urlUser;
58
+ if( g.urlPasswd ){
59
+ zPw = g.urlPasswd;
60
+ }else{
61
+ url_prompt_for_password();
7062
zPw = g.urlPasswd;
71
- zLogin = g.urlUser;
63
+ if( !g.dontKeepUrl ) db_set("last-sync-pw", zPw, 0);
7264
}
7365
7466
/* The login card wants the SHA1 hash of the password, so convert the
7567
** password to its SHA1 hash it it isn't already a SHA1 hash.
7668
**
7769
--- src/http.c
+++ src/http.c
@@ -44,33 +44,25 @@
44 const char *zLogin; /* The user login name */
45 const char *zPw; /* The user password */
46 Blob pw; /* The nonce with user password appended */
47 Blob sig; /* The signature field */
48
 
 
 
 
49 blob_zero(&nonce);
50 blob_zero(&pw);
51 sha1sum_blob(pPayload, &nonce);
52 blob_copy(&pw, &nonce);
53 blob_zero(pLogin);
54 if( g.urlUser==0 ){
55 user_select();
56 zPw = db_text("", "SELECT pw FROM user WHERE uid=%d", g.userUid);
57 zLogin = g.zLogin;
58 }else{
59 if( g.urlPasswd==0 ){
60 if( strcmp(g.urlUser,"anonymous")!=0 ){
61 char *zPrompt = mprintf("password for %s: ", g.urlUser);
62 Blob x;
63 prompt_for_password(zPrompt, &x, 0);
64 free(zPrompt);
65 g.urlPasswd = blob_str(&x);
66 }else{
67 g.urlPasswd = "";
68 }
69 }
70 zPw = g.urlPasswd;
71 zLogin = g.urlUser;
72 }
73
74 /* The login card wants the SHA1 hash of the password, so convert the
75 ** password to its SHA1 hash it it isn't already a SHA1 hash.
76 **
77
--- src/http.c
+++ src/http.c
@@ -44,33 +44,25 @@
44 const char *zLogin; /* The user login name */
45 const char *zPw; /* The user password */
46 Blob pw; /* The nonce with user password appended */
47 Blob sig; /* The signature field */
48
49 blob_zero(pLogin);
50 if( g.urlUser==0 || strcmp(g.urlUser, "anonymous")==0 ){
51 return; /* If no login card for users "nobody" and "anonymous" */
52 }
53 blob_zero(&nonce);
54 blob_zero(&pw);
55 sha1sum_blob(pPayload, &nonce);
56 blob_copy(&pw, &nonce);
57 zLogin = g.urlUser;
58 if( g.urlPasswd ){
59 zPw = g.urlPasswd;
60 }else{
61 url_prompt_for_password();
 
 
 
 
 
 
 
 
 
 
 
 
62 zPw = g.urlPasswd;
63 if( !g.dontKeepUrl ) db_set("last-sync-pw", zPw, 0);
64 }
65
66 /* The login card wants the SHA1 hash of the password, so convert the
67 ** password to its SHA1 hash it it isn't already a SHA1 hash.
68 **
69
+1
--- src/main.c
+++ src/main.c
@@ -101,10 +101,11 @@
101101
char *urlPath; /* Pathname for http: */
102102
char *urlUser; /* User id for http: */
103103
char *urlPasswd; /* Password for http: */
104104
char *urlCanonical; /* Canonical representation of the URL */
105105
char *urlProxyAuth; /* Proxy-Authorizer: string */
106
+ int dontKeepUrl; /* Do not persist the URL */
106107
107108
const char *zLogin; /* Login name. "" if not logged in. */
108109
int noPswd; /* Logged in without password (on 127.0.0.1) */
109110
int userUid; /* Integer user id */
110111
111112
--- src/main.c
+++ src/main.c
@@ -101,10 +101,11 @@
101 char *urlPath; /* Pathname for http: */
102 char *urlUser; /* User id for http: */
103 char *urlPasswd; /* Password for http: */
104 char *urlCanonical; /* Canonical representation of the URL */
105 char *urlProxyAuth; /* Proxy-Authorizer: string */
 
106
107 const char *zLogin; /* Login name. "" if not logged in. */
108 int noPswd; /* Logged in without password (on 127.0.0.1) */
109 int userUid; /* Integer user id */
110
111
--- src/main.c
+++ src/main.c
@@ -101,10 +101,11 @@
101 char *urlPath; /* Pathname for http: */
102 char *urlUser; /* User id for http: */
103 char *urlPasswd; /* Password for http: */
104 char *urlCanonical; /* Canonical representation of the URL */
105 char *urlProxyAuth; /* Proxy-Authorizer: string */
106 int dontKeepUrl; /* Do not persist the URL */
107
108 const char *zLogin; /* Login name. "" if not logged in. */
109 int noPswd; /* Logged in without password (on 127.0.0.1) */
110 int userUid; /* Integer user id */
111
112
+34 -20
--- src/merge.c
+++ src/merge.c
@@ -30,56 +30,68 @@
3030
3131
3232
/*
3333
** COMMAND: merge
3434
**
35
-** Usage: %fossil merge VERSION
35
+** Usage: %fossil merge [--cherrypick] VERSION
3636
**
3737
** The argument is a version that should be merged into the current
38
-** checkout.
38
+** checkout. All changes from VERSION back to the nearest common
39
+** ancestor are merged. Except, if the --cherrypick option is used
40
+** only the changes associated with the single check-in VERSION are
41
+** merged.
3942
**
4043
** Only file content is merged. The result continues to use the
4144
** file and directory names from the current check-out even if those
4245
** names might have been changed in the branch being merged in.
4346
*/
4447
void merge_cmd(void){
4548
int vid; /* Current version */
4649
int mid; /* Version we are merging against */
4750
int pid; /* The pivot version - most recent common ancestor */
51
+ int detailFlag; /* True if the --detail option is present */
52
+ int pickFlag; /* True if the --cherrypick option is present */
4853
Stmt q;
49
- int detailFlag;
5054
5155
detailFlag = find_option("detail",0,0)!=0;
56
+ pickFlag = find_option("cherrypick",0,0)!=0;
5257
if( g.argc!=3 ){
5358
usage("VERSION");
5459
}
5560
db_must_be_within_tree();
5661
vid = db_lget_int("checkout", 0);
5762
if( vid==0 ){
58
- fossil_panic("nothing is checked out");
63
+ fossil_fatal("nothing is checked out");
5964
}
6065
mid = name_to_rid(g.argv[2]);
6166
if( mid==0 ){
62
- fossil_panic("not a version: %s", g.argv[2]);
67
+ fossil_fatal("not a version: %s", g.argv[2]);
6368
}
6469
if( mid>1 && !db_exists("SELECT 1 FROM plink WHERE cid=%d", mid) ){
65
- fossil_panic("not a version: %s", g.argv[2]);
66
- }
67
- pivot_set_primary(mid);
68
- pivot_set_secondary(vid);
69
- db_prepare(&q, "SELECT merge FROM vmerge WHERE id=0");
70
- while( db_step(&q)==SQLITE_ROW ){
71
- pivot_set_secondary(db_column_int(&q,0));
72
- }
73
- db_finalize(&q);
74
- pid = pivot_find();
75
- if( pid<=0 ){
76
- fossil_panic("cannot find a common ancestor between the current"
77
- "checkout and %s", g.argv[2]);
70
+ fossil_fatal("not a version: %s", g.argv[2]);
71
+ }
72
+ if( pickFlag ){
73
+ pid = db_int(0, "SELECT pid FROM plink WHERE cid=%d AND isprim", mid);
74
+ if( pid<=0 ){
75
+ fossil_fatal("cannot find an ancestor for %s", g.argv[2]);
76
+ }
77
+ }else{
78
+ pivot_set_primary(mid);
79
+ pivot_set_secondary(vid);
80
+ db_prepare(&q, "SELECT merge FROM vmerge WHERE id=0");
81
+ while( db_step(&q)==SQLITE_ROW ){
82
+ pivot_set_secondary(db_column_int(&q,0));
83
+ }
84
+ db_finalize(&q);
85
+ pid = pivot_find();
86
+ if( pid<=0 ){
87
+ fossil_fatal("cannot find a common ancestor between the current"
88
+ "checkout and %s", g.argv[2]);
89
+ }
7890
}
7991
if( pid>1 && !db_exists("SELECT 1 FROM plink WHERE cid=%d", pid) ){
80
- fossil_panic("not a version: record #%d", mid);
92
+ fossil_fatal("not a version: record #%d", mid);
8193
}
8294
vfile_check_signature(vid, 1);
8395
db_begin_transaction();
8496
undo_begin();
8597
load_vfile_from_rid(mid);
@@ -285,9 +297,11 @@
285297
286298
/*
287299
** Clean up the mid and pid VFILE entries. Then commit the changes.
288300
*/
289301
db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid);
290
- db_multi_exec("INSERT OR IGNORE INTO vmerge(id,merge) VALUES(0,%d)", mid);
302
+ if( !pickFlag ){
303
+ db_multi_exec("INSERT OR IGNORE INTO vmerge(id,merge) VALUES(0,%d)", mid);
304
+ }
291305
undo_finish();
292306
db_end_transaction(0);
293307
}
294308
--- src/merge.c
+++ src/merge.c
@@ -30,56 +30,68 @@
30
31
32 /*
33 ** COMMAND: merge
34 **
35 ** Usage: %fossil merge VERSION
36 **
37 ** The argument is a version that should be merged into the current
38 ** checkout.
 
 
 
39 **
40 ** Only file content is merged. The result continues to use the
41 ** file and directory names from the current check-out even if those
42 ** names might have been changed in the branch being merged in.
43 */
44 void merge_cmd(void){
45 int vid; /* Current version */
46 int mid; /* Version we are merging against */
47 int pid; /* The pivot version - most recent common ancestor */
 
 
48 Stmt q;
49 int detailFlag;
50
51 detailFlag = find_option("detail",0,0)!=0;
 
52 if( g.argc!=3 ){
53 usage("VERSION");
54 }
55 db_must_be_within_tree();
56 vid = db_lget_int("checkout", 0);
57 if( vid==0 ){
58 fossil_panic("nothing is checked out");
59 }
60 mid = name_to_rid(g.argv[2]);
61 if( mid==0 ){
62 fossil_panic("not a version: %s", g.argv[2]);
63 }
64 if( mid>1 && !db_exists("SELECT 1 FROM plink WHERE cid=%d", mid) ){
65 fossil_panic("not a version: %s", g.argv[2]);
66 }
67 pivot_set_primary(mid);
68 pivot_set_secondary(vid);
69 db_prepare(&q, "SELECT merge FROM vmerge WHERE id=0");
70 while( db_step(&q)==SQLITE_ROW ){
71 pivot_set_secondary(db_column_int(&q,0));
72 }
73 db_finalize(&q);
74 pid = pivot_find();
75 if( pid<=0 ){
76 fossil_panic("cannot find a common ancestor between the current"
77 "checkout and %s", g.argv[2]);
 
 
 
 
 
 
 
78 }
79 if( pid>1 && !db_exists("SELECT 1 FROM plink WHERE cid=%d", pid) ){
80 fossil_panic("not a version: record #%d", mid);
81 }
82 vfile_check_signature(vid, 1);
83 db_begin_transaction();
84 undo_begin();
85 load_vfile_from_rid(mid);
@@ -285,9 +297,11 @@
285
286 /*
287 ** Clean up the mid and pid VFILE entries. Then commit the changes.
288 */
289 db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid);
290 db_multi_exec("INSERT OR IGNORE INTO vmerge(id,merge) VALUES(0,%d)", mid);
 
 
291 undo_finish();
292 db_end_transaction(0);
293 }
294
--- src/merge.c
+++ src/merge.c
@@ -30,56 +30,68 @@
30
31
32 /*
33 ** COMMAND: merge
34 **
35 ** Usage: %fossil merge [--cherrypick] VERSION
36 **
37 ** The argument is a version that should be merged into the current
38 ** checkout. All changes from VERSION back to the nearest common
39 ** ancestor are merged. Except, if the --cherrypick option is used
40 ** only the changes associated with the single check-in VERSION are
41 ** merged.
42 **
43 ** Only file content is merged. The result continues to use the
44 ** file and directory names from the current check-out even if those
45 ** names might have been changed in the branch being merged in.
46 */
47 void merge_cmd(void){
48 int vid; /* Current version */
49 int mid; /* Version we are merging against */
50 int pid; /* The pivot version - most recent common ancestor */
51 int detailFlag; /* True if the --detail option is present */
52 int pickFlag; /* True if the --cherrypick option is present */
53 Stmt q;
 
54
55 detailFlag = find_option("detail",0,0)!=0;
56 pickFlag = find_option("cherrypick",0,0)!=0;
57 if( g.argc!=3 ){
58 usage("VERSION");
59 }
60 db_must_be_within_tree();
61 vid = db_lget_int("checkout", 0);
62 if( vid==0 ){
63 fossil_fatal("nothing is checked out");
64 }
65 mid = name_to_rid(g.argv[2]);
66 if( mid==0 ){
67 fossil_fatal("not a version: %s", g.argv[2]);
68 }
69 if( mid>1 && !db_exists("SELECT 1 FROM plink WHERE cid=%d", mid) ){
70 fossil_fatal("not a version: %s", g.argv[2]);
71 }
72 if( pickFlag ){
73 pid = db_int(0, "SELECT pid FROM plink WHERE cid=%d AND isprim", mid);
74 if( pid<=0 ){
75 fossil_fatal("cannot find an ancestor for %s", g.argv[2]);
76 }
77 }else{
78 pivot_set_primary(mid);
79 pivot_set_secondary(vid);
80 db_prepare(&q, "SELECT merge FROM vmerge WHERE id=0");
81 while( db_step(&q)==SQLITE_ROW ){
82 pivot_set_secondary(db_column_int(&q,0));
83 }
84 db_finalize(&q);
85 pid = pivot_find();
86 if( pid<=0 ){
87 fossil_fatal("cannot find a common ancestor between the current"
88 "checkout and %s", g.argv[2]);
89 }
90 }
91 if( pid>1 && !db_exists("SELECT 1 FROM plink WHERE cid=%d", pid) ){
92 fossil_fatal("not a version: record #%d", mid);
93 }
94 vfile_check_signature(vid, 1);
95 db_begin_transaction();
96 undo_begin();
97 load_vfile_from_rid(mid);
@@ -285,9 +297,11 @@
297
298 /*
299 ** Clean up the mid and pid VFILE entries. Then commit the changes.
300 */
301 db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid);
302 if( !pickFlag ){
303 db_multi_exec("INSERT OR IGNORE INTO vmerge(id,merge) VALUES(0,%d)", mid);
304 }
305 undo_finish();
306 db_end_transaction(0);
307 }
308
+1 -1
--- src/rebuild.c
+++ src/rebuild.c
@@ -384,11 +384,11 @@
384384
}
385385
}
386386
db_begin_transaction();
387387
db_multi_exec(
388388
"UPDATE user SET pw='';"
389
- "DELETE FROM config WHERE name='last-sync-url';"
389
+ "DELETE FROM config WHERE name GLOB 'last-sync-*';"
390390
);
391391
if( bVerily ){
392392
bNeedRebuild = db_exists("SELECT 1 FROM private");
393393
db_multi_exec(
394394
"DELETE FROM concealed;"
395395
--- src/rebuild.c
+++ src/rebuild.c
@@ -384,11 +384,11 @@
384 }
385 }
386 db_begin_transaction();
387 db_multi_exec(
388 "UPDATE user SET pw='';"
389 "DELETE FROM config WHERE name='last-sync-url';"
390 );
391 if( bVerily ){
392 bNeedRebuild = db_exists("SELECT 1 FROM private");
393 db_multi_exec(
394 "DELETE FROM concealed;"
395
--- src/rebuild.c
+++ src/rebuild.c
@@ -384,11 +384,11 @@
384 }
385 }
386 db_begin_transaction();
387 db_multi_exec(
388 "UPDATE user SET pw='';"
389 "DELETE FROM config WHERE name GLOB 'last-sync-*';"
390 );
391 if( bVerily ){
392 bNeedRebuild = db_exists("SELECT 1 FROM private");
393 db_multi_exec(
394 "DELETE FROM concealed;"
395
+27 -23
--- src/sync.c
+++ src/sync.c
@@ -42,10 +42,11 @@
4242
** if the argument is false.
4343
*/
4444
void autosync(int flags){
4545
const char *zUrl;
4646
const char *zAutosync;
47
+ const char *zPw;
4748
if( g.fNoSync ){
4849
return;
4950
}
5051
zAutosync = db_get("autosync", 0);
5152
if( zAutosync ){
@@ -60,17 +61,16 @@
6061
}
6162
zUrl = db_get("last-sync-url", 0);
6263
if( zUrl==0 ){
6364
return; /* No default server */
6465
}
66
+ zPw = db_get("last-sync-pw", 0);
6567
url_parse(zUrl);
66
- if( g.urlPort!=g.urlDfltPort ){
67
- printf("Autosync: %s://%s:%d%s\n",
68
- g.urlProtocol, g.urlName, g.urlPort, g.urlPath);
69
- }else{
70
- printf("Autosync: %s://%s%s\n", g.urlProtocol, g.urlName, g.urlPath);
68
+ if( g.urlUser!=0 && g.urlPasswd==0 ){
69
+ g.urlPasswd = mprintf("%s", zPw);
7170
}
71
+ printf("Autosync: %s\n", g.urlCanonical);
7272
url_enable_proxy("via proxy: ");
7373
client_sync((flags & AUTOSYNC_PUSH)!=0, 1, 0, 0, 0);
7474
}
7575
7676
/*
@@ -79,35 +79,36 @@
7979
** of a server to sync against. If no argument is given, use the
8080
** most recently synced URL. Remember the current URL for next time.
8181
*/
8282
void process_sync_args(void){
8383
const char *zUrl = 0;
84
+ const char *zPw = 0;
8485
int urlOptional = find_option("autourl",0,0)!=0;
85
- int dontKeepUrl = find_option("once",0,0)!=0;
86
+ g.dontKeepUrl = find_option("once",0,0)!=0;
8687
url_proxy_options();
8788
db_find_and_open_repository(1);
8889
if( g.argc==2 ){
8990
zUrl = db_get("last-sync-url", 0);
91
+ zPw = db_get("last-sync-pw", 0);
9092
}else if( g.argc==3 ){
9193
zUrl = g.argv[2];
9294
}
9395
if( zUrl==0 ){
9496
if( urlOptional ) exit(0);
9597
usage("URL");
9698
}
9799
url_parse(zUrl);
98
- if( !dontKeepUrl ){
99
- db_set("last-sync-url", g.urlIsFile ? g.urlCanonical : zUrl, 0);
100
+ if( !g.dontKeepUrl ){
101
+ db_set("last-sync-url", g.urlCanonical, 0);
102
+ if( g.urlPasswd ) db_set("last-sync-pw", g.urlPasswd, 0);
103
+ }
104
+ if( g.urlUser!=0 && g.urlPasswd==0 ){
105
+ g.urlPasswd = mprintf("%s", zPw);
100106
}
101107
user_select();
102108
if( g.argc==2 ){
103
- if( g.urlPort!=g.urlDfltPort ){
104
- printf("Server: %s://%s:%d%s\n",
105
- g.urlProtocol, g.urlName, g.urlPort, g.urlPath);
106
- }else{
107
- printf("Server: %s://%s%s\n", g.urlProtocol, g.urlName, g.urlPath);
108
- }
109
+ printf("Server: %s\n", g.urlCanonical);
109110
}
110111
url_enable_proxy("via proxy: ");
111112
}
112113
113114
/*
@@ -189,46 +190,49 @@
189190
}
190191
191192
/*
192193
** COMMAND: remote-url
193194
**
194
-** Usage: %fossil remote-url ?URL|off? --show-pw
195
+** Usage: %fossil remote-url ?URL|off?
195196
**
196197
** Query and/or change the default server URL used by the "pull", "push",
197198
** and "sync" commands.
198199
**
199
-** The userid and password are of the URL are not printed unless
200
-** the --show-pw option is used on the command-line.
201
-**
202200
** The remote-url is set automatically by a "clone" command or by any
203201
** "sync", "push", or "pull" command that specifies an explicit URL.
204202
** The default remote-url is used by auto-syncing and by "sync", "push",
205203
** "pull" that omit the server URL.
206204
**
207205
** See also: clone, push, pull, sync
208206
*/
209207
void remote_url_cmd(void){
210208
char *zUrl;
211
- int showPw = find_option("show-pw",0,0)!=0;
212209
db_find_and_open_repository(1);
213210
if( g.argc!=2 && g.argc!=3 ){
214211
usage("remote-url ?URL|off?");
215212
}
216213
if( g.argc==3 ){
217214
if( strcmp(g.argv[2],"off")==0 ){
218215
db_unset("last-sync-url", 0);
216
+ db_unset("last-sync-pw", 0);
219217
}else{
220218
url_parse(g.argv[2]);
221
- db_set("last-sync-url", g.urlIsFile ? g.urlCanonical : g.argv[2], 0);
219
+ if( g.urlUser && g.urlPasswd==0 ){
220
+ url_prompt_for_password();
221
+ }
222
+ db_set("last-sync-url", g.urlCanonical, 0);
223
+ if( g.urlPasswd ){
224
+ db_set("last-sync-pw", g.urlPasswd, 0);
225
+ }else{
226
+ db_unset("last-sync-pw", 0);
227
+ }
222228
}
223229
}
224230
zUrl = db_get("last-sync-url", 0);
225231
if( zUrl==0 ){
226232
printf("off\n");
227233
return;
228
- }else if( showPw ){
229
- g.urlCanonical = zUrl;
230234
}else{
231235
url_parse(zUrl);
236
+ printf("%s\n", g.urlCanonical);
232237
}
233
- printf("%s\n", g.urlCanonical);
234238
}
235239
--- src/sync.c
+++ src/sync.c
@@ -42,10 +42,11 @@
42 ** if the argument is false.
43 */
44 void autosync(int flags){
45 const char *zUrl;
46 const char *zAutosync;
 
47 if( g.fNoSync ){
48 return;
49 }
50 zAutosync = db_get("autosync", 0);
51 if( zAutosync ){
@@ -60,17 +61,16 @@
60 }
61 zUrl = db_get("last-sync-url", 0);
62 if( zUrl==0 ){
63 return; /* No default server */
64 }
 
65 url_parse(zUrl);
66 if( g.urlPort!=g.urlDfltPort ){
67 printf("Autosync: %s://%s:%d%s\n",
68 g.urlProtocol, g.urlName, g.urlPort, g.urlPath);
69 }else{
70 printf("Autosync: %s://%s%s\n", g.urlProtocol, g.urlName, g.urlPath);
71 }
 
72 url_enable_proxy("via proxy: ");
73 client_sync((flags & AUTOSYNC_PUSH)!=0, 1, 0, 0, 0);
74 }
75
76 /*
@@ -79,35 +79,36 @@
79 ** of a server to sync against. If no argument is given, use the
80 ** most recently synced URL. Remember the current URL for next time.
81 */
82 void process_sync_args(void){
83 const char *zUrl = 0;
 
84 int urlOptional = find_option("autourl",0,0)!=0;
85 int dontKeepUrl = find_option("once",0,0)!=0;
86 url_proxy_options();
87 db_find_and_open_repository(1);
88 if( g.argc==2 ){
89 zUrl = db_get("last-sync-url", 0);
 
90 }else if( g.argc==3 ){
91 zUrl = g.argv[2];
92 }
93 if( zUrl==0 ){
94 if( urlOptional ) exit(0);
95 usage("URL");
96 }
97 url_parse(zUrl);
98 if( !dontKeepUrl ){
99 db_set("last-sync-url", g.urlIsFile ? g.urlCanonical : zUrl, 0);
 
 
 
 
100 }
101 user_select();
102 if( g.argc==2 ){
103 if( g.urlPort!=g.urlDfltPort ){
104 printf("Server: %s://%s:%d%s\n",
105 g.urlProtocol, g.urlName, g.urlPort, g.urlPath);
106 }else{
107 printf("Server: %s://%s%s\n", g.urlProtocol, g.urlName, g.urlPath);
108 }
109 }
110 url_enable_proxy("via proxy: ");
111 }
112
113 /*
@@ -189,46 +190,49 @@
189 }
190
191 /*
192 ** COMMAND: remote-url
193 **
194 ** Usage: %fossil remote-url ?URL|off? --show-pw
195 **
196 ** Query and/or change the default server URL used by the "pull", "push",
197 ** and "sync" commands.
198 **
199 ** The userid and password are of the URL are not printed unless
200 ** the --show-pw option is used on the command-line.
201 **
202 ** The remote-url is set automatically by a "clone" command or by any
203 ** "sync", "push", or "pull" command that specifies an explicit URL.
204 ** The default remote-url is used by auto-syncing and by "sync", "push",
205 ** "pull" that omit the server URL.
206 **
207 ** See also: clone, push, pull, sync
208 */
209 void remote_url_cmd(void){
210 char *zUrl;
211 int showPw = find_option("show-pw",0,0)!=0;
212 db_find_and_open_repository(1);
213 if( g.argc!=2 && g.argc!=3 ){
214 usage("remote-url ?URL|off?");
215 }
216 if( g.argc==3 ){
217 if( strcmp(g.argv[2],"off")==0 ){
218 db_unset("last-sync-url", 0);
 
219 }else{
220 url_parse(g.argv[2]);
221 db_set("last-sync-url", g.urlIsFile ? g.urlCanonical : g.argv[2], 0);
 
 
 
 
 
 
 
 
222 }
223 }
224 zUrl = db_get("last-sync-url", 0);
225 if( zUrl==0 ){
226 printf("off\n");
227 return;
228 }else if( showPw ){
229 g.urlCanonical = zUrl;
230 }else{
231 url_parse(zUrl);
 
232 }
233 printf("%s\n", g.urlCanonical);
234 }
235
--- src/sync.c
+++ src/sync.c
@@ -42,10 +42,11 @@
42 ** if the argument is false.
43 */
44 void autosync(int flags){
45 const char *zUrl;
46 const char *zAutosync;
47 const char *zPw;
48 if( g.fNoSync ){
49 return;
50 }
51 zAutosync = db_get("autosync", 0);
52 if( zAutosync ){
@@ -60,17 +61,16 @@
61 }
62 zUrl = db_get("last-sync-url", 0);
63 if( zUrl==0 ){
64 return; /* No default server */
65 }
66 zPw = db_get("last-sync-pw", 0);
67 url_parse(zUrl);
68 if( g.urlUser!=0 && g.urlPasswd==0 ){
69 g.urlPasswd = mprintf("%s", zPw);
 
 
 
70 }
71 printf("Autosync: %s\n", g.urlCanonical);
72 url_enable_proxy("via proxy: ");
73 client_sync((flags & AUTOSYNC_PUSH)!=0, 1, 0, 0, 0);
74 }
75
76 /*
@@ -79,35 +79,36 @@
79 ** of a server to sync against. If no argument is given, use the
80 ** most recently synced URL. Remember the current URL for next time.
81 */
82 void process_sync_args(void){
83 const char *zUrl = 0;
84 const char *zPw = 0;
85 int urlOptional = find_option("autourl",0,0)!=0;
86 g.dontKeepUrl = find_option("once",0,0)!=0;
87 url_proxy_options();
88 db_find_and_open_repository(1);
89 if( g.argc==2 ){
90 zUrl = db_get("last-sync-url", 0);
91 zPw = db_get("last-sync-pw", 0);
92 }else if( g.argc==3 ){
93 zUrl = g.argv[2];
94 }
95 if( zUrl==0 ){
96 if( urlOptional ) exit(0);
97 usage("URL");
98 }
99 url_parse(zUrl);
100 if( !g.dontKeepUrl ){
101 db_set("last-sync-url", g.urlCanonical, 0);
102 if( g.urlPasswd ) db_set("last-sync-pw", g.urlPasswd, 0);
103 }
104 if( g.urlUser!=0 && g.urlPasswd==0 ){
105 g.urlPasswd = mprintf("%s", zPw);
106 }
107 user_select();
108 if( g.argc==2 ){
109 printf("Server: %s\n", g.urlCanonical);
 
 
 
 
 
110 }
111 url_enable_proxy("via proxy: ");
112 }
113
114 /*
@@ -189,46 +190,49 @@
190 }
191
192 /*
193 ** COMMAND: remote-url
194 **
195 ** Usage: %fossil remote-url ?URL|off?
196 **
197 ** Query and/or change the default server URL used by the "pull", "push",
198 ** and "sync" commands.
199 **
 
 
 
200 ** The remote-url is set automatically by a "clone" command or by any
201 ** "sync", "push", or "pull" command that specifies an explicit URL.
202 ** The default remote-url is used by auto-syncing and by "sync", "push",
203 ** "pull" that omit the server URL.
204 **
205 ** See also: clone, push, pull, sync
206 */
207 void remote_url_cmd(void){
208 char *zUrl;
 
209 db_find_and_open_repository(1);
210 if( g.argc!=2 && g.argc!=3 ){
211 usage("remote-url ?URL|off?");
212 }
213 if( g.argc==3 ){
214 if( strcmp(g.argv[2],"off")==0 ){
215 db_unset("last-sync-url", 0);
216 db_unset("last-sync-pw", 0);
217 }else{
218 url_parse(g.argv[2]);
219 if( g.urlUser && g.urlPasswd==0 ){
220 url_prompt_for_password();
221 }
222 db_set("last-sync-url", g.urlCanonical, 0);
223 if( g.urlPasswd ){
224 db_set("last-sync-pw", g.urlPasswd, 0);
225 }else{
226 db_unset("last-sync-pw", 0);
227 }
228 }
229 }
230 zUrl = db_get("last-sync-url", 0);
231 if( zUrl==0 ){
232 printf("off\n");
233 return;
 
 
234 }else{
235 url_parse(zUrl);
236 printf("%s\n", g.urlCanonical);
237 }
 
238 }
239
+26 -5
--- src/url.c
+++ src/url.c
@@ -37,11 +37,11 @@
3737
** g.urlDfltPort Default TCP port number (80 or 443).
3838
** g.urlPath Path name for HTTP or HTTPS.
3939
** g.urlUser Userid.
4040
** g.urlPasswd Password.
4141
** g.urlHostname HOST:PORT or just HOST if port is the default.
42
-** g.urlCanonical The URL in canonical form, omitting userid/password
42
+** g.urlCanonical The URL in canonical form, omitting the password
4343
**
4444
** HTTP url format is:
4545
**
4646
** http://userid:password@host:port/path?query#fragment
4747
**
@@ -49,10 +49,11 @@
4949
void url_parse(const char *zUrl){
5050
int i, j, c;
5151
char *zFile = 0;
5252
if( strncmp(zUrl, "http://", 7)==0 || strncmp(zUrl, "https://", 8)==0 ){
5353
int iStart;
54
+ char *zLogin;
5455
g.urlIsFile = 0;
5556
if( zUrl[4]=='s' ){
5657
g.urlIsHttps = 1;
5758
g.urlProtocol = "https";
5859
g.urlDfltPort = 443;
@@ -73,13 +74,15 @@
7374
dehttpize(g.urlPasswd);
7475
}
7576
for(j=i+1; (c=zUrl[j])!=0 && c!='/' && c!=':'; j++){}
7677
g.urlName = mprintf("%.*s", j-i-1, &zUrl[i+1]);
7778
i = j;
79
+ zLogin = mprintf("%t@", g.urlUser);
7880
}else{
7981
for(i=iStart; (c=zUrl[i])!=0 && c!='/' && c!=':'; i++){}
8082
g.urlName = mprintf("%.*s", i-iStart, &zUrl[iStart]);
83
+ zLogin = mprintf("");
8184
}
8285
for(j=0; g.urlName[j]; j++){ g.urlName[j] = tolower(g.urlName[j]); }
8386
if( c==':' ){
8487
g.urlPort = 0;
8588
i++;
@@ -94,16 +97,21 @@
9497
}
9598
g.urlPath = mprintf(&zUrl[i]);
9699
dehttpize(g.urlName);
97100
dehttpize(g.urlPath);
98101
if( g.urlDfltPort==g.urlPort ){
99
- g.urlCanonical = mprintf("%s://%T%T",
100
- g.urlProtocol, g.urlName, g.urlPath);
102
+ g.urlCanonical = mprintf(
103
+ "%s://%s%T%T",
104
+ g.urlProtocol, zLogin, g.urlName, g.urlPath
105
+ );
101106
}else{
102
- g.urlCanonical = mprintf("%s://%T:%d%T",
103
- g.urlProtocol, g.urlName, g.urlPort, g.urlPath);
107
+ g.urlCanonical = mprintf(
108
+ "%s://%s%T:%d%T",
109
+ g.urlProtocol, zLogin, g.urlName, g.urlPort, g.urlPath
110
+ );
104111
}
112
+ free(zLogin);
105113
}else if( strncmp(zUrl, "file:", 5)==0 ){
106114
g.urlIsFile = 1;
107115
if( zUrl[5]=='/' && zUrl[6]=='/' ){
108116
i = 7;
109117
}else{
@@ -296,5 +304,18 @@
296304
if( zName2 && zValue2 ){
297305
blob_appendf(&p->url, "%s%s=%T", zSep, zName2, zValue2);
298306
}
299307
return blob_str(&p->url);
300308
}
309
+
310
+/*
311
+** Prompt the user for the password for g.urlUser. Store the result
312
+** in g.urlPasswd.
313
+*/
314
+void url_prompt_for_password(void){
315
+ char *zPrompt = mprintf("password for %s: ", g.urlUser);
316
+ Blob x;
317
+ prompt_for_password(zPrompt, &x, 0);
318
+ free(zPrompt);
319
+ g.urlPasswd = mprintf("%b", &x);
320
+ blob_reset(&x);
321
+}
301322
--- src/url.c
+++ src/url.c
@@ -37,11 +37,11 @@
37 ** g.urlDfltPort Default TCP port number (80 or 443).
38 ** g.urlPath Path name for HTTP or HTTPS.
39 ** g.urlUser Userid.
40 ** g.urlPasswd Password.
41 ** g.urlHostname HOST:PORT or just HOST if port is the default.
42 ** g.urlCanonical The URL in canonical form, omitting userid/password
43 **
44 ** HTTP url format is:
45 **
46 ** http://userid:password@host:port/path?query#fragment
47 **
@@ -49,10 +49,11 @@
49 void url_parse(const char *zUrl){
50 int i, j, c;
51 char *zFile = 0;
52 if( strncmp(zUrl, "http://", 7)==0 || strncmp(zUrl, "https://", 8)==0 ){
53 int iStart;
 
54 g.urlIsFile = 0;
55 if( zUrl[4]=='s' ){
56 g.urlIsHttps = 1;
57 g.urlProtocol = "https";
58 g.urlDfltPort = 443;
@@ -73,13 +74,15 @@
73 dehttpize(g.urlPasswd);
74 }
75 for(j=i+1; (c=zUrl[j])!=0 && c!='/' && c!=':'; j++){}
76 g.urlName = mprintf("%.*s", j-i-1, &zUrl[i+1]);
77 i = j;
 
78 }else{
79 for(i=iStart; (c=zUrl[i])!=0 && c!='/' && c!=':'; i++){}
80 g.urlName = mprintf("%.*s", i-iStart, &zUrl[iStart]);
 
81 }
82 for(j=0; g.urlName[j]; j++){ g.urlName[j] = tolower(g.urlName[j]); }
83 if( c==':' ){
84 g.urlPort = 0;
85 i++;
@@ -94,16 +97,21 @@
94 }
95 g.urlPath = mprintf(&zUrl[i]);
96 dehttpize(g.urlName);
97 dehttpize(g.urlPath);
98 if( g.urlDfltPort==g.urlPort ){
99 g.urlCanonical = mprintf("%s://%T%T",
100 g.urlProtocol, g.urlName, g.urlPath);
 
 
101 }else{
102 g.urlCanonical = mprintf("%s://%T:%d%T",
103 g.urlProtocol, g.urlName, g.urlPort, g.urlPath);
 
 
104 }
 
105 }else if( strncmp(zUrl, "file:", 5)==0 ){
106 g.urlIsFile = 1;
107 if( zUrl[5]=='/' && zUrl[6]=='/' ){
108 i = 7;
109 }else{
@@ -296,5 +304,18 @@
296 if( zName2 && zValue2 ){
297 blob_appendf(&p->url, "%s%s=%T", zSep, zName2, zValue2);
298 }
299 return blob_str(&p->url);
300 }
 
 
 
 
 
 
 
 
 
 
 
 
 
301
--- src/url.c
+++ src/url.c
@@ -37,11 +37,11 @@
37 ** g.urlDfltPort Default TCP port number (80 or 443).
38 ** g.urlPath Path name for HTTP or HTTPS.
39 ** g.urlUser Userid.
40 ** g.urlPasswd Password.
41 ** g.urlHostname HOST:PORT or just HOST if port is the default.
42 ** g.urlCanonical The URL in canonical form, omitting the password
43 **
44 ** HTTP url format is:
45 **
46 ** http://userid:password@host:port/path?query#fragment
47 **
@@ -49,10 +49,11 @@
49 void url_parse(const char *zUrl){
50 int i, j, c;
51 char *zFile = 0;
52 if( strncmp(zUrl, "http://", 7)==0 || strncmp(zUrl, "https://", 8)==0 ){
53 int iStart;
54 char *zLogin;
55 g.urlIsFile = 0;
56 if( zUrl[4]=='s' ){
57 g.urlIsHttps = 1;
58 g.urlProtocol = "https";
59 g.urlDfltPort = 443;
@@ -73,13 +74,15 @@
74 dehttpize(g.urlPasswd);
75 }
76 for(j=i+1; (c=zUrl[j])!=0 && c!='/' && c!=':'; j++){}
77 g.urlName = mprintf("%.*s", j-i-1, &zUrl[i+1]);
78 i = j;
79 zLogin = mprintf("%t@", g.urlUser);
80 }else{
81 for(i=iStart; (c=zUrl[i])!=0 && c!='/' && c!=':'; i++){}
82 g.urlName = mprintf("%.*s", i-iStart, &zUrl[iStart]);
83 zLogin = mprintf("");
84 }
85 for(j=0; g.urlName[j]; j++){ g.urlName[j] = tolower(g.urlName[j]); }
86 if( c==':' ){
87 g.urlPort = 0;
88 i++;
@@ -94,16 +97,21 @@
97 }
98 g.urlPath = mprintf(&zUrl[i]);
99 dehttpize(g.urlName);
100 dehttpize(g.urlPath);
101 if( g.urlDfltPort==g.urlPort ){
102 g.urlCanonical = mprintf(
103 "%s://%s%T%T",
104 g.urlProtocol, zLogin, g.urlName, g.urlPath
105 );
106 }else{
107 g.urlCanonical = mprintf(
108 "%s://%s%T:%d%T",
109 g.urlProtocol, zLogin, g.urlName, g.urlPort, g.urlPath
110 );
111 }
112 free(zLogin);
113 }else if( strncmp(zUrl, "file:", 5)==0 ){
114 g.urlIsFile = 1;
115 if( zUrl[5]=='/' && zUrl[6]=='/' ){
116 i = 7;
117 }else{
@@ -296,5 +304,18 @@
304 if( zName2 && zValue2 ){
305 blob_appendf(&p->url, "%s%s=%T", zSep, zName2, zValue2);
306 }
307 return blob_str(&p->url);
308 }
309
310 /*
311 ** Prompt the user for the password for g.urlUser. Store the result
312 ** in g.urlPasswd.
313 */
314 void url_prompt_for_password(void){
315 char *zPrompt = mprintf("password for %s: ", g.urlUser);
316 Blob x;
317 prompt_for_password(zPrompt, &x, 0);
318 free(zPrompt);
319 g.urlPasswd = mprintf("%b", &x);
320 blob_reset(&x);
321 }
322
+4 -3
--- src/vfile.c
+++ src/vfile.c
@@ -146,11 +146,11 @@
146146
*/
147147
void vfile_check_signature(int vid, int notFileIsFatal){
148148
int nErr = 0;
149149
Stmt q;
150150
Blob fileCksum, origCksum;
151
- int checkMtime = db_get_boolean("mtime-changes", 0);
151
+ int checkMtime = db_get_boolean("mtime-changes", 1);
152152
153153
db_begin_transaction();
154154
db_prepare(&q, "SELECT id, %Q || pathname,"
155155
" vfile.mrid, deleted, chnged, uuid, mtime"
156156
" FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid"
@@ -167,11 +167,11 @@
167167
zName = db_column_text(&q, 1);
168168
rid = db_column_int(&q, 2);
169169
isDeleted = db_column_int(&q, 3);
170170
oldChnged = db_column_int(&q, 4);
171171
oldMtime = db_column_int64(&q, 6);
172
- if( !file_isfile(zName) && file_size(zName)>=0 ){
172
+ if( !file_isfile(zName) && file_size(0)>=0 ){
173173
if( notFileIsFatal ){
174174
fossil_warning("not a ordinary file: %s", zName);
175175
nErr++;
176176
}
177177
chnged = 1;
@@ -179,11 +179,12 @@
179179
chnged = oldChnged;
180180
}else if( isDeleted || rid==0 ){
181181
chnged = 1;
182182
}
183183
if( chnged!=1 ){
184
- currentMtime = file_mtime(zName);
184
+ currentMtime = file_mtime(0);
185
+ assert( currentMtime>0 );
185186
}
186187
if( chnged!=1 && (checkMtime==0 || currentMtime!=oldMtime) ){
187188
db_ephemeral_blob(&q, 5, &origCksum);
188189
if( sha1sum_file(zName, &fileCksum) ){
189190
blob_zero(&fileCksum);
190191
--- src/vfile.c
+++ src/vfile.c
@@ -146,11 +146,11 @@
146 */
147 void vfile_check_signature(int vid, int notFileIsFatal){
148 int nErr = 0;
149 Stmt q;
150 Blob fileCksum, origCksum;
151 int checkMtime = db_get_boolean("mtime-changes", 0);
152
153 db_begin_transaction();
154 db_prepare(&q, "SELECT id, %Q || pathname,"
155 " vfile.mrid, deleted, chnged, uuid, mtime"
156 " FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid"
@@ -167,11 +167,11 @@
167 zName = db_column_text(&q, 1);
168 rid = db_column_int(&q, 2);
169 isDeleted = db_column_int(&q, 3);
170 oldChnged = db_column_int(&q, 4);
171 oldMtime = db_column_int64(&q, 6);
172 if( !file_isfile(zName) && file_size(zName)>=0 ){
173 if( notFileIsFatal ){
174 fossil_warning("not a ordinary file: %s", zName);
175 nErr++;
176 }
177 chnged = 1;
@@ -179,11 +179,12 @@
179 chnged = oldChnged;
180 }else if( isDeleted || rid==0 ){
181 chnged = 1;
182 }
183 if( chnged!=1 ){
184 currentMtime = file_mtime(zName);
 
185 }
186 if( chnged!=1 && (checkMtime==0 || currentMtime!=oldMtime) ){
187 db_ephemeral_blob(&q, 5, &origCksum);
188 if( sha1sum_file(zName, &fileCksum) ){
189 blob_zero(&fileCksum);
190
--- src/vfile.c
+++ src/vfile.c
@@ -146,11 +146,11 @@
146 */
147 void vfile_check_signature(int vid, int notFileIsFatal){
148 int nErr = 0;
149 Stmt q;
150 Blob fileCksum, origCksum;
151 int checkMtime = db_get_boolean("mtime-changes", 1);
152
153 db_begin_transaction();
154 db_prepare(&q, "SELECT id, %Q || pathname,"
155 " vfile.mrid, deleted, chnged, uuid, mtime"
156 " FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid"
@@ -167,11 +167,11 @@
167 zName = db_column_text(&q, 1);
168 rid = db_column_int(&q, 2);
169 isDeleted = db_column_int(&q, 3);
170 oldChnged = db_column_int(&q, 4);
171 oldMtime = db_column_int64(&q, 6);
172 if( !file_isfile(zName) && file_size(0)>=0 ){
173 if( notFileIsFatal ){
174 fossil_warning("not a ordinary file: %s", zName);
175 nErr++;
176 }
177 chnged = 1;
@@ -179,11 +179,12 @@
179 chnged = oldChnged;
180 }else if( isDeleted || rid==0 ){
181 chnged = 1;
182 }
183 if( chnged!=1 ){
184 currentMtime = file_mtime(0);
185 assert( currentMtime>0 );
186 }
187 if( chnged!=1 && (checkMtime==0 || currentMtime!=oldMtime) ){
188 db_ephemeral_blob(&q, 5, &origCksum);
189 if( sha1sum_file(zName, &fileCksum) ){
190 blob_zero(&fileCksum);
191
+29 -11
--- src/xfer.c
+++ src/xfer.c
@@ -342,12 +342,11 @@
342342
db_finalize(&q);
343343
}
344344
345345
/*
346346
** Compute an SHA1 hash on the tail of pMsg. Verify that it matches the
347
-** the hash given in pHash. Return 1 on a successful match. Return 0
348
-** if there is a mismatch.
347
+** the hash given in pHash. Return non-zero for an error and 0 on success.
349348
*/
350349
static int check_tail_hash(Blob *pHash, Blob *pMsg){
351350
Blob tail;
352351
Blob h2;
353352
int rc;
@@ -354,11 +353,11 @@
354353
blob_tail(pMsg, &tail);
355354
sha1sum_blob(&tail, &h2);
356355
rc = blob_compare(pHash, &h2);
357356
blob_reset(&h2);
358357
blob_reset(&tail);
359
- return rc==0;
358
+ return rc;
360359
}
361360
362361
/*
363362
** Check the signature on an application/x-fossil payload received by
364363
** the HTTP server. The signature is a line of the following form:
@@ -378,12 +377,14 @@
378377
**
379378
** If anything fails to check out, no changes are made to privileges.
380379
**
381380
** Signature generation on the client side is handled by the
382381
** http_exchange() routine.
382
+**
383
+** Return non-zero for a login failure and zero for success.
383384
*/
384
-void check_login(Blob *pLogin, Blob *pNonce, Blob *pSig){
385
+int check_login(Blob *pLogin, Blob *pNonce, Blob *pSig){
385386
Stmt q;
386387
int rc = -1;
387388
char *zLogin = blob_terminate(pLogin);
388389
defossilize(zLogin);
389390
@@ -440,10 +441,11 @@
440441
441442
if( rc==0 ){
442443
/* If the login was successful. */
443444
login_set_anon_nobody_capabilities();
444445
}
446
+ return rc;
445447
}
446448
447449
/*
448450
** Send the content of all files in the unsent table.
449451
**
@@ -741,12 +743,19 @@
741743
if( blob_eq(&xfer.aToken[0], "login")
742744
&& xfer.nToken==4
743745
){
744746
if( disableLogin ){
745747
g.okRead = g.okWrite = 1;
746
- }else if( check_tail_hash(&xfer.aToken[2], xfer.pIn) ){
747
- check_login(&xfer.aToken[1], &xfer.aToken[2], &xfer.aToken[3]);
748
+ }else{
749
+ if( check_tail_hash(&xfer.aToken[2], xfer.pIn)
750
+ || check_login(&xfer.aToken[1], &xfer.aToken[2], &xfer.aToken[3])
751
+ ){
752
+ cgi_reset_content();
753
+ @ error login\sfailed
754
+ nErr++;
755
+ break;
756
+ }
748757
}
749758
}else
750759
751760
/* reqconfig NAME
752761
**
@@ -1067,10 +1076,11 @@
10671076
}
10681077
if( pushFlag ){
10691078
blob_appendf(&send, "push %s %s\n", zSCode, zPCode);
10701079
nCardSent++;
10711080
}
1081
+ go = 0;
10721082
10731083
/* Process the reply that came back from the server */
10741084
while( blob_line(&recv, &xfer.line) ){
10751085
if( blob_buffer(&xfer.line)[0]=='#' ){
10761086
continue;
@@ -1208,16 +1218,19 @@
12081218
db_set("cookie", blob_str(&xfer.aToken[1]), 0);
12091219
}else
12101220
12111221
/* message MESSAGE
12121222
**
1213
- ** Print a message. Similar to "error" but does not stop processing
1223
+ ** Print a message. Similar to "error" but does not stop processing.
1224
+ **
1225
+ ** If the "login failed" message is seen, clear the sync password prior
1226
+ ** to the next cycle.
12141227
*/
12151228
if( blob_eq(&xfer.aToken[0],"message") && xfer.nToken==2 ){
12161229
char *zMsg = blob_terminate(&xfer.aToken[1]);
12171230
defossilize(zMsg);
1218
- printf("\rServer says: %s\n", zMsg);
1231
+ if( zMsg ) printf("\rServer says: %s\n", zMsg);
12191232
}else
12201233
12211234
/* error MESSAGE
12221235
**
12231236
** Report an error and abandon the sync session.
@@ -1231,12 +1244,18 @@
12311244
*/
12321245
if( blob_eq(&xfer.aToken[0],"error") && xfer.nToken==2 ){
12331246
if( !cloneFlag || nCycle>0 ){
12341247
char *zMsg = blob_terminate(&xfer.aToken[1]);
12351248
defossilize(zMsg);
1236
- blob_appendf(&xfer.err, "server says: %s", zMsg);
1237
- printf("Server Error: %s\n", zMsg);
1249
+ if( strcmp(zMsg, "login failed")==0 ){
1250
+ if( !g.dontKeepUrl ) db_unset("last-sync-pw", 0);
1251
+ g.urlPasswd = 0;
1252
+ if( nCycle<2 ) go = 1;
1253
+ }else{
1254
+ blob_appendf(&xfer.err, "\rserver says: %s", zMsg);
1255
+ }
1256
+ printf("\rServer Error: %s\n", zMsg);
12381257
}
12391258
}else
12401259
12411260
/* Unknown message */
12421261
{
@@ -1264,11 +1283,10 @@
12641283
blob_size(&recv), nCardRcvd,
12651284
xfer.nFileRcvd, xfer.nDeltaRcvd + xfer.nDanglingFile);
12661285
}
12671286
blob_reset(&recv);
12681287
nCycle++;
1269
- go = 0;
12701288
12711289
/* If we received one or more files on the previous exchange but
12721290
** there are still phantoms, then go another round.
12731291
*/
12741292
nFileRecv = xfer.nFileRcvd + xfer.nDeltaRcvd + xfer.nDanglingFile;
12751293
--- src/xfer.c
+++ src/xfer.c
@@ -342,12 +342,11 @@
342 db_finalize(&q);
343 }
344
345 /*
346 ** Compute an SHA1 hash on the tail of pMsg. Verify that it matches the
347 ** the hash given in pHash. Return 1 on a successful match. Return 0
348 ** if there is a mismatch.
349 */
350 static int check_tail_hash(Blob *pHash, Blob *pMsg){
351 Blob tail;
352 Blob h2;
353 int rc;
@@ -354,11 +353,11 @@
354 blob_tail(pMsg, &tail);
355 sha1sum_blob(&tail, &h2);
356 rc = blob_compare(pHash, &h2);
357 blob_reset(&h2);
358 blob_reset(&tail);
359 return rc==0;
360 }
361
362 /*
363 ** Check the signature on an application/x-fossil payload received by
364 ** the HTTP server. The signature is a line of the following form:
@@ -378,12 +377,14 @@
378 **
379 ** If anything fails to check out, no changes are made to privileges.
380 **
381 ** Signature generation on the client side is handled by the
382 ** http_exchange() routine.
 
 
383 */
384 void check_login(Blob *pLogin, Blob *pNonce, Blob *pSig){
385 Stmt q;
386 int rc = -1;
387 char *zLogin = blob_terminate(pLogin);
388 defossilize(zLogin);
389
@@ -440,10 +441,11 @@
440
441 if( rc==0 ){
442 /* If the login was successful. */
443 login_set_anon_nobody_capabilities();
444 }
 
445 }
446
447 /*
448 ** Send the content of all files in the unsent table.
449 **
@@ -741,12 +743,19 @@
741 if( blob_eq(&xfer.aToken[0], "login")
742 && xfer.nToken==4
743 ){
744 if( disableLogin ){
745 g.okRead = g.okWrite = 1;
746 }else if( check_tail_hash(&xfer.aToken[2], xfer.pIn) ){
747 check_login(&xfer.aToken[1], &xfer.aToken[2], &xfer.aToken[3]);
 
 
 
 
 
 
 
748 }
749 }else
750
751 /* reqconfig NAME
752 **
@@ -1067,10 +1076,11 @@
1067 }
1068 if( pushFlag ){
1069 blob_appendf(&send, "push %s %s\n", zSCode, zPCode);
1070 nCardSent++;
1071 }
 
1072
1073 /* Process the reply that came back from the server */
1074 while( blob_line(&recv, &xfer.line) ){
1075 if( blob_buffer(&xfer.line)[0]=='#' ){
1076 continue;
@@ -1208,16 +1218,19 @@
1208 db_set("cookie", blob_str(&xfer.aToken[1]), 0);
1209 }else
1210
1211 /* message MESSAGE
1212 **
1213 ** Print a message. Similar to "error" but does not stop processing
 
 
 
1214 */
1215 if( blob_eq(&xfer.aToken[0],"message") && xfer.nToken==2 ){
1216 char *zMsg = blob_terminate(&xfer.aToken[1]);
1217 defossilize(zMsg);
1218 printf("\rServer says: %s\n", zMsg);
1219 }else
1220
1221 /* error MESSAGE
1222 **
1223 ** Report an error and abandon the sync session.
@@ -1231,12 +1244,18 @@
1231 */
1232 if( blob_eq(&xfer.aToken[0],"error") && xfer.nToken==2 ){
1233 if( !cloneFlag || nCycle>0 ){
1234 char *zMsg = blob_terminate(&xfer.aToken[1]);
1235 defossilize(zMsg);
1236 blob_appendf(&xfer.err, "server says: %s", zMsg);
1237 printf("Server Error: %s\n", zMsg);
 
 
 
 
 
 
1238 }
1239 }else
1240
1241 /* Unknown message */
1242 {
@@ -1264,11 +1283,10 @@
1264 blob_size(&recv), nCardRcvd,
1265 xfer.nFileRcvd, xfer.nDeltaRcvd + xfer.nDanglingFile);
1266 }
1267 blob_reset(&recv);
1268 nCycle++;
1269 go = 0;
1270
1271 /* If we received one or more files on the previous exchange but
1272 ** there are still phantoms, then go another round.
1273 */
1274 nFileRecv = xfer.nFileRcvd + xfer.nDeltaRcvd + xfer.nDanglingFile;
1275
--- src/xfer.c
+++ src/xfer.c
@@ -342,12 +342,11 @@
342 db_finalize(&q);
343 }
344
345 /*
346 ** Compute an SHA1 hash on the tail of pMsg. Verify that it matches the
347 ** the hash given in pHash. Return non-zero for an error and 0 on success.
 
348 */
349 static int check_tail_hash(Blob *pHash, Blob *pMsg){
350 Blob tail;
351 Blob h2;
352 int rc;
@@ -354,11 +353,11 @@
353 blob_tail(pMsg, &tail);
354 sha1sum_blob(&tail, &h2);
355 rc = blob_compare(pHash, &h2);
356 blob_reset(&h2);
357 blob_reset(&tail);
358 return rc;
359 }
360
361 /*
362 ** Check the signature on an application/x-fossil payload received by
363 ** the HTTP server. The signature is a line of the following form:
@@ -378,12 +377,14 @@
377 **
378 ** If anything fails to check out, no changes are made to privileges.
379 **
380 ** Signature generation on the client side is handled by the
381 ** http_exchange() routine.
382 **
383 ** Return non-zero for a login failure and zero for success.
384 */
385 int check_login(Blob *pLogin, Blob *pNonce, Blob *pSig){
386 Stmt q;
387 int rc = -1;
388 char *zLogin = blob_terminate(pLogin);
389 defossilize(zLogin);
390
@@ -440,10 +441,11 @@
441
442 if( rc==0 ){
443 /* If the login was successful. */
444 login_set_anon_nobody_capabilities();
445 }
446 return rc;
447 }
448
449 /*
450 ** Send the content of all files in the unsent table.
451 **
@@ -741,12 +743,19 @@
743 if( blob_eq(&xfer.aToken[0], "login")
744 && xfer.nToken==4
745 ){
746 if( disableLogin ){
747 g.okRead = g.okWrite = 1;
748 }else{
749 if( check_tail_hash(&xfer.aToken[2], xfer.pIn)
750 || check_login(&xfer.aToken[1], &xfer.aToken[2], &xfer.aToken[3])
751 ){
752 cgi_reset_content();
753 @ error login\sfailed
754 nErr++;
755 break;
756 }
757 }
758 }else
759
760 /* reqconfig NAME
761 **
@@ -1067,10 +1076,11 @@
1076 }
1077 if( pushFlag ){
1078 blob_appendf(&send, "push %s %s\n", zSCode, zPCode);
1079 nCardSent++;
1080 }
1081 go = 0;
1082
1083 /* Process the reply that came back from the server */
1084 while( blob_line(&recv, &xfer.line) ){
1085 if( blob_buffer(&xfer.line)[0]=='#' ){
1086 continue;
@@ -1208,16 +1218,19 @@
1218 db_set("cookie", blob_str(&xfer.aToken[1]), 0);
1219 }else
1220
1221 /* message MESSAGE
1222 **
1223 ** Print a message. Similar to "error" but does not stop processing.
1224 **
1225 ** If the "login failed" message is seen, clear the sync password prior
1226 ** to the next cycle.
1227 */
1228 if( blob_eq(&xfer.aToken[0],"message") && xfer.nToken==2 ){
1229 char *zMsg = blob_terminate(&xfer.aToken[1]);
1230 defossilize(zMsg);
1231 if( zMsg ) printf("\rServer says: %s\n", zMsg);
1232 }else
1233
1234 /* error MESSAGE
1235 **
1236 ** Report an error and abandon the sync session.
@@ -1231,12 +1244,18 @@
1244 */
1245 if( blob_eq(&xfer.aToken[0],"error") && xfer.nToken==2 ){
1246 if( !cloneFlag || nCycle>0 ){
1247 char *zMsg = blob_terminate(&xfer.aToken[1]);
1248 defossilize(zMsg);
1249 if( strcmp(zMsg, "login failed")==0 ){
1250 if( !g.dontKeepUrl ) db_unset("last-sync-pw", 0);
1251 g.urlPasswd = 0;
1252 if( nCycle<2 ) go = 1;
1253 }else{
1254 blob_appendf(&xfer.err, "\rserver says: %s", zMsg);
1255 }
1256 printf("\rServer Error: %s\n", zMsg);
1257 }
1258 }else
1259
1260 /* Unknown message */
1261 {
@@ -1264,11 +1283,10 @@
1283 blob_size(&recv), nCardRcvd,
1284 xfer.nFileRcvd, xfer.nDeltaRcvd + xfer.nDanglingFile);
1285 }
1286 blob_reset(&recv);
1287 nCycle++;
 
1288
1289 /* If we received one or more files on the previous exchange but
1290 ** there are still phantoms, then go another round.
1291 */
1292 nFileRecv = xfer.nFileRcvd + xfer.nDeltaRcvd + xfer.nDanglingFile;
1293
+1 -1
--- src/zip.c
+++ src/zip.c
@@ -408,11 +408,11 @@
408408
char *zName, *zRid;
409409
int nName, nRid;
410410
Blob zip;
411411
412412
login_check_credentials();
413
- if( !g.okZip && (!g.okRead || !g.okHistory) ){ login_needed(); return; }
413
+ if( !g.okZip ){ login_needed(); return; }
414414
zName = mprintf("%s", PD("name",""));
415415
nName = strlen(zName);
416416
zRid = mprintf("%s", PD("uuid",""));
417417
nRid = strlen(zRid);
418418
for(nName=strlen(zName)-1; nName>5; nName--){
419419
--- src/zip.c
+++ src/zip.c
@@ -408,11 +408,11 @@
408 char *zName, *zRid;
409 int nName, nRid;
410 Blob zip;
411
412 login_check_credentials();
413 if( !g.okZip && (!g.okRead || !g.okHistory) ){ login_needed(); return; }
414 zName = mprintf("%s", PD("name",""));
415 nName = strlen(zName);
416 zRid = mprintf("%s", PD("uuid",""));
417 nRid = strlen(zRid);
418 for(nName=strlen(zName)-1; nName>5; nName--){
419
--- src/zip.c
+++ src/zip.c
@@ -408,11 +408,11 @@
408 char *zName, *zRid;
409 int nName, nRid;
410 Blob zip;
411
412 login_check_credentials();
413 if( !g.okZip ){ login_needed(); return; }
414 zName = mprintf("%s", PD("name",""));
415 nName = strlen(zName);
416 zRid = mprintf("%s", PD("uuid",""));
417 nRid = strlen(zRid);
418 for(nName=strlen(zName)-1; nName>5; nName--){
419

Keyboard Shortcuts

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