Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Update the SSL branch to include all the latest changes. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | ssl |
Files: | files | file ages | folders |
SHA1: |
652f20ef9c55a6972485532d8110a087 |
User & Date: | drh 2010-01-21 22:03:24 |
References
2010-01-22
| ||
16:08 | • Ticket [0e3f8719] ssl-enabled fossil cannot log in to server status still Open with 1 other change artifact: c23da96e user: drh | |
06:36 | • Open ticket [0e3f8719]. artifact: bb5abf2e user: ron | |
2010-01-21
| ||
22:08 | • Fixed ticket [0e3f8719]. artifact: 65251cb8 user: drh | |
Context
2010-01-24
| ||
22:35 | Pull in the latest changes from trunk. check-in: 97311bd9 user: drh tags: ssl | |
2010-01-21
| ||
22:03 | Update the SSL branch to include all the latest changes. check-in: 652f20ef user: drh tags: ssl | |
20:53 | Merge experimental remote-url password handling changes into the trunk. check-in: a3c97c90 user: drh tags: trunk, release | |
20:18 | fix compile error check-in: 5fc80efd user: ron tags: ssl | |
Changes
Changes to Makefile.
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
#### The suffix to add to executable files. ".exe" for windows.
# Nothing for unix.
#
E =
#### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
#
# FOSSIL_ENABLE_SSL=1
#### C Compile and options for use in building executables that
# will run on the target platform. This is usually the same
# as BCC, unless you are cross-compiling. This C compiler builds
# the finished binary for fossil. The BCC compiler above is used
# for building intermediate code-generator tools.
#
|
| |
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
#### The suffix to add to executable files. ".exe" for windows. # Nothing for unix. # E = #### Enable HTTPS support via OpenSSL (links to libssl and libcrypto) # FOSSIL_ENABLE_SSL=1 #### C Compile and options for use in building executables that # will run on the target platform. This is usually the same # as BCC, unless you are cross-compiling. This C compiler builds # the finished binary for fossil. The BCC compiler above is used # for building intermediate code-generator tools. # |
Changes to src/add.c.
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
...
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
|| blob_compare(&pathname, pOmit)==0 ){ fossil_warning("cannot add %s", zPath); }else{ if( !file_is_simple_pathname(zPath) ){ fossil_fatal("filename contains illegal characters: %s", zPath); } if( db_exists("SELECT 1 FROM vfile WHERE pathname=%Q", zPath) ){ db_multi_exec("UPDATE vfile SET deleted=0 WHERE pathname=%Q", zPath); }else{ db_multi_exec( "INSERT INTO vfile(vid,deleted,rid,mrid,pathname)" "VALUES(%d,0,0,0,%Q)", vid, zPath); } printf("ADDED %s\n", zPath); } blob_reset(&pathname); ................................................................................ fossil_panic("no checkout to add to"); } db_begin_transaction(); if( !file_tree_name(g.zRepositoryName, &repo, 0) ){ blob_zero(&repo); } db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)"); for(i=2; i<g.argc; i++){ char *zName; int isDir; zName = mprintf("%/", g.argv[i]); isDir = file_isdir(zName); if( isDir==1 ){ |
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
...
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
|
|| blob_compare(&pathname, pOmit)==0 ){ fossil_warning("cannot add %s", zPath); }else{ if( !file_is_simple_pathname(zPath) ){ fossil_fatal("filename contains illegal characters: %s", zPath); } #ifdef __MINGW32__ if( db_exists("SELECT 1 FROM vfile WHERE pathname LIKE %Q", zPath) ){ db_multi_exec("UPDATE vfile SET deleted=0 WHERE pathname LIKE %Q", zPath); } #else if( db_exists("SELECT 1 FROM vfile WHERE pathname=%Q", zPath) ){ db_multi_exec("UPDATE vfile SET deleted=0 WHERE pathname=%Q", zPath); } #endif else{ db_multi_exec( "INSERT INTO vfile(vid,deleted,rid,mrid,pathname)" "VALUES(%d,0,0,0,%Q)", vid, zPath); } printf("ADDED %s\n", zPath); } blob_reset(&pathname); ................................................................................ fossil_panic("no checkout to add to"); } db_begin_transaction(); if( !file_tree_name(g.zRepositoryName, &repo, 0) ){ blob_zero(&repo); } db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)"); #ifdef __MINGW32__ db_multi_exec( "CREATE INDEX IF NOT EXISTS vfile_pathname " " ON vfile(pathname COLLATE nocase)" ); #endif for(i=2; i<g.argc; i++){ char *zName; int isDir; zName = mprintf("%/", g.argv[i]); isDir = file_isdir(zName); if( isDir==1 ){ |
Changes to src/configure.c.
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 |
db_multi_exec("%s", blob_str(&in)); configure_finalize_receive(); db_end_transaction(0); }else if( strncmp(zMethod, "pull", n)==0 || strncmp(zMethod, "push", n)==0 ){ int mask; const char *zServer; url_proxy_options(); if( g.argc!=4 && g.argc!=5 ){ usage("pull AREA ?URL?"); } mask = find_area(g.argv[3]); if( g.argc==5 ){ zServer = g.argv[4]; }else{ zServer = db_get("last-sync-url", 0); if( zServer==0 ){ fossil_fatal("no server specified"); } } url_parse(zServer); user_select(); if( strncmp(zMethod, "push", n)==0 ){ client_sync(0,0,0,0,mask); }else{ client_sync(0,0,0,mask,0); } }else |
> > > > > |
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 |
db_multi_exec("%s", blob_str(&in)); configure_finalize_receive(); db_end_transaction(0); }else if( strncmp(zMethod, "pull", n)==0 || strncmp(zMethod, "push", n)==0 ){ int mask; const char *zServer; const char *zPw; url_proxy_options(); if( g.argc!=4 && g.argc!=5 ){ usage("pull AREA ?URL?"); } mask = find_area(g.argv[3]); if( g.argc==5 ){ zServer = g.argv[4]; zPw = 0; g.dontKeepUrl = 1; }else{ zServer = db_get("last-sync-url", 0); if( zServer==0 ){ fossil_fatal("no server specified"); } zPw = db_get("last-sync-pw", 0); } url_parse(zServer); if( g.urlPasswd==0 && zPw ) g.urlPasswd = mprintf("%s", zPw); user_select(); if( strncmp(zMethod, "push", n)==0 ){ client_sync(0,0,0,0,mask); }else{ client_sync(0,0,0,mask,0); } }else |
Changes to src/db.c.
1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 |
** ** localauth If enabled, require that HTTP connections from ** 127.0.0.1 be authenticated by password. If ** false, all HTTP requests from localhost have ** unrestricted access to the repository. ** ** mtime-changes Use file modification times (mtimes) to detect when ** files have been modified. ** ** pgp-command Command used to clear-sign manifests at check-in. ** The default is "gpg --clearsign -o ". ** ** proxy URL of the HTTP proxy. If undefined or "off" then ** the "http_proxy" environment variable is consulted. ** If the http_proxy environment variable is undefined |
| |
1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 |
**
** localauth If enabled, require that HTTP connections from
** 127.0.0.1 be authenticated by password. If
** false, all HTTP requests from localhost have
** unrestricted access to the repository.
**
** mtime-changes Use file modification times (mtimes) to detect when
** files have been modified. (Default "on".)
**
** pgp-command Command used to clear-sign manifests at check-in.
** The default is "gpg --clearsign -o ".
**
** proxy URL of the HTTP proxy. If undefined or "off" then
** the "http_proxy" environment variable is consulted.
** If the http_proxy environment variable is undefined
|
Changes to src/file.c.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 .. 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 ... 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
*/ #include "config.h" #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include "file.h" /* ** Return the size of a file in bytes. Return -1 if the file does not ** exist. */ i64 file_size(const char *zFilename){ struct stat buf; if( stat(zFilename, &buf)!=0 ){ return -1; } return buf.st_size; } /* ** Return the modification time for a file. Return -1 if the file ** does not exist. */ i64 file_mtime(const char *zFilename){ struct stat buf; if( stat(zFilename, &buf)!=0 ){ return -1; } return buf.st_mtime; } /* ** Return the tail of a file pathname. The tail is the last component ** of the path. For example, the tail of "/a/b/c.d" is "c.d". */ const char *file_tail(const char *z){ ................................................................................ while( (got=fread(zBuf, 1, sizeof(zBuf), in))>0 ){ fwrite(zBuf, 1, got, out); } fclose(in); fclose(out); } /* ** Return TRUE if the named file is an ordinary file. Return false ** for directories, devices, fifos, symlinks, etc. */ int file_isfile(const char *zFilename){ struct stat buf; if( stat(zFilename, &buf)!=0 ){ return 0; } return S_ISREG(buf.st_mode); } /* ** Return TRUE if the named file is an executable. Return false ** for directories, devices, fifos, symlinks, etc. */ int file_isexe(const char *zFilename){ struct stat buf; if( stat(zFilename, &buf)!=0 ){ return 0; } if( !S_ISREG(buf.st_mode) ) return 0; #ifdef __MINGW32__ return ((S_IXUSR)&buf.st_mode)!=0; #else return ((S_IXUSR|S_IXGRP|S_IXOTH)&buf.st_mode)!=0; #endif } /* ** Set or clear the execute bit on a file. */ void file_setexe(const char *zFilename, int onoff){ #ifndef __MINGW32__ struct stat buf; if( stat(zFilename, &buf)!=0 ) return; ................................................................................ if( (buf.st_mode & 0111)!=0 ){ chmod(zFilename, buf.st_mode & ~0111); } } #endif } /* ** Return 1 if zFilename is a directory. Return 0 if zFilename ** does not exist. Return 2 if zFilename exists but is something ** other than a directory. */ int file_isdir(const char *zFilename){ struct stat buf; int rc; char *zFN; zFN = mprintf("%s", zFilename); file_simplify_name(zFN, strlen(zFN)); rc = stat(zFN, &buf); free(zFN); return rc!=0 ? 0 : (S_ISDIR(buf.st_mode) ? 1 : 2); } /* ** Create the directory named in the argument, if it does not already ** exist. If forceFlag is 1, delete any prior non-directory object ** with the same name. ** ** Return the number of errors. */ |
> > > > > < > > > | > | < > > > | > > | | < > > > > > > > > > | > < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < > > > > > > < > < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 ... 139 140 141 142 143 144 145 146 147 148 149 150 151 152 ... 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
*/ #include "config.h" #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include "file.h" /* ** The file status information from the most recent stat() call. */ static struct stat fileStat; static int fileStatValid = 0; /* ** Fill in the fileStat variable for the file named zFilename. ** If zFilename==0, then use the previous value of fileStat if ** there is a previous value. ** ** Return the number of errors. No error messages are generated. */ static int getStat(const char *zFilename){ if( zFilename==0 ){ if( fileStatValid==0 ) return 1; }else{ if( stat(zFilename, &fileStat)!=0 ) return 1; fileStatValid = 1; } return 0; } /* ** Return the size of a file in bytes. Return -1 if the file does not ** exist. If zFilename is NULL, return the size of the most recently ** stat-ed file. */ i64 file_size(const char *zFilename){ return getStat(zFilename) ? -1 : fileStat.st_size; } /* ** Return the modification time for a file. Return -1 if the file ** does not exist. If zFilename is NULL return the size of the most ** recently stat-ed file. */ i64 file_mtime(const char *zFilename){ return getStat(zFilename) ? -1 : fileStat.st_mtime; } /* ** Return TRUE if the named file is an ordinary file. Return false ** for directories, devices, fifos, symlinks, etc. */ int file_isfile(const char *zFilename){ return getStat(zFilename) ? 0 : S_ISREG(fileStat.st_mode); } /* ** Return TRUE if the named file is an executable. Return false ** for directories, devices, fifos, symlinks, etc. */ int file_isexe(const char *zFilename){ if( getStat(zFilename) || !S_ISREG(fileStat.st_mode) ) return 0; #ifdef __MINGW32__ return ((S_IXUSR)&fileStat.st_mode)!=0; #else return ((S_IXUSR|S_IXGRP|S_IXOTH)&fileStat.st_mode)!=0; #endif } /* ** Return 1 if zFilename is a directory. Return 0 if zFilename ** does not exist. Return 2 if zFilename exists but is something ** other than a directory. */ int file_isdir(const char *zFilename){ int rc; if( zFilename ){ char *zFN = mprintf("%s", zFilename); file_simplify_name(zFN, strlen(zFN)); rc = getStat(zFN); free(zFN); }else{ rc = getStat(0); } return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2); } /* ** Return the tail of a file pathname. The tail is the last component ** of the path. For example, the tail of "/a/b/c.d" is "c.d". */ const char *file_tail(const char *z){ ................................................................................ while( (got=fread(zBuf, 1, sizeof(zBuf), in))>0 ){ fwrite(zBuf, 1, got, out); } fclose(in); fclose(out); } /* ** Set or clear the execute bit on a file. */ void file_setexe(const char *zFilename, int onoff){ #ifndef __MINGW32__ struct stat buf; if( stat(zFilename, &buf)!=0 ) return; ................................................................................ if( (buf.st_mode & 0111)!=0 ){ chmod(zFilename, buf.st_mode & ~0111); } } #endif } /* ** Create the directory named in the argument, if it does not already ** exist. If forceFlag is 1, delete any prior non-directory object ** with the same name. ** ** Return the number of errors. */ |
Changes to src/http.c.
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
static void http_build_login_card(Blob *pPayload, Blob *pLogin){ Blob nonce; /* The nonce */ const char *zLogin; /* The user login name */ const char *zPw; /* The user password */ Blob pw; /* The nonce with user password appended */ Blob sig; /* The signature field */ blob_zero(&nonce); blob_zero(&pw); sha1sum_blob(pPayload, &nonce); blob_copy(&pw, &nonce); blob_zero(pLogin); if( g.urlUser==0 ){ user_select(); zPw = db_text("", "SELECT pw FROM user WHERE uid=%d", g.userUid); zLogin = g.zLogin; }else{ if( g.urlPasswd==0 ){ if( strcmp(g.urlUser,"anonymous")!=0 ){ char *zPrompt = mprintf("password for %s: ", g.urlUser); Blob x; prompt_for_password(zPrompt, &x, 0); free(zPrompt); g.urlPasswd = blob_str(&x); }else{ g.urlPasswd = ""; } } zPw = g.urlPasswd; zLogin = g.urlUser; } /* The login card wants the SHA1 hash of the password, so convert the ** password to its SHA1 hash it it isn't already a SHA1 hash. ** ** Except, if the password begins with "*" then use the characters ** after the "*" as a cleartext password. Put an "*" at the beginning |
> > > > < < < < | < | < < < < < | | < < < > < > |
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
static void http_build_login_card(Blob *pPayload, Blob *pLogin){ Blob nonce; /* The nonce */ const char *zLogin; /* The user login name */ const char *zPw; /* The user password */ Blob pw; /* The nonce with user password appended */ Blob sig; /* The signature field */ blob_zero(pLogin); if( g.urlUser==0 || strcmp(g.urlUser, "anonymous")==0 ){ return; /* If no login card for users "nobody" and "anonymous" */ } blob_zero(&nonce); blob_zero(&pw); sha1sum_blob(pPayload, &nonce); blob_copy(&pw, &nonce); zLogin = g.urlUser; if( g.urlPasswd ){ zPw = g.urlPasswd; }else{ url_prompt_for_password(); zPw = g.urlPasswd; if( !g.dontKeepUrl ) db_set("last-sync-pw", zPw, 0); } /* The login card wants the SHA1 hash of the password, so convert the ** password to its SHA1 hash it it isn't already a SHA1 hash. ** ** Except, if the password begins with "*" then use the characters ** after the "*" as a cleartext password. Put an "*" at the beginning |
Changes to src/main.c.
99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
int urlPort; /* TCP port number for http: or https: */ int urlDfltPort; /* The default port for the given protocol */ char *urlPath; /* Pathname for http: */ char *urlUser; /* User id for http: */ char *urlPasswd; /* Password for http: */ char *urlCanonical; /* Canonical representation of the URL */ char *urlProxyAuth; /* Proxy-Authorizer: string */ const char *zLogin; /* Login name. "" if not logged in. */ int noPswd; /* Logged in without password (on 127.0.0.1) */ int userUid; /* Integer user id */ /* Information used to populate the RCVFROM table */ int rcvid; /* The rcvid. 0 if not yet defined. */ |
> |
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
int urlPort; /* TCP port number for http: or https: */
int urlDfltPort; /* The default port for the given protocol */
char *urlPath; /* Pathname for http: */
char *urlUser; /* User id for http: */
char *urlPasswd; /* Password for http: */
char *urlCanonical; /* Canonical representation of the URL */
char *urlProxyAuth; /* Proxy-Authorizer: string */
int dontKeepUrl; /* Do not persist the URL */
const char *zLogin; /* Login name. "" if not logged in. */
int noPswd; /* Logged in without password (on 127.0.0.1) */
int userUid; /* Integer user id */
/* Information used to populate the RCVFROM table */
int rcvid; /* The rcvid. 0 if not yet defined. */
|
Changes to src/rebuild.c.
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 |
if( blob_str(&ans)[0]!='y' ){ exit(1); } } db_begin_transaction(); db_multi_exec( "UPDATE user SET pw='';" "DELETE FROM config WHERE name='last-sync-url';" ); if( bVerily ){ bNeedRebuild = db_exists("SELECT 1 FROM private"); db_multi_exec( "DELETE FROM concealed;" "UPDATE rcvfrom SET ipaddr='unknown';" "UPDATE user SET photo=NULL, info='';" |
| |
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 |
if( blob_str(&ans)[0]!='y' ){ exit(1); } } db_begin_transaction(); db_multi_exec( "UPDATE user SET pw='';" "DELETE FROM config WHERE name GLOB 'last-sync-*';" ); if( bVerily ){ bNeedRebuild = db_exists("SELECT 1 FROM private"); db_multi_exec( "DELETE FROM concealed;" "UPDATE rcvfrom SET ipaddr='unknown';" "UPDATE user SET photo=NULL, info='';" |
Changes to src/sync.c.
40 41 42 43 44 45 46 47 48 49 50 51 52 53 .. 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 ... 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 |
** If the respository is configured for autosyncing, then do an ** autosync. This will be a pull if the argument is true or a push ** if the argument is false. */ void autosync(int flags){ const char *zUrl; const char *zAutosync; if( g.fNoSync ){ return; } zAutosync = db_get("autosync", 0); if( zAutosync ){ if( (flags & AUTOSYNC_PUSH)!=0 && memcmp(zAutosync,"pull",4)==0 ){ return; /* Do not auto-push when autosync=pullonly */ ................................................................................ }else{ /* Autosync defaults on. To make it default off, "return" here. */ } zUrl = db_get("last-sync-url", 0); if( zUrl==0 ){ return; /* No default server */ } url_parse(zUrl); if( g.urlPort!=g.urlDfltPort ){ printf("Autosync: %s://%s:%d%s\n", g.urlProtocol, g.urlName, g.urlPort, g.urlPath); }else{ printf("Autosync: %s://%s%s\n", g.urlProtocol, g.urlName, g.urlPath); } url_enable_proxy("via proxy: "); client_sync((flags & AUTOSYNC_PUSH)!=0, 1, 0, 0, 0); } /* ** This routine processes the command-line argument for push, pull, ** and sync. If a command-line argument is given, that is the URL ** of a server to sync against. If no argument is given, use the ** most recently synced URL. Remember the current URL for next time. */ void process_sync_args(void){ const char *zUrl = 0; int urlOptional = find_option("autourl",0,0)!=0; int dontKeepUrl = find_option("once",0,0)!=0; url_proxy_options(); db_find_and_open_repository(1); if( g.argc==2 ){ zUrl = db_get("last-sync-url", 0); }else if( g.argc==3 ){ zUrl = g.argv[2]; } if( zUrl==0 ){ if( urlOptional ) exit(0); usage("URL"); } url_parse(zUrl); if( !dontKeepUrl ){ db_set("last-sync-url", g.urlIsFile ? g.urlCanonical : zUrl, 0); } user_select(); if( g.argc==2 ){ if( g.urlPort!=g.urlDfltPort ){ printf("Server: %s://%s:%d%s\n", g.urlProtocol, g.urlName, g.urlPort, g.urlPath); }else{ printf("Server: %s://%s%s\n", g.urlProtocol, g.urlName, g.urlPath); } } url_enable_proxy("via proxy: "); } /* ** COMMAND: pull ** ................................................................................ process_sync_args(); client_sync(1,1,0,0,0); } /* ** COMMAND: remote-url ** ** Usage: %fossil remote-url ?URL|off? --show-pw ** ** Query and/or change the default server URL used by the "pull", "push", ** and "sync" commands. ** ** The userid and password are of the URL are not printed unless ** the --show-pw option is used on the command-line. ** ** The remote-url is set automatically by a "clone" command or by any ** "sync", "push", or "pull" command that specifies an explicit URL. ** The default remote-url is used by auto-syncing and by "sync", "push", ** "pull" that omit the server URL. ** ** See also: clone, push, pull, sync */ void remote_url_cmd(void){ char *zUrl; int showPw = find_option("show-pw",0,0)!=0; db_find_and_open_repository(1); if( g.argc!=2 && g.argc!=3 ){ usage("remote-url ?URL|off?"); } if( g.argc==3 ){ if( strcmp(g.argv[2],"off")==0 ){ db_unset("last-sync-url", 0); }else{ url_parse(g.argv[2]); db_set("last-sync-url", g.urlIsFile ? g.urlCanonical : g.argv[2], 0); } } zUrl = db_get("last-sync-url", 0); if( zUrl==0 ){ printf("off\n"); return; }else if( showPw ){ g.urlCanonical = zUrl; }else{ url_parse(zUrl); } printf("%s\n", g.urlCanonical); } |
> > < | | < < > > | > | | > > > > < | < < < < | < < < < > > > > | > > > > > < < < | | > |
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 .. 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 ... 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
** If the respository is configured for autosyncing, then do an ** autosync. This will be a pull if the argument is true or a push ** if the argument is false. */ void autosync(int flags){ const char *zUrl; const char *zAutosync; const char *zPw; if( g.fNoSync ){ return; } zAutosync = db_get("autosync", 0); if( zAutosync ){ if( (flags & AUTOSYNC_PUSH)!=0 && memcmp(zAutosync,"pull",4)==0 ){ return; /* Do not auto-push when autosync=pullonly */ ................................................................................ }else{ /* Autosync defaults on. To make it default off, "return" here. */ } zUrl = db_get("last-sync-url", 0); if( zUrl==0 ){ return; /* No default server */ } zPw = db_get("last-sync-pw", 0); url_parse(zUrl); if( g.urlUser!=0 && g.urlPasswd==0 ){ g.urlPasswd = mprintf("%s", zPw); } printf("Autosync: %s\n", g.urlCanonical); url_enable_proxy("via proxy: "); client_sync((flags & AUTOSYNC_PUSH)!=0, 1, 0, 0, 0); } /* ** This routine processes the command-line argument for push, pull, ** and sync. If a command-line argument is given, that is the URL ** of a server to sync against. If no argument is given, use the ** most recently synced URL. Remember the current URL for next time. */ void process_sync_args(void){ const char *zUrl = 0; const char *zPw = 0; int urlOptional = find_option("autourl",0,0)!=0; g.dontKeepUrl = find_option("once",0,0)!=0; url_proxy_options(); db_find_and_open_repository(1); if( g.argc==2 ){ zUrl = db_get("last-sync-url", 0); zPw = db_get("last-sync-pw", 0); }else if( g.argc==3 ){ zUrl = g.argv[2]; } if( zUrl==0 ){ if( urlOptional ) exit(0); usage("URL"); } url_parse(zUrl); if( !g.dontKeepUrl ){ db_set("last-sync-url", g.urlCanonical, 0); if( g.urlPasswd ) db_set("last-sync-pw", g.urlPasswd, 0); } if( g.urlUser!=0 && g.urlPasswd==0 ){ g.urlPasswd = mprintf("%s", zPw); } user_select(); if( g.argc==2 ){ printf("Server: %s\n", g.urlCanonical); } url_enable_proxy("via proxy: "); } /* ** COMMAND: pull ** ................................................................................ process_sync_args(); client_sync(1,1,0,0,0); } /* ** COMMAND: remote-url ** ** Usage: %fossil remote-url ?URL|off? ** ** Query and/or change the default server URL used by the "pull", "push", ** and "sync" commands. ** ** The remote-url is set automatically by a "clone" command or by any ** "sync", "push", or "pull" command that specifies an explicit URL. ** The default remote-url is used by auto-syncing and by "sync", "push", ** "pull" that omit the server URL. ** ** See also: clone, push, pull, sync */ void remote_url_cmd(void){ char *zUrl; db_find_and_open_repository(1); if( g.argc!=2 && g.argc!=3 ){ usage("remote-url ?URL|off?"); } if( g.argc==3 ){ if( strcmp(g.argv[2],"off")==0 ){ db_unset("last-sync-url", 0); db_unset("last-sync-pw", 0); }else{ url_parse(g.argv[2]); if( g.urlUser && g.urlPasswd==0 ){ url_prompt_for_password(); } db_set("last-sync-url", g.urlCanonical, 0); if( g.urlPasswd ){ db_set("last-sync-pw", g.urlPasswd, 0); }else{ db_unset("last-sync-pw", 0); } } } zUrl = db_get("last-sync-url", 0); if( zUrl==0 ){ printf("off\n"); return; }else{ url_parse(zUrl); printf("%s\n", g.urlCanonical); } } |
Changes to src/url.c.
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 .. 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 .. 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 ... 294 295 296 297 298 299 300 |
** g.urlName Hostname for HTTP: or HTTPS:. Filename for FILE: ** g.urlPort TCP port number for HTTP or HTTPS. ** g.urlDfltPort Default TCP port number (80 or 443). ** g.urlPath Path name for HTTP or HTTPS. ** g.urlUser Userid. ** g.urlPasswd Password. ** g.urlHostname HOST:PORT or just HOST if port is the default. ** g.urlCanonical The URL in canonical form, omitting userid/password ** ** HTTP url format is: ** ** http://userid:password@host:port/path?query#fragment ** */ void url_parse(const char *zUrl){ int i, j, c; char *zFile = 0; if( strncmp(zUrl, "http://", 7)==0 || strncmp(zUrl, "https://", 8)==0 ){ int iStart; g.urlIsFile = 0; if( zUrl[4]=='s' ){ g.urlIsHttps = 1; g.urlProtocol = "https"; g.urlDfltPort = 443; iStart = 8; }else{ ................................................................................ if( j<i ){ g.urlPasswd = mprintf("%.*s", i-j-1, &zUrl[j+1]); dehttpize(g.urlPasswd); } for(j=i+1; (c=zUrl[j])!=0 && c!='/' && c!=':'; j++){} g.urlName = mprintf("%.*s", j-i-1, &zUrl[i+1]); i = j; }else{ for(i=iStart; (c=zUrl[i])!=0 && c!='/' && c!=':'; i++){} g.urlName = mprintf("%.*s", i-iStart, &zUrl[iStart]); } for(j=0; g.urlName[j]; j++){ g.urlName[j] = tolower(g.urlName[j]); } if( c==':' ){ g.urlPort = 0; i++; while( (c = zUrl[i])!=0 && isdigit(c) ){ g.urlPort = g.urlPort*10 + c - '0'; ................................................................................ g.urlPort = g.urlDfltPort; g.urlHostname = g.urlName; } g.urlPath = mprintf(&zUrl[i]); dehttpize(g.urlName); dehttpize(g.urlPath); if( g.urlDfltPort==g.urlPort ){ g.urlCanonical = mprintf("%s://%T%T", g.urlProtocol, g.urlName, g.urlPath); }else{ g.urlCanonical = mprintf("%s://%T:%d%T", g.urlProtocol, g.urlName, g.urlPort, g.urlPath); } }else if( strncmp(zUrl, "file:", 5)==0 ){ g.urlIsFile = 1; if( zUrl[5]=='/' && zUrl[6]=='/' ){ i = 7; }else{ i = 5; } ................................................................................ blob_appendf(&p->url, "%s%s=%T", zSep, zName1, zValue1); } if( zName2 && zValue2 ){ blob_appendf(&p->url, "%s%s=%T", zSep, zName2, zValue2); } return blob_str(&p->url); } |
| > > > | > | > | > | > > > > > > > > > > > > > > > |
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 .. 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 .. 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 ... 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 |
** g.urlName Hostname for HTTP: or HTTPS:. Filename for FILE: ** g.urlPort TCP port number for HTTP or HTTPS. ** g.urlDfltPort Default TCP port number (80 or 443). ** g.urlPath Path name for HTTP or HTTPS. ** g.urlUser Userid. ** g.urlPasswd Password. ** g.urlHostname HOST:PORT or just HOST if port is the default. ** g.urlCanonical The URL in canonical form, omitting the password ** ** HTTP url format is: ** ** http://userid:password@host:port/path?query#fragment ** */ void url_parse(const char *zUrl){ int i, j, c; char *zFile = 0; if( strncmp(zUrl, "http://", 7)==0 || strncmp(zUrl, "https://", 8)==0 ){ int iStart; char *zLogin; g.urlIsFile = 0; if( zUrl[4]=='s' ){ g.urlIsHttps = 1; g.urlProtocol = "https"; g.urlDfltPort = 443; iStart = 8; }else{ ................................................................................ if( j<i ){ g.urlPasswd = mprintf("%.*s", i-j-1, &zUrl[j+1]); dehttpize(g.urlPasswd); } for(j=i+1; (c=zUrl[j])!=0 && c!='/' && c!=':'; j++){} g.urlName = mprintf("%.*s", j-i-1, &zUrl[i+1]); i = j; zLogin = mprintf("%t@", g.urlUser); }else{ for(i=iStart; (c=zUrl[i])!=0 && c!='/' && c!=':'; i++){} g.urlName = mprintf("%.*s", i-iStart, &zUrl[iStart]); zLogin = mprintf(""); } for(j=0; g.urlName[j]; j++){ g.urlName[j] = tolower(g.urlName[j]); } if( c==':' ){ g.urlPort = 0; i++; while( (c = zUrl[i])!=0 && isdigit(c) ){ g.urlPort = g.urlPort*10 + c - '0'; ................................................................................ g.urlPort = g.urlDfltPort; g.urlHostname = g.urlName; } g.urlPath = mprintf(&zUrl[i]); dehttpize(g.urlName); dehttpize(g.urlPath); if( g.urlDfltPort==g.urlPort ){ g.urlCanonical = mprintf( "%s://%s%T%T", g.urlProtocol, zLogin, g.urlName, g.urlPath ); }else{ g.urlCanonical = mprintf( "%s://%s%T:%d%T", g.urlProtocol, zLogin, g.urlName, g.urlPort, g.urlPath ); } free(zLogin); }else if( strncmp(zUrl, "file:", 5)==0 ){ g.urlIsFile = 1; if( zUrl[5]=='/' && zUrl[6]=='/' ){ i = 7; }else{ i = 5; } ................................................................................ blob_appendf(&p->url, "%s%s=%T", zSep, zName1, zValue1); } if( zName2 && zValue2 ){ blob_appendf(&p->url, "%s%s=%T", zSep, zName2, zValue2); } return blob_str(&p->url); } /* ** Prompt the user for the password for g.urlUser. Store the result ** in g.urlPasswd. */ void url_prompt_for_password(void){ char *zPrompt = mprintf("password for %s: ", g.urlUser); Blob x; prompt_for_password(zPrompt, &x, 0); free(zPrompt); g.urlPasswd = mprintf("%b", &x); blob_reset(&x); } |
Changes to src/vfile.c.
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
...
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
|
** If VFILE.DELETED is null or if VFILE.RID is zero, then we can assume ** the file has changed without having the check the on-disk image. */ void vfile_check_signature(int vid, int notFileIsFatal){ int nErr = 0; Stmt q; Blob fileCksum, origCksum; int checkMtime = db_get_boolean("mtime-changes", 0); db_begin_transaction(); db_prepare(&q, "SELECT id, %Q || pathname," " vfile.mrid, deleted, chnged, uuid, mtime" " FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid" " WHERE vid=%d ", g.zLocalRoot, vid); while( db_step(&q)==SQLITE_ROW ){ ................................................................................ id = db_column_int(&q, 0); zName = db_column_text(&q, 1); rid = db_column_int(&q, 2); isDeleted = db_column_int(&q, 3); oldChnged = db_column_int(&q, 4); oldMtime = db_column_int64(&q, 6); if( !file_isfile(zName) && file_size(zName)>=0 ){ if( notFileIsFatal ){ fossil_warning("not a ordinary file: %s", zName); nErr++; } chnged = 1; }else if( oldChnged>=2 ){ chnged = oldChnged; }else if( isDeleted || rid==0 ){ chnged = 1; } if( chnged!=1 ){ currentMtime = file_mtime(zName); } if( chnged!=1 && (checkMtime==0 || currentMtime!=oldMtime) ){ db_ephemeral_blob(&q, 5, &origCksum); if( sha1sum_file(zName, &fileCksum) ){ blob_zero(&fileCksum); } if( blob_compare(&fileCksum, &origCksum) ){ |
|
|
|
>
|
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
...
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
|
** If VFILE.DELETED is null or if VFILE.RID is zero, then we can assume ** the file has changed without having the check the on-disk image. */ void vfile_check_signature(int vid, int notFileIsFatal){ int nErr = 0; Stmt q; Blob fileCksum, origCksum; int checkMtime = db_get_boolean("mtime-changes", 1); db_begin_transaction(); db_prepare(&q, "SELECT id, %Q || pathname," " vfile.mrid, deleted, chnged, uuid, mtime" " FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid" " WHERE vid=%d ", g.zLocalRoot, vid); while( db_step(&q)==SQLITE_ROW ){ ................................................................................ id = db_column_int(&q, 0); zName = db_column_text(&q, 1); rid = db_column_int(&q, 2); isDeleted = db_column_int(&q, 3); oldChnged = db_column_int(&q, 4); oldMtime = db_column_int64(&q, 6); if( !file_isfile(zName) && file_size(0)>=0 ){ if( notFileIsFatal ){ fossil_warning("not a ordinary file: %s", zName); nErr++; } chnged = 1; }else if( oldChnged>=2 ){ chnged = oldChnged; }else if( isDeleted || rid==0 ){ chnged = 1; } if( chnged!=1 ){ currentMtime = file_mtime(0); assert( currentMtime>0 ); } if( chnged!=1 && (checkMtime==0 || currentMtime!=oldMtime) ){ db_ephemeral_blob(&q, 5, &origCksum); if( sha1sum_file(zName, &fileCksum) ){ blob_zero(&fileCksum); } if( blob_compare(&fileCksum, &origCksum) ){ |
Changes to src/xfer.c.
340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 ... 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 ... 438 439 440 441 442 443 444 445 446 447 448 449 450 451 ... 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 .... 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 .... 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 .... 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 .... 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 |
pXfer->nGimmeSent++; } db_finalize(&q); } /* ** Compute an SHA1 hash on the tail of pMsg. Verify that it matches the ** the hash given in pHash. Return 1 on a successful match. Return 0 ** if there is a mismatch. */ static int check_tail_hash(Blob *pHash, Blob *pMsg){ Blob tail; Blob h2; int rc; blob_tail(pMsg, &tail); sha1sum_blob(&tail, &h2); rc = blob_compare(pHash, &h2); blob_reset(&h2); blob_reset(&tail); return rc==0; } /* ** Check the signature on an application/x-fossil payload received by ** the HTTP server. The signature is a line of the following form: ** ** login LOGIN NONCE SIGNATURE ................................................................................ ** If everything checks out, the USER.CAP column for the USER table ** is consulted to set privileges in the global g variable. ** ** If anything fails to check out, no changes are made to privileges. ** ** Signature generation on the client side is handled by the ** http_exchange() routine. */ void check_login(Blob *pLogin, Blob *pNonce, Blob *pSig){ Stmt q; int rc = -1; char *zLogin = blob_terminate(pLogin); defossilize(zLogin); db_prepare(&q, "SELECT pw, cap, uid FROM user" ................................................................................ } db_finalize(&q); if( rc==0 ){ /* If the login was successful. */ login_set_anon_nobody_capabilities(); } } /* ** Send the content of all files in the unsent table. ** ** This is really just an optimization. If you clear the ** unsent table, all the right files will still get transferred. ................................................................................ ** The client can send multiple logins. Permissions are cumulative. */ if( blob_eq(&xfer.aToken[0], "login") && xfer.nToken==4 ){ if( disableLogin ){ g.okRead = g.okWrite = 1; }else if( check_tail_hash(&xfer.aToken[2], xfer.pIn) ){ check_login(&xfer.aToken[1], &xfer.aToken[2], &xfer.aToken[3]); } }else /* reqconfig NAME ** ** Request a configuration value */ ................................................................................ blob_appendf(&send, "pull %s %s\n", zSCode, zPCode); nCardSent++; } if( pushFlag ){ blob_appendf(&send, "push %s %s\n", zSCode, zPCode); nCardSent++; } /* Process the reply that came back from the server */ while( blob_line(&recv, &xfer.line) ){ if( blob_buffer(&xfer.line)[0]=='#' ){ continue; } xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken)); ................................................................................ */ if( blob_eq(&xfer.aToken[0], "cookie") && xfer.nToken==2 ){ db_set("cookie", blob_str(&xfer.aToken[1]), 0); }else /* message MESSAGE ** ** Print a message. Similar to "error" but does not stop processing */ if( blob_eq(&xfer.aToken[0],"message") && xfer.nToken==2 ){ char *zMsg = blob_terminate(&xfer.aToken[1]); defossilize(zMsg); printf("\rServer says: %s\n", zMsg); }else /* error MESSAGE ** ** Report an error and abandon the sync session. ** ** Except, when cloning we will sometimes get an error on the ................................................................................ ** subsequent messages should be OK. Nevertheless, we need to ignore ** the error card on the first message of a clone. */ if( blob_eq(&xfer.aToken[0],"error") && xfer.nToken==2 ){ if( !cloneFlag || nCycle>0 ){ char *zMsg = blob_terminate(&xfer.aToken[1]); defossilize(zMsg); blob_appendf(&xfer.err, "server says: %s", zMsg); printf("Server Error: %s\n", zMsg); } }else /* Unknown message */ { if( blob_str(&xfer.aToken[0])[0]=='<' ){ fossil_fatal( ................................................................................ if( nCardRcvd>0 ){ printf(zValueFormat, "Received:", blob_size(&recv), nCardRcvd, xfer.nFileRcvd, xfer.nDeltaRcvd + xfer.nDanglingFile); } blob_reset(&recv); nCycle++; go = 0; /* If we received one or more files on the previous exchange but ** there are still phantoms, then go another round. */ nFileRecv = xfer.nFileRcvd + xfer.nDeltaRcvd + xfer.nDanglingFile; if( (nFileRecv>0 || newPhantom) && db_exists("SELECT 1 FROM phantom") ){ go = 1; |
| < | > > | > > | | > > > > > > > | > > > | > > > > > | > | < |
340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 ... 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 ... 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 ... 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 .... 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 .... 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 .... 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 .... 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 |
pXfer->nGimmeSent++; } db_finalize(&q); } /* ** Compute an SHA1 hash on the tail of pMsg. Verify that it matches the ** the hash given in pHash. Return non-zero for an error and 0 on success. */ static int check_tail_hash(Blob *pHash, Blob *pMsg){ Blob tail; Blob h2; int rc; blob_tail(pMsg, &tail); sha1sum_blob(&tail, &h2); rc = blob_compare(pHash, &h2); blob_reset(&h2); blob_reset(&tail); return rc; } /* ** Check the signature on an application/x-fossil payload received by ** the HTTP server. The signature is a line of the following form: ** ** login LOGIN NONCE SIGNATURE ................................................................................ ** If everything checks out, the USER.CAP column for the USER table ** is consulted to set privileges in the global g variable. ** ** If anything fails to check out, no changes are made to privileges. ** ** Signature generation on the client side is handled by the ** http_exchange() routine. ** ** Return non-zero for a login failure and zero for success. */ int check_login(Blob *pLogin, Blob *pNonce, Blob *pSig){ Stmt q; int rc = -1; char *zLogin = blob_terminate(pLogin); defossilize(zLogin); db_prepare(&q, "SELECT pw, cap, uid FROM user" ................................................................................ } db_finalize(&q); if( rc==0 ){ /* If the login was successful. */ login_set_anon_nobody_capabilities(); } return rc; } /* ** Send the content of all files in the unsent table. ** ** This is really just an optimization. If you clear the ** unsent table, all the right files will still get transferred. ................................................................................ ** The client can send multiple logins. Permissions are cumulative. */ if( blob_eq(&xfer.aToken[0], "login") && xfer.nToken==4 ){ if( disableLogin ){ g.okRead = g.okWrite = 1; }else{ if( check_tail_hash(&xfer.aToken[2], xfer.pIn) || check_login(&xfer.aToken[1], &xfer.aToken[2], &xfer.aToken[3]) ){ cgi_reset_content(); @ error login\sfailed nErr++; break; } } }else /* reqconfig NAME ** ** Request a configuration value */ ................................................................................ blob_appendf(&send, "pull %s %s\n", zSCode, zPCode); nCardSent++; } if( pushFlag ){ blob_appendf(&send, "push %s %s\n", zSCode, zPCode); nCardSent++; } go = 0; /* Process the reply that came back from the server */ while( blob_line(&recv, &xfer.line) ){ if( blob_buffer(&xfer.line)[0]=='#' ){ continue; } xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken)); ................................................................................ */ if( blob_eq(&xfer.aToken[0], "cookie") && xfer.nToken==2 ){ db_set("cookie", blob_str(&xfer.aToken[1]), 0); }else /* message MESSAGE ** ** Print a message. Similar to "error" but does not stop processing. ** ** If the "login failed" message is seen, clear the sync password prior ** to the next cycle. */ if( blob_eq(&xfer.aToken[0],"message") && xfer.nToken==2 ){ char *zMsg = blob_terminate(&xfer.aToken[1]); defossilize(zMsg); if( zMsg ) printf("\rServer says: %s\n", zMsg); }else /* error MESSAGE ** ** Report an error and abandon the sync session. ** ** Except, when cloning we will sometimes get an error on the ................................................................................ ** subsequent messages should be OK. Nevertheless, we need to ignore ** the error card on the first message of a clone. */ if( blob_eq(&xfer.aToken[0],"error") && xfer.nToken==2 ){ if( !cloneFlag || nCycle>0 ){ char *zMsg = blob_terminate(&xfer.aToken[1]); defossilize(zMsg); if( strcmp(zMsg, "login failed")==0 ){ if( !g.dontKeepUrl ) db_unset("last-sync-pw", 0); g.urlPasswd = 0; if( nCycle<2 ) go = 1; }else{ blob_appendf(&xfer.err, "\rserver says: %s", zMsg); } printf("\rServer Error: %s\n", zMsg); } }else /* Unknown message */ { if( blob_str(&xfer.aToken[0])[0]=='<' ){ fossil_fatal( ................................................................................ if( nCardRcvd>0 ){ printf(zValueFormat, "Received:", blob_size(&recv), nCardRcvd, xfer.nFileRcvd, xfer.nDeltaRcvd + xfer.nDanglingFile); } blob_reset(&recv); nCycle++; /* If we received one or more files on the previous exchange but ** there are still phantoms, then go another round. */ nFileRecv = xfer.nFileRcvd + xfer.nDeltaRcvd + xfer.nDanglingFile; if( (nFileRecv>0 || newPhantom) && db_exists("SELECT 1 FROM phantom") ){ go = 1; |
Changes to src/zip.c.
406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 |
void baseline_zip_page(void){
int rid;
char *zName, *zRid;
int nName, nRid;
Blob zip;
login_check_credentials();
if( !g.okZip && (!g.okRead || !g.okHistory) ){ login_needed(); return; }
zName = mprintf("%s", PD("name",""));
nName = strlen(zName);
zRid = mprintf("%s", PD("uuid",""));
nRid = strlen(zRid);
for(nName=strlen(zName)-1; nName>5; nName--){
if( zName[nName]=='.' ){
zName[nName] = 0;
|
| |
406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 |
void baseline_zip_page(void){ int rid; char *zName, *zRid; int nName, nRid; Blob zip; login_check_credentials(); if( !g.okZip ){ login_needed(); return; } zName = mprintf("%s", PD("name","")); nName = strlen(zName); zRid = mprintf("%s", PD("uuid","")); nRid = strlen(zRid); for(nName=strlen(zName)-1; nName>5; nName--){ if( zName[nName]=='.' ){ zName[nName] = 0; |