Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Add logic to do a configuration push. Add logic to synchronize the CONCEALED table containing hidden email addresses (assuming appropriate permissions). Additional testng is needed; this check-in is to transfer the work to another machine. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA1: |
6b0b57a924b66439b52629bda6f6306f |
| User & Date: | drh 2008-10-25 17:51:37.000 |
Context
|
2008-10-25
| ||
| 20:43 | Get "configuration push" working. Fix bugs in concealed-field processing of tickets. check-in: 31e94c0a04 user: drh tags: trunk | |
| 17:51 | Add logic to do a configuration push. Add logic to synchronize the CONCEALED table containing hidden email addresses (assuming appropriate permissions). Additional testng is needed; this check-in is to transfer the work to another machine. check-in: 6b0b57a924 user: drh tags: trunk | |
| 17:19 | Update conditions when to look for proxy URL in environment. check-in: d65d619d94 user: altufaltu tags: trunk | |
Changes
Changes to src/clone.c.
| ︙ | ︙ | |||
70 71 72 73 74 75 76 |
db_set("last-sync-url", g.argv[2], 0);
db_multi_exec(
"REPLACE INTO config(name,value)"
" VALUES('server-code', lower(hex(randomblob(20))));"
);
url_enable_proxy(0);
g.xlinkClusterOnly = 1;
| | | 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
db_set("last-sync-url", g.argv[2], 0);
db_multi_exec(
"REPLACE INTO config(name,value)"
" VALUES('server-code', lower(hex(randomblob(20))));"
);
url_enable_proxy(0);
g.xlinkClusterOnly = 1;
client_sync(0,0,1,CONFIGSET_ALL,0);
g.xlinkClusterOnly = 0;
verify_cancel();
db_end_transaction(0);
db_close();
db_open_repository(g.argv[3]);
}
db_begin_transaction();
|
| ︙ | ︙ |
Changes to src/configure.c.
| ︙ | ︙ | |||
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
** groupings:
*/
#define CONFIGSET_SKIN 0x000001 /* WWW interface appearance */
#define CONFIGSET_TKT 0x000002 /* Ticket configuration */
#define CONFIGSET_PROJ 0x000004 /* Project name */
#define CONFIGSET_SHUN 0x000008 /* Shun settings */
#define CONFIGSET_USER 0x000010 /* The USER table */
#define CONFIGSET_ALL 0xffffff /* Everything */
#endif /* INTERFACE */
/*
** Names of the configuration sets
*/
static struct {
const char *zName; /* Name of the configuration set */
int groupMask; /* Mask for that configuration set */
const char *zHelp; /* What it does */
} aGroupName[] = {
| > | < | > | > | | | 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 |
** groupings:
*/
#define CONFIGSET_SKIN 0x000001 /* WWW interface appearance */
#define CONFIGSET_TKT 0x000002 /* Ticket configuration */
#define CONFIGSET_PROJ 0x000004 /* Project name */
#define CONFIGSET_SHUN 0x000008 /* Shun settings */
#define CONFIGSET_USER 0x000010 /* The USER table */
#define CONFIGSET_ADDR 0x000020 /* The CONCEALED table */
#define CONFIGSET_ALL 0xffffff /* Everything */
#endif /* INTERFACE */
/*
** Names of the configuration sets
*/
static struct {
const char *zName; /* Name of the configuration set */
int groupMask; /* Mask for that configuration set */
const char *zHelp; /* What it does */
} aGroupName[] = {
{ "email", CONFIGSET_ADDR, "Concealed email addresses in tickets" },
{ "project", CONFIGSET_PROJ, "Project name and description" },
{ "skin", CONFIGSET_SKIN, "Web interface apparance settings" },
{ "shun", CONFIGSET_SHUN, "List of shunned artifacts" },
{ "ticket", CONFIGSET_TKT, "Ticket setup", },
{ "user", CONFIGSET_USER, "Users and privilege settings" },
{ "all", CONFIGSET_ALL, "All of the above" },
};
/*
** The following is a list of settings that we are willing to
** transfer.
**
|
| ︙ | ︙ | |||
88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
{ "ticket-editpage", CONFIGSET_TKT },
{ "ticket-report-template", CONFIGSET_TKT },
{ "ticket-key-template", CONFIGSET_TKT },
{ "ticket-title-expr", CONFIGSET_TKT },
{ "ticket-closed-expr", CONFIGSET_TKT },
{ "@reportfmt", CONFIGSET_TKT },
{ "@user", CONFIGSET_USER },
{ "@shun", CONFIGSET_SHUN },
};
static int iConfig = 0;
/*
** Return name of first configuration property matching the given mask.
*/
| > | 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
{ "ticket-editpage", CONFIGSET_TKT },
{ "ticket-report-template", CONFIGSET_TKT },
{ "ticket-key-template", CONFIGSET_TKT },
{ "ticket-title-expr", CONFIGSET_TKT },
{ "ticket-closed-expr", CONFIGSET_TKT },
{ "@reportfmt", CONFIGSET_TKT },
{ "@user", CONFIGSET_USER },
{ "@concealed", CONFIGSET_ADDR },
{ "@shun", CONFIGSET_SHUN },
};
static int iConfig = 0;
/*
** Return name of first configuration property matching the given mask.
*/
|
| ︙ | ︙ | |||
122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
int i;
for(i=0; i<count(aConfig); i++){
if( strcmp(zName, aConfig[i].zName)==0 ){
int m = aConfig[i].groupMask;
if( !g.okAdmin ){
m &= ~CONFIGSET_USER;
}
return m;
}
}
return 0;
}
/*
| > > > | 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
int i;
for(i=0; i<count(aConfig); i++){
if( strcmp(zName, aConfig[i].zName)==0 ){
int m = aConfig[i].groupMask;
if( !g.okAdmin ){
m &= ~CONFIGSET_USER;
}
if( !g.okRdAddr ){
m &= ~CONFIGSET_ADDR;
}
return m;
}
}
return 0;
}
/*
|
| ︙ | ︙ | |||
147 148 149 150 151 152 153 |
db_column_text(&q, 0)
);
}
db_finalize(&q);
}else if( strcmp(zName, "@reportfmt")==0 ){
db_prepare(&q, "SELECT title, cols, sqlcode FROM reportfmt");
while( db_step(&q)==SQLITE_ROW ){
| | | > > > > > > > > > > | 153 154 155 156 157 158 159 160 161 162 163 164 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 193 194 |
db_column_text(&q, 0)
);
}
db_finalize(&q);
}else if( strcmp(zName, "@reportfmt")==0 ){
db_prepare(&q, "SELECT title, cols, sqlcode FROM reportfmt");
while( db_step(&q)==SQLITE_ROW ){
blob_appendf(pOut, "INSERT INTO _xfer_reportfmt(title,cols,sqlcode)"
" VALUES(%Q,%Q,%Q);\n",
db_column_text(&q, 0),
db_column_text(&q, 1),
db_column_text(&q, 2)
);
}
db_finalize(&q);
}else if( strcmp(zName, "@user")==0 ){
db_prepare(&q, "SELECT login, cap, info, quote(photo) FROM user");
while( db_step(&q)==SQLITE_ROW ){
blob_appendf(pOut, "INSERT INTO _xfer_user(login,cap,info,photo)"
" VALUES(%Q,%Q,%Q,%s);\n",
db_column_text(&q, 0),
db_column_text(&q, 1),
db_column_text(&q, 2),
db_column_text(&q, 3)
);
}
db_finalize(&q);
}else if( strcmp(zName, "@concealed")==0 ){
db_prepare(&q, "SELECT hash, content FROM concealed");
while( db_step(&q)==SQLITE_ROW ){
blob_appendf(pOut, "INSERT OR IGNORE INTO concealed(hash,content)"
" VALUES(%Q,%Q);\n",
db_column_text(&q, 0),
db_column_text(&q, 1)
);
}
db_finalize(&q);
}
}
/*
** Two SQL functions:
|
| ︙ | ︙ | |||
351 352 353 354 355 356 357 | /* ** COMMAND: configuration ** ** Usage: %fossil configure METHOD ... ** | | | 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 | /* ** COMMAND: configuration ** ** Usage: %fossil configure METHOD ... ** ** Where METHOD is one of: export import merge pull push reset. All methods ** accept the -R or --repository option to specific a repository. ** ** %fossil configuration export AREA FILENAME ** ** Write to FILENAME exported configuraton information for AREA. ** AREA can be one of: all ticket skin project ** |
| ︙ | ︙ | |||
374 375 376 377 378 379 380 | ** the current configuration. Existing values take priority over ** values read from FILENAME. ** ** %fossil configuration pull AREA ?URL? ** ** Pull and install the configuration from a different server ** identified by URL. If no URL is specified, then the default | | > > > > > > | 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 | ** the current configuration. Existing values take priority over ** values read from FILENAME. ** ** %fossil configuration pull AREA ?URL? ** ** Pull and install the configuration from a different server ** identified by URL. If no URL is specified, then the default ** server is used. ** ** %fossil configuration push AREA ?URL? ** ** Push the local configuration into the remote server identified ** by URL. Admin privilege is required on the remote server for ** this to work. ** ** %fossil configuration reset AREA ** ** Restore the configuration to the default. AREA as above. ** ** WARNING: Do not import, merge, or pull configurations from an untrusted ** source. The inbound configuration is not checked for safety and can |
| ︙ | ︙ | |||
412 413 414 415 416 417 418 |
blob_read_from_file(&in, g.argv[3]);
db_begin_transaction();
configure_prepare_to_receive(zMethod[0]=='i');
db_multi_exec("%s", blob_str(&in));
configure_finalize_receive();
db_end_transaction(0);
}else
| | > | > > > > > > > | > | 434 435 436 437 438 439 440 441 442 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 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 |
blob_read_from_file(&in, g.argv[3]);
db_begin_transaction();
configure_prepare_to_receive(zMethod[0]=='i');
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);
if( g.urlIsFile ){
fossil_fatal("network sync only");
}
user_select();
if( strncmp(zMethod, "push", n)==0 ){
client_sync(0,0,0,0,mask);
}else{
client_sync(0,0,0,mask,0);
}
}else
if( strncmp(zMethod, "reset", n)==0 ){
int mask, i;
char *zBackup;
if( g.argc!=4 ) usage("reset AREA");
mask = find_area(g.argv[3]);
zBackup = db_text(0,
"SELECT strftime('config-backup-%%Y%%m%%d%%H%%M%%f','now')");
db_begin_transaction();
export_config(mask, g.argv[3], zBackup);
for(i=0; i<count(aConfig); i++){
const char *zName = aConfig[i].zName;
if( (aConfig[i].groupMask & mask)==0 ) continue;
if( zName[0]!='@' ){
db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
}else if( strcmp(zName,"@user")==0 ){
db_multi_exec("DELETE FROM user");
db_create_default_users();
}else if( strcmp(zName,"@concealed")==0 ){
db_multi_exec("DELETE FROM concealed");
}else if( strcmp(zName,"@shun")==0 ){
db_multi_exec("DELETE FROM shun");
}else if( strcmp(zName,"@reportfmt")==0 ){
db_multi_exec("DELETE FROM reportfmt");
}
}
db_end_transaction(0);
printf("Configuration reset to factory defaults.\n");
printf("To recover, use: %s %s import %s\n",
g.argv[0], g.argv[1], zBackup);
}else
{
fossil_fatal("METHOD should be one of:"
" export import merge pull push reset");
}
}
|
Changes to src/db.c.
| ︙ | ︙ | |||
909 910 911 912 913 914 915 916 917 918 919 |
/*
** Convert the input string into an SHA1. Make a notation in the
** CONCEALED table so that the hash can be undo using the db_reveal()
** function at some later time.
**
** The value returned is stored in static space and will be overwritten
** on subsequent calls.
*/
char *db_conceal(const char *zContent, int n){
static char zHash[42];
Blob out;
| > > > > > > > > > > > > | | | | | | | | > | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 |
/*
** Convert the input string into an SHA1. Make a notation in the
** CONCEALED table so that the hash can be undo using the db_reveal()
** function at some later time.
**
** The value returned is stored in static space and will be overwritten
** on subsequent calls.
**
** If zContent is already a well-formed SHA1 hash, then return a copy
** of that hash, not a hash of the hash.
**
** The CONCEALED table is meant to obscure email addresses. Every valid
** email address will contain a "@" character and "@" is not valid within
** an SHA1 hash so there is no chance that a valid email address will go
** unconcealed.
*/
char *db_conceal(const char *zContent, int n){
static char zHash[42];
Blob out;
if( n==40 && validate16(zContent, n) ){
memcpy(zHash, zContent, n);
zHash[n] = 0;
}else{
sha1sum_step_text(zContent, n);
sha1sum_finish(&out);
strcpy(zHash, blob_str(&out));
blob_reset(&out);
db_multi_exec(
"INSERT OR IGNORE INTO concealed VALUES(%Q,%#Q)",
zHash, n, zContent
);
}
return zHash;
}
/*
** Attempt to look up the input in the CONCEALED table. If found,
** and if the okRdAddr permission is enabled then return the
** original value for which the input is a hash. If okRdAddr is
** false or if the lookup fails, return the original string content.
**
** In either case, the string returned is stored in space obtained
** from malloc and should be freed by the calling function.
*/
char *db_reveal(const char *zKey){
char *zOut;
if( g.okRdAddr ){
zOut = db_text(0, "SELECT content FROM concealed WHERE hash=%Q", zKey);
}else{
zOut = 0;
}
if( zOut==0 ){
zOut = mprintf("%s", zKey);
}
return zOut;
}
/*
** This function registers auxiliary functions when the SQLite
** database connection is first established.
*/
LOCAL void db_connection_init(void){
static int once = 1;
if( once ){
sqlite3_create_function(g.db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0);
sqlite3_create_function(
g.db, "file_is_selected", 1, SQLITE_UTF8, 0, file_is_selected,0,0
);
if( g.fSqlTrace ){
sqlite3_trace(g.db, db_sql_trace, 0);
}
once = 0;
}
}
|
| ︙ | ︙ |
Changes to src/sync.c.
| ︙ | ︙ | |||
59 60 61 62 63 64 65 |
}
if( g.urlPort!=80 ){
printf("Autosync: http://%s:%d%s\n", g.urlName, g.urlPort, g.urlPath);
}else{
printf("Autosync: http://%s%s\n", g.urlName, g.urlPath);
}
url_enable_proxy("via proxy: ");
| | | 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
}
if( g.urlPort!=80 ){
printf("Autosync: http://%s:%d%s\n", g.urlName, g.urlPort, g.urlPath);
}else{
printf("Autosync: http://%s%s\n", 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.
|
| ︙ | ︙ | |||
122 123 124 125 126 127 128 |
** The "USER" substring specifies the login user. You will be
** prompted for the password on the command-line. The PORT
** specifies the TCP port of the server. The default port is
** 80.
*/
void pull_cmd(void){
process_sync_args();
| | | | | 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
** The "USER" substring specifies the login user. You will be
** prompted for the password on the command-line. The PORT
** specifies the TCP port of the server. The default port is
** 80.
*/
void pull_cmd(void){
process_sync_args();
client_sync(0,1,0,0,0);
}
/*
** COMMAND: push
**
** Usage: %fossil push ?URL? ?-R|--repository REPOSITORY?
**
** Push changes in the local repository over into a remote repository.
** See the "pull" command for additional information.
*/
void push_cmd(void){
process_sync_args();
client_sync(1,0,0,0,0);
}
/*
** COMMAND: sync
**
** Usage: %fossil sync ?URL? ?-R|--repository REPOSITORY?
**
** Synchronize the local repository with a remote repository. This is
** the equivalent of running both "push" and "pull" at the same time.
** See the "pull" command for additional information.
*/
void sync_cmd(void){
process_sync_args();
client_sync(1,1,0,0,0);
}
|
Changes to src/xfer.c.
| ︙ | ︙ | |||
477 478 479 480 481 482 483 484 485 486 487 488 489 490 |
" WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)"
);
while( db_step(&q)==SQLITE_ROW ){
blob_appendf(pXfer->pOut, "igot %s\n", db_column_text(&q, 0));
}
db_finalize(&q);
}
/*
** If this variable is set, disable login checks. Used for debugging
** only.
*/
static int disableLogin = 0;
| > > > > > > > > > > > > > > > > > > > > > > | 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 |
" WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)"
);
while( db_step(&q)==SQLITE_ROW ){
blob_appendf(pXfer->pOut, "igot %s\n", db_column_text(&q, 0));
}
db_finalize(&q);
}
/*
** Send a single config card for configuration item zName
*/
static void send_config_card(Xfer *pXfer, const char *zName){
if( zName[0]!='@' ){
char *zValue = db_get(zName, 0);
if( zValue ){
blob_appendf(pXfer->pOut, "config %s %d\n%s\n",
zName, strlen(zValue), zValue);
free(zValue);
}
}else{
Blob content;
blob_zero(&content);
configure_render_special_name(zName, &content);
blob_appendf(pXfer->pOut, "config %s %d\n%s\n", zName,
blob_size(&content), blob_str(&content));
blob_reset(&content);
}
}
/*
** If this variable is set, disable login checks. Used for debugging
** only.
*/
static int disableLogin = 0;
|
| ︙ | ︙ | |||
505 506 507 508 509 510 511 512 513 514 515 516 517 518 | int isPull = 0; int isPush = 0; int nErr = 0; Xfer xfer; int deltaFlag = 0; int isClone = 0; int nGimme = 0; memset(&xfer, 0, sizeof(xfer)); blobarray_zero(xfer.aToken, count(xfer.aToken)); cgi_set_content_type(g.zContentType); blob_zero(&xfer.err); xfer.pIn = &g.cgiIn; xfer.pOut = cgi_output_blob(); | > > | 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 | int isPull = 0; int isPush = 0; int nErr = 0; Xfer xfer; int deltaFlag = 0; int isClone = 0; int nGimme = 0; int size; int recvConfig = 0; memset(&xfer, 0, sizeof(xfer)); blobarray_zero(xfer.aToken, count(xfer.aToken)); cgi_set_content_type(g.zContentType); blob_zero(&xfer.err); xfer.pIn = &g.cgiIn; xfer.pOut = cgi_output_blob(); |
| ︙ | ︙ | |||
676 677 678 679 680 681 682 |
*/
if( blob_eq(&xfer.aToken[0], "reqconfig")
&& xfer.nToken==2
){
if( g.okRead ){
char *zName = blob_str(&xfer.aToken[1]);
if( configure_is_exportable(zName) ){
| | < < < < < | > | > > > > > > > > > | | | < > | > > | | > > > > > > > > > > > > > > > > > | > > | 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 |
*/
if( blob_eq(&xfer.aToken[0], "reqconfig")
&& xfer.nToken==2
){
if( g.okRead ){
char *zName = blob_str(&xfer.aToken[1]);
if( configure_is_exportable(zName) ){
send_config_card(&xfer, zName);
}
}
}else
/* config NAME SIZE \n CONTENT
**
** Receive a configuration value from the client. This is only
** permitted for high-privilege users.
*/
if( blob_eq(&xfer.aToken[0],"config") && xfer.nToken==3
&& blob_is_int(&xfer.aToken[2], &size) ){
const char *zName = blob_str(&xfer.aToken[1]);
Blob content;
blob_zero(&content);
blob_extract(xfer.pIn, size, &content);
if( !g.okAdmin ){
cgi_reset_content();
@ error not\sauthorized\sto\spush\sconfiguration\data
nErr++;
break;
}
if( zName[0]!='@' ){
if( !recvConfig ){
configure_prepare_to_receive(0);
recvConfig = 1;
}
db_multi_exec(
"REPLACE INTO config(name,value) VALUES(%Q,%Q)",
zName, blob_str(&content)
);
}else{
/* Notice that we are evaluating arbitrary SQL received from the
** client. But this can only happen if the client has authenticated
** as an administrator, so presumably we trust the client at this
** point.
*/
db_multi_exec("%s", blob_str(&content));
}
blob_reset(&content);
blob_seek(xfer.pIn, 1, BLOB_SEEK_CUR);
}else
/* cookie TEXT
**
** A cookie contains a arbitrary-length argument that is server-defined.
** The argument must be encoded so as not to contain any whitespace.
** The server can optionally send a cookie to the client. The client
** might then return the same cookie back to the server on its next
** communication. The cookie might record information that helps
|
| ︙ | ︙ | |||
740 741 742 743 744 745 746 747 748 749 750 751 752 753 |
** and expeditiously.
*/
send_all(&xfer);
}else if( isPull ){
create_cluster();
send_unclustered(&xfer);
}
db_end_transaction(0);
}
/*
** COMMAND: test-xfer
**
** This command is used for debugging the server. There is a single
| > > > | 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 |
** and expeditiously.
*/
send_all(&xfer);
}else if( isPull ){
create_cluster();
send_unclustered(&xfer);
}
if( recvConfig ){
configure_finalize_receive();
}
db_end_transaction(0);
}
/*
** COMMAND: test-xfer
**
** This command is used for debugging the server. There is a single
|
| ︙ | ︙ | |||
791 792 793 794 795 796 797 | ** Sync to the host identified in g.urlName and g.urlPath. This ** routine is called by the client. ** ** Records are pushed to the server if pushFlag is true. Records ** are pulled if pullFlag is true. A full sync occurs if both are ** true. */ | | > > > > > > | | | | 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 |
** Sync to the host identified in g.urlName and g.urlPath. This
** routine is called by the client.
**
** Records are pushed to the server if pushFlag is true. Records
** are pulled if pullFlag is true. A full sync occurs if both are
** true.
*/
void client_sync(
int pushFlag, /* True to do a push (or a sync) */
int pullFlag, /* True to do a pull (or a sync) */
int cloneFlag, /* True if this is a clone */
int configRcvMask, /* Receive these configuration items */
int configSendMask /* Send these configuration items */
){
int go = 1; /* Loop until zero */
const char *zSCode = db_get("server-code", "x");
const char *zPCode = db_get("project-code", 0);
int nCard = 0; /* Number of cards sent or received */
int nCycle = 0; /* Number of round trips to the server */
int size; /* Size of a config value */
int nFileSend = 0;
int origConfigRcvMask; /* Original value of configRcvMask */
int nFileRecv; /* Number of files received */
int mxPhantomReq = 200; /* Max number of phantoms to request per comm */
const char *zCookie; /* Server cookie */
Blob send; /* Text we are sending to the server */
Blob recv; /* Reply we got back from the server */
Xfer xfer; /* Transfer data */
memset(&xfer, 0, sizeof(xfer));
xfer.pIn = &recv;
xfer.pOut = &send;
xfer.mxSend = db_get_int("max-upload", 250000);
assert( pushFlag | pullFlag | cloneFlag | configRcvMask | configSendMask );
assert( !g.urlIsFile ); /* This only works for networking */
db_begin_transaction();
db_record_repository_filename(0);
db_multi_exec(
"CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);"
);
blobarray_zero(xfer.aToken, count(xfer.aToken));
blob_zero(&send);
blob_zero(&recv);
blob_zero(&xfer.err);
blob_zero(&xfer.line);
origConfigRcvMask = configRcvMask;
/*
** Always begin with a clone, pull, or push message
*/
if( cloneFlag ){
blob_appendf(&send, "clone\n");
pushFlag = 0;
|
| ︙ | ︙ | |||
870 871 872 873 874 875 876 |
}
if( pushFlag ){
send_unsent(&xfer);
nCard += send_unclustered(&xfer);
}
/* Send configuration parameter requests */
| | | | | | > > > > > > > > > > > > | 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 |
}
if( pushFlag ){
send_unsent(&xfer);
nCard += send_unclustered(&xfer);
}
/* Send configuration parameter requests */
if( configRcvMask ){
const char *zName;
zName = configure_first_name(configRcvMask);
while( zName ){
blob_appendf(&send, "reqconfig %s\n", zName);
zName = configure_next_name(configRcvMask);
nCard++;
}
if( configRcvMask & (CONFIGSET_USER|CONFIGSET_TKT) ){
configure_prepare_to_receive(0);
}
configRcvMask = 0;
}
/* Send configuration parameters being pushed */
if( configSendMask ){
const char *zName;
zName = configure_first_name(configSendMask);
while( zName ){
send_config_card(&xfer, zName);
zName = configure_next_name(configSendMask);
nCard++;
}
configSendMask = 0;
}
/* Append randomness to the end of the message */
#if 0 /* Enable this after all servers have upgraded */
zRandomness = db_text(0, "SELECT hex(randomblob(20))");
blob_appendf(&send, "# %s\n", zRandomness);
free(zRandomness);
|
| ︙ | ︙ | |||
1004 1005 1006 1007 1008 1009 1010 |
*/
if( blob_eq(&xfer.aToken[0],"config") && xfer.nToken==3
&& blob_is_int(&xfer.aToken[2], &size) ){
const char *zName = blob_str(&xfer.aToken[1]);
Blob content;
blob_zero(&content);
blob_extract(xfer.pIn, size, &content);
| | > > > > > | 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 |
*/
if( blob_eq(&xfer.aToken[0],"config") && xfer.nToken==3
&& blob_is_int(&xfer.aToken[2], &size) ){
const char *zName = blob_str(&xfer.aToken[1]);
Blob content;
blob_zero(&content);
blob_extract(xfer.pIn, size, &content);
if( configure_is_exportable(zName) & origConfigRcvMask ){
if( zName[0]!='@' ){
db_multi_exec(
"REPLACE INTO config(name,value) VALUES(%Q,%Q)",
zName, blob_str(&content)
);
}else{
/* Notice that we are evaluating arbitrary SQL received from the
** server. But this can only happen if we have specifically
** requested configuration information from the server, so
** presumably the operator trusts the server.
*/
db_multi_exec("%s", blob_str(&content));
}
}
nCard++;
blob_reset(&content);
blob_seek(xfer.pIn, 1, BLOB_SEEK_CUR);
}else
|
| ︙ | ︙ | |||
1064 1065 1066 1067 1068 1069 1070 |
if( blob_size(&xfer.err) ){
fossil_fatal("%b", &xfer.err);
}
blobarray_reset(xfer.aToken, xfer.nToken);
blob_reset(&xfer.line);
}
| | | | 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 |
if( blob_size(&xfer.err) ){
fossil_fatal("%b", &xfer.err);
}
blobarray_reset(xfer.aToken, xfer.nToken);
blob_reset(&xfer.line);
}
if( origConfigRcvMask & (CONFIGSET_TKT|CONFIGSET_USER) ){
configure_finalize_receive();
}
origConfigRcvMask = 0;
printf(zValueFormat, "Received:",
blob_size(&recv), nCard,
xfer.nFileRcvd, xfer.nDeltaRcvd + xfer.nDanglingFile);
blob_reset(&recv);
nCycle++;
go = 0;
|
| ︙ | ︙ |