Fossil SCM
Private sync now appears to be working in all modes. More testing and fail-safe mechanisms are desired before merging with the trunk.
Commit
1aae2b582e9afc7d31f89247adc44b3c0cddaf3e
Parent
6da5d4ad5f478c9…
1 file changed
+31
-7
+31
-7
| --- src/xfer.c | ||
| +++ src/xfer.c | ||
| @@ -155,11 +155,11 @@ | ||
| 155 | 155 | if( content_get(srcid, &src)==0 ){ |
| 156 | 156 | rid = content_put_ex(&content, blob_str(&pXfer->aToken[1]), srcid, |
| 157 | 157 | 0, isPriv); |
| 158 | 158 | pXfer->nDanglingFile++; |
| 159 | 159 | db_multi_exec("DELETE FROM phantom WHERE rid=%d", rid); |
| 160 | - content_make_public(rid); | |
| 160 | + if( !isPriv ) content_make_public(rid); | |
| 161 | 161 | return; |
| 162 | 162 | } |
| 163 | 163 | pXfer->nDeltaRcvd++; |
| 164 | 164 | blob_delta_apply(&src, &content, &next); |
| 165 | 165 | blob_reset(&src); |
| @@ -301,11 +301,10 @@ | ||
| 301 | 301 | size = 0; |
| 302 | 302 | }else{ |
| 303 | 303 | if( isPrivate ) blob_append(pXfer->pOut, "private\n", -1); |
| 304 | 304 | blob_appendf(pXfer->pOut, "file %b %s %d\n", pUuid, zUuid, size); |
| 305 | 305 | blob_append(pXfer->pOut, blob_buffer(&delta), size); |
| 306 | - /* blob_appendf(pXfer->pOut, "\n", 1); */ | |
| 307 | 306 | } |
| 308 | 307 | blob_reset(&delta); |
| 309 | 308 | free(zUuid); |
| 310 | 309 | blob_reset(&src); |
| 311 | 310 | } |
| @@ -424,10 +423,13 @@ | ||
| 424 | 423 | pXfer->nDeltaSent++; |
| 425 | 424 | } |
| 426 | 425 | } |
| 427 | 426 | remote_has(rid); |
| 428 | 427 | blob_reset(&uuid); |
| 428 | + if( blob_buffer(pXfer->pOut)[blob_size(pXfer->pOut)-1]!='\n' ){ | |
| 429 | + blob_appendf(pXfer->pOut, "\n", 1); | |
| 430 | + } | |
| 429 | 431 | } |
| 430 | 432 | |
| 431 | 433 | /* |
| 432 | 434 | ** Send the file identified by rid as a compressed artifact. Basically, |
| 433 | 435 | ** send the content exactly as it appears in the BLOB table using |
| @@ -470,11 +472,13 @@ | ||
| 470 | 472 | }else{ |
| 471 | 473 | pXfer->nFileSent++; |
| 472 | 474 | } |
| 473 | 475 | blob_appendf(pXfer->pOut, "%d %d\n", szU, szC); |
| 474 | 476 | blob_append(pXfer->pOut, zContent, szC); |
| 475 | - blob_append(pXfer->pOut, "\n", 1); | |
| 477 | + if( blob_buffer(pXfer->pOut)[blob_size(pXfer->pOut)-1]!='\n' ){ | |
| 478 | + blob_appendf(pXfer->pOut, "\n", 1); | |
| 479 | + } | |
| 476 | 480 | } |
| 477 | 481 | db_reset(&q1); |
| 478 | 482 | } |
| 479 | 483 | |
| 480 | 484 | /* |
| @@ -755,10 +759,19 @@ | ||
| 755 | 759 | blob_size(&content), blob_str(&content)); |
| 756 | 760 | blob_reset(&content); |
| 757 | 761 | } |
| 758 | 762 | } |
| 759 | 763 | |
| 764 | + | |
| 765 | +/* | |
| 766 | +** Called when there is an attempt to transfer private content to and | |
| 767 | +** from a server without authorization. | |
| 768 | +*/ | |
| 769 | +static void server_private_xfer_not_authorized(void){ | |
| 770 | + @ error not\sauthorized\sto\ssync\sprivate\scontent | |
| 771 | +} | |
| 772 | + | |
| 760 | 773 | |
| 761 | 774 | /* |
| 762 | 775 | ** If this variable is set, disable login checks. Used for debugging |
| 763 | 776 | ** only. |
| 764 | 777 | */ |
| @@ -879,14 +892,16 @@ | ||
| 879 | 892 | if( xfer.nToken>=2 |
| 880 | 893 | && blob_eq(&xfer.aToken[0], "igot") |
| 881 | 894 | && blob_is_uuid(&xfer.aToken[1]) |
| 882 | 895 | ){ |
| 883 | 896 | if( isPush ){ |
| 884 | - if( xfer.nToken==2 || blob_eq(&xfer.aToken[1],"1")==0 ){ | |
| 897 | + if( xfer.nToken==2 || blob_eq(&xfer.aToken[2],"1")==0 ){ | |
| 885 | 898 | rid_from_uuid(&xfer.aToken[1], 1, 0); |
| 886 | 899 | }else if( g.okPrivate ){ |
| 887 | 900 | rid_from_uuid(&xfer.aToken[1], 1, 1); |
| 901 | + }else{ | |
| 902 | + server_private_xfer_not_authorized(); | |
| 888 | 903 | } |
| 889 | 904 | } |
| 890 | 905 | }else |
| 891 | 906 | |
| 892 | 907 | |
| @@ -1092,11 +1107,15 @@ | ||
| 1092 | 1107 | ** |
| 1093 | 1108 | ** This card indicates that the next "file" or "cfile" will contain |
| 1094 | 1109 | ** private content. |
| 1095 | 1110 | */ |
| 1096 | 1111 | if( blob_eq(&xfer.aToken[0], "private") ){ |
| 1097 | - xfer.nextIsPrivate = 1; | |
| 1112 | + if( !g.okPrivate ){ | |
| 1113 | + server_private_xfer_not_authorized(); | |
| 1114 | + }else{ | |
| 1115 | + xfer.nextIsPrivate = 1; | |
| 1116 | + } | |
| 1098 | 1117 | }else |
| 1099 | 1118 | |
| 1100 | 1119 | |
| 1101 | 1120 | /* pragma NAME VALUE... |
| 1102 | 1121 | ** |
| @@ -1110,11 +1129,15 @@ | ||
| 1110 | 1129 | ** If the user has the "x" privilege (which must be set explicitly - |
| 1111 | 1130 | ** it is not automatic with "a" or "s") then this pragma causes |
| 1112 | 1131 | ** private information to be pulled in addition to public records. |
| 1113 | 1132 | */ |
| 1114 | 1133 | if( blob_eq(&xfer.aToken[1], "send-private") ){ |
| 1115 | - if( g.okPrivate ) xfer.syncPrivate = 1; | |
| 1134 | + if( !g.okPrivate ){ | |
| 1135 | + server_private_xfer_not_authorized(); | |
| 1136 | + }else{ | |
| 1137 | + xfer.syncPrivate = 1; | |
| 1138 | + } | |
| 1116 | 1139 | } |
| 1117 | 1140 | }else |
| 1118 | 1141 | |
| 1119 | 1142 | /* Unknown message |
| 1120 | 1143 | */ |
| @@ -1308,10 +1331,11 @@ | ||
| 1308 | 1331 | request_phantoms(&xfer, mxPhantomReq); |
| 1309 | 1332 | } |
| 1310 | 1333 | if( pushFlag ){ |
| 1311 | 1334 | send_unsent(&xfer); |
| 1312 | 1335 | nCardSent += send_unclustered(&xfer); |
| 1336 | + if( privateFlag ) send_private(&xfer); | |
| 1313 | 1337 | } |
| 1314 | 1338 | |
| 1315 | 1339 | /* Send configuration parameter requests. On a clone, delay sending |
| 1316 | 1340 | ** this until the second cycle since the login card might fail on |
| 1317 | 1341 | ** the first cycle. |
| @@ -1470,11 +1494,11 @@ | ||
| 1470 | 1494 | if( xfer.nToken>=2 |
| 1471 | 1495 | && blob_eq(&xfer.aToken[0], "igot") |
| 1472 | 1496 | && blob_is_uuid(&xfer.aToken[1]) |
| 1473 | 1497 | ){ |
| 1474 | 1498 | int rid; |
| 1475 | - int isPriv = xfer.nToken>=3 && blob_eq(&xfer.aToken[1],"1"); | |
| 1499 | + int isPriv = xfer.nToken>=3 && blob_eq(&xfer.aToken[2],"1"); | |
| 1476 | 1500 | rid = rid_from_uuid(&xfer.aToken[1], 0, 0); |
| 1477 | 1501 | if( rid>0 ){ |
| 1478 | 1502 | if( !isPriv ) content_make_public(rid); |
| 1479 | 1503 | }else if( !g.okPrivate ){ |
| 1480 | 1504 | /* ignore private files */ |
| 1481 | 1505 |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -155,11 +155,11 @@ | |
| 155 | if( content_get(srcid, &src)==0 ){ |
| 156 | rid = content_put_ex(&content, blob_str(&pXfer->aToken[1]), srcid, |
| 157 | 0, isPriv); |
| 158 | pXfer->nDanglingFile++; |
| 159 | db_multi_exec("DELETE FROM phantom WHERE rid=%d", rid); |
| 160 | content_make_public(rid); |
| 161 | return; |
| 162 | } |
| 163 | pXfer->nDeltaRcvd++; |
| 164 | blob_delta_apply(&src, &content, &next); |
| 165 | blob_reset(&src); |
| @@ -301,11 +301,10 @@ | |
| 301 | size = 0; |
| 302 | }else{ |
| 303 | if( isPrivate ) blob_append(pXfer->pOut, "private\n", -1); |
| 304 | blob_appendf(pXfer->pOut, "file %b %s %d\n", pUuid, zUuid, size); |
| 305 | blob_append(pXfer->pOut, blob_buffer(&delta), size); |
| 306 | /* blob_appendf(pXfer->pOut, "\n", 1); */ |
| 307 | } |
| 308 | blob_reset(&delta); |
| 309 | free(zUuid); |
| 310 | blob_reset(&src); |
| 311 | } |
| @@ -424,10 +423,13 @@ | |
| 424 | pXfer->nDeltaSent++; |
| 425 | } |
| 426 | } |
| 427 | remote_has(rid); |
| 428 | blob_reset(&uuid); |
| 429 | } |
| 430 | |
| 431 | /* |
| 432 | ** Send the file identified by rid as a compressed artifact. Basically, |
| 433 | ** send the content exactly as it appears in the BLOB table using |
| @@ -470,11 +472,13 @@ | |
| 470 | }else{ |
| 471 | pXfer->nFileSent++; |
| 472 | } |
| 473 | blob_appendf(pXfer->pOut, "%d %d\n", szU, szC); |
| 474 | blob_append(pXfer->pOut, zContent, szC); |
| 475 | blob_append(pXfer->pOut, "\n", 1); |
| 476 | } |
| 477 | db_reset(&q1); |
| 478 | } |
| 479 | |
| 480 | /* |
| @@ -755,10 +759,19 @@ | |
| 755 | blob_size(&content), blob_str(&content)); |
| 756 | blob_reset(&content); |
| 757 | } |
| 758 | } |
| 759 | |
| 760 | |
| 761 | /* |
| 762 | ** If this variable is set, disable login checks. Used for debugging |
| 763 | ** only. |
| 764 | */ |
| @@ -879,14 +892,16 @@ | |
| 879 | if( xfer.nToken>=2 |
| 880 | && blob_eq(&xfer.aToken[0], "igot") |
| 881 | && blob_is_uuid(&xfer.aToken[1]) |
| 882 | ){ |
| 883 | if( isPush ){ |
| 884 | if( xfer.nToken==2 || blob_eq(&xfer.aToken[1],"1")==0 ){ |
| 885 | rid_from_uuid(&xfer.aToken[1], 1, 0); |
| 886 | }else if( g.okPrivate ){ |
| 887 | rid_from_uuid(&xfer.aToken[1], 1, 1); |
| 888 | } |
| 889 | } |
| 890 | }else |
| 891 | |
| 892 | |
| @@ -1092,11 +1107,15 @@ | |
| 1092 | ** |
| 1093 | ** This card indicates that the next "file" or "cfile" will contain |
| 1094 | ** private content. |
| 1095 | */ |
| 1096 | if( blob_eq(&xfer.aToken[0], "private") ){ |
| 1097 | xfer.nextIsPrivate = 1; |
| 1098 | }else |
| 1099 | |
| 1100 | |
| 1101 | /* pragma NAME VALUE... |
| 1102 | ** |
| @@ -1110,11 +1129,15 @@ | |
| 1110 | ** If the user has the "x" privilege (which must be set explicitly - |
| 1111 | ** it is not automatic with "a" or "s") then this pragma causes |
| 1112 | ** private information to be pulled in addition to public records. |
| 1113 | */ |
| 1114 | if( blob_eq(&xfer.aToken[1], "send-private") ){ |
| 1115 | if( g.okPrivate ) xfer.syncPrivate = 1; |
| 1116 | } |
| 1117 | }else |
| 1118 | |
| 1119 | /* Unknown message |
| 1120 | */ |
| @@ -1308,10 +1331,11 @@ | |
| 1308 | request_phantoms(&xfer, mxPhantomReq); |
| 1309 | } |
| 1310 | if( pushFlag ){ |
| 1311 | send_unsent(&xfer); |
| 1312 | nCardSent += send_unclustered(&xfer); |
| 1313 | } |
| 1314 | |
| 1315 | /* Send configuration parameter requests. On a clone, delay sending |
| 1316 | ** this until the second cycle since the login card might fail on |
| 1317 | ** the first cycle. |
| @@ -1470,11 +1494,11 @@ | |
| 1470 | if( xfer.nToken>=2 |
| 1471 | && blob_eq(&xfer.aToken[0], "igot") |
| 1472 | && blob_is_uuid(&xfer.aToken[1]) |
| 1473 | ){ |
| 1474 | int rid; |
| 1475 | int isPriv = xfer.nToken>=3 && blob_eq(&xfer.aToken[1],"1"); |
| 1476 | rid = rid_from_uuid(&xfer.aToken[1], 0, 0); |
| 1477 | if( rid>0 ){ |
| 1478 | if( !isPriv ) content_make_public(rid); |
| 1479 | }else if( !g.okPrivate ){ |
| 1480 | /* ignore private files */ |
| 1481 |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -155,11 +155,11 @@ | |
| 155 | if( content_get(srcid, &src)==0 ){ |
| 156 | rid = content_put_ex(&content, blob_str(&pXfer->aToken[1]), srcid, |
| 157 | 0, isPriv); |
| 158 | pXfer->nDanglingFile++; |
| 159 | db_multi_exec("DELETE FROM phantom WHERE rid=%d", rid); |
| 160 | if( !isPriv ) content_make_public(rid); |
| 161 | return; |
| 162 | } |
| 163 | pXfer->nDeltaRcvd++; |
| 164 | blob_delta_apply(&src, &content, &next); |
| 165 | blob_reset(&src); |
| @@ -301,11 +301,10 @@ | |
| 301 | size = 0; |
| 302 | }else{ |
| 303 | if( isPrivate ) blob_append(pXfer->pOut, "private\n", -1); |
| 304 | blob_appendf(pXfer->pOut, "file %b %s %d\n", pUuid, zUuid, size); |
| 305 | blob_append(pXfer->pOut, blob_buffer(&delta), size); |
| 306 | } |
| 307 | blob_reset(&delta); |
| 308 | free(zUuid); |
| 309 | blob_reset(&src); |
| 310 | } |
| @@ -424,10 +423,13 @@ | |
| 423 | pXfer->nDeltaSent++; |
| 424 | } |
| 425 | } |
| 426 | remote_has(rid); |
| 427 | blob_reset(&uuid); |
| 428 | if( blob_buffer(pXfer->pOut)[blob_size(pXfer->pOut)-1]!='\n' ){ |
| 429 | blob_appendf(pXfer->pOut, "\n", 1); |
| 430 | } |
| 431 | } |
| 432 | |
| 433 | /* |
| 434 | ** Send the file identified by rid as a compressed artifact. Basically, |
| 435 | ** send the content exactly as it appears in the BLOB table using |
| @@ -470,11 +472,13 @@ | |
| 472 | }else{ |
| 473 | pXfer->nFileSent++; |
| 474 | } |
| 475 | blob_appendf(pXfer->pOut, "%d %d\n", szU, szC); |
| 476 | blob_append(pXfer->pOut, zContent, szC); |
| 477 | if( blob_buffer(pXfer->pOut)[blob_size(pXfer->pOut)-1]!='\n' ){ |
| 478 | blob_appendf(pXfer->pOut, "\n", 1); |
| 479 | } |
| 480 | } |
| 481 | db_reset(&q1); |
| 482 | } |
| 483 | |
| 484 | /* |
| @@ -755,10 +759,19 @@ | |
| 759 | blob_size(&content), blob_str(&content)); |
| 760 | blob_reset(&content); |
| 761 | } |
| 762 | } |
| 763 | |
| 764 | |
| 765 | /* |
| 766 | ** Called when there is an attempt to transfer private content to and |
| 767 | ** from a server without authorization. |
| 768 | */ |
| 769 | static void server_private_xfer_not_authorized(void){ |
| 770 | @ error not\sauthorized\sto\ssync\sprivate\scontent |
| 771 | } |
| 772 | |
| 773 | |
| 774 | /* |
| 775 | ** If this variable is set, disable login checks. Used for debugging |
| 776 | ** only. |
| 777 | */ |
| @@ -879,14 +892,16 @@ | |
| 892 | if( xfer.nToken>=2 |
| 893 | && blob_eq(&xfer.aToken[0], "igot") |
| 894 | && blob_is_uuid(&xfer.aToken[1]) |
| 895 | ){ |
| 896 | if( isPush ){ |
| 897 | if( xfer.nToken==2 || blob_eq(&xfer.aToken[2],"1")==0 ){ |
| 898 | rid_from_uuid(&xfer.aToken[1], 1, 0); |
| 899 | }else if( g.okPrivate ){ |
| 900 | rid_from_uuid(&xfer.aToken[1], 1, 1); |
| 901 | }else{ |
| 902 | server_private_xfer_not_authorized(); |
| 903 | } |
| 904 | } |
| 905 | }else |
| 906 | |
| 907 | |
| @@ -1092,11 +1107,15 @@ | |
| 1107 | ** |
| 1108 | ** This card indicates that the next "file" or "cfile" will contain |
| 1109 | ** private content. |
| 1110 | */ |
| 1111 | if( blob_eq(&xfer.aToken[0], "private") ){ |
| 1112 | if( !g.okPrivate ){ |
| 1113 | server_private_xfer_not_authorized(); |
| 1114 | }else{ |
| 1115 | xfer.nextIsPrivate = 1; |
| 1116 | } |
| 1117 | }else |
| 1118 | |
| 1119 | |
| 1120 | /* pragma NAME VALUE... |
| 1121 | ** |
| @@ -1110,11 +1129,15 @@ | |
| 1129 | ** If the user has the "x" privilege (which must be set explicitly - |
| 1130 | ** it is not automatic with "a" or "s") then this pragma causes |
| 1131 | ** private information to be pulled in addition to public records. |
| 1132 | */ |
| 1133 | if( blob_eq(&xfer.aToken[1], "send-private") ){ |
| 1134 | if( !g.okPrivate ){ |
| 1135 | server_private_xfer_not_authorized(); |
| 1136 | }else{ |
| 1137 | xfer.syncPrivate = 1; |
| 1138 | } |
| 1139 | } |
| 1140 | }else |
| 1141 | |
| 1142 | /* Unknown message |
| 1143 | */ |
| @@ -1308,10 +1331,11 @@ | |
| 1331 | request_phantoms(&xfer, mxPhantomReq); |
| 1332 | } |
| 1333 | if( pushFlag ){ |
| 1334 | send_unsent(&xfer); |
| 1335 | nCardSent += send_unclustered(&xfer); |
| 1336 | if( privateFlag ) send_private(&xfer); |
| 1337 | } |
| 1338 | |
| 1339 | /* Send configuration parameter requests. On a clone, delay sending |
| 1340 | ** this until the second cycle since the login card might fail on |
| 1341 | ** the first cycle. |
| @@ -1470,11 +1494,11 @@ | |
| 1494 | if( xfer.nToken>=2 |
| 1495 | && blob_eq(&xfer.aToken[0], "igot") |
| 1496 | && blob_is_uuid(&xfer.aToken[1]) |
| 1497 | ){ |
| 1498 | int rid; |
| 1499 | int isPriv = xfer.nToken>=3 && blob_eq(&xfer.aToken[2],"1"); |
| 1500 | rid = rid_from_uuid(&xfer.aToken[1], 0, 0); |
| 1501 | if( rid>0 ){ |
| 1502 | if( !isPriv ) content_make_public(rid); |
| 1503 | }else if( !g.okPrivate ){ |
| 1504 | /* ignore private files */ |
| 1505 |