| | @@ -38,11 +38,11 @@ |
| 38 | 38 | int nDeltaSent; /* Number of deltas sent */ |
| 39 | 39 | int nFileRcvd; /* Number of files received */ |
| 40 | 40 | int nDeltaRcvd; /* Number of deltas received */ |
| 41 | 41 | int nDanglingFile; /* Number of dangling deltas received */ |
| 42 | 42 | int mxSend; /* Stop sending "file" with pOut reaches this size */ |
| 43 | | - u8 sendPrivate; /* True to enable sending private content */ |
| 43 | + u8 syncPrivate; /* True to enable syncing private content */ |
| 44 | 44 | u8 nextIsPrivate; /* If true, next "file" received is a private */ |
| 45 | 45 | }; |
| 46 | 46 | |
| 47 | 47 | |
| 48 | 48 | /* |
| | @@ -261,10 +261,11 @@ |
| 261 | 261 | ** Never send a delta against a private artifact. |
| 262 | 262 | */ |
| 263 | 263 | static int send_delta_parent( |
| 264 | 264 | Xfer *pXfer, /* The transfer context */ |
| 265 | 265 | int rid, /* record id of the file to send */ |
| 266 | + int isPrivate, /* True if rid is a private artifact */ |
| 266 | 267 | Blob *pContent, /* The content of the file to send */ |
| 267 | 268 | Blob *pUuid /* The UUID of the file to send */ |
| 268 | 269 | ){ |
| 269 | 270 | static const char *azQuery[] = { |
| 270 | 271 | "SELECT pid FROM plink x" |
| | @@ -285,19 +286,23 @@ |
| 285 | 286 | int srcId = 0; |
| 286 | 287 | |
| 287 | 288 | for(i=0; srcId==0 && i<count(azQuery); i++){ |
| 288 | 289 | srcId = db_int(0, azQuery[i], rid); |
| 289 | 290 | } |
| 290 | | - if( srcId>0 && !content_is_private(srcId) && content_get(srcId, &src) ){ |
| 291 | + if( srcId>0 |
| 292 | + && (pXfer->syncPrivate || !content_is_private(srcId)) |
| 293 | + && content_get(srcId, &src) |
| 294 | + ){ |
| 291 | 295 | char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", srcId); |
| 292 | 296 | blob_delta_create(&src, pContent, &delta); |
| 293 | 297 | size = blob_size(&delta); |
| 294 | 298 | if( size>=blob_size(pContent)-50 ){ |
| 295 | 299 | size = 0; |
| 296 | 300 | }else if( uuid_is_shunned(zUuid) ){ |
| 297 | 301 | size = 0; |
| 298 | 302 | }else{ |
| 303 | + if( isPrivate ) blob_append(pXfer->pOut, "private\n", -1); |
| 299 | 304 | blob_appendf(pXfer->pOut, "file %b %s %d\n", pUuid, zUuid, size); |
| 300 | 305 | blob_append(pXfer->pOut, blob_buffer(&delta), size); |
| 301 | 306 | /* blob_appendf(pXfer->pOut, "\n", 1); */ |
| 302 | 307 | } |
| 303 | 308 | blob_reset(&delta); |
| | @@ -316,27 +321,31 @@ |
| 316 | 321 | ** Never send a delta against a private artifact. |
| 317 | 322 | */ |
| 318 | 323 | static int send_delta_native( |
| 319 | 324 | Xfer *pXfer, /* The transfer context */ |
| 320 | 325 | int rid, /* record id of the file to send */ |
| 326 | + int isPrivate, /* True if rid is a private artifact */ |
| 321 | 327 | Blob *pUuid /* The UUID of the file to send */ |
| 322 | 328 | ){ |
| 323 | 329 | Blob src, delta; |
| 324 | 330 | int size = 0; |
| 325 | 331 | int srcId; |
| 326 | 332 | |
| 327 | 333 | srcId = db_int(0, "SELECT srcid FROM delta WHERE rid=%d", rid); |
| 328 | | - if( srcId>0 && !content_is_private(srcId) ){ |
| 334 | + if( srcId>0 |
| 335 | + && (pXfer->syncPrivate || !content_is_private(srcId)) |
| 336 | + ){ |
| 329 | 337 | blob_zero(&src); |
| 330 | 338 | db_blob(&src, "SELECT uuid FROM blob WHERE rid=%d", srcId); |
| 331 | 339 | if( uuid_is_shunned(blob_str(&src)) ){ |
| 332 | 340 | blob_reset(&src); |
| 333 | 341 | return 0; |
| 334 | 342 | } |
| 335 | 343 | blob_zero(&delta); |
| 336 | 344 | db_blob(&delta, "SELECT content FROM blob WHERE rid=%d", rid); |
| 337 | 345 | blob_uncompress(&delta, &delta); |
| 346 | + if( isPrivate ) blob_append(pXfer->pOut, "private\n", -1); |
| 338 | 347 | blob_appendf(pXfer->pOut, "file %b %b %d\n", |
| 339 | 348 | pUuid, &src, blob_size(&delta)); |
| 340 | 349 | blob_append(pXfer->pOut, blob_buffer(&delta), blob_size(&delta)); |
| 341 | 350 | size = blob_size(&delta); |
| 342 | 351 | blob_reset(&delta); |
| | @@ -361,12 +370,13 @@ |
| 361 | 370 | ** this routine becomes a no-op. |
| 362 | 371 | */ |
| 363 | 372 | static void send_file(Xfer *pXfer, int rid, Blob *pUuid, int nativeDelta){ |
| 364 | 373 | Blob content, uuid; |
| 365 | 374 | int size = 0; |
| 375 | + int isPriv = content_is_private(rid); |
| 366 | 376 | |
| 367 | | - if( content_is_private(rid) ) return; |
| 377 | + if( pXfer->syncPrivate==0 && isPriv ) return; |
| 368 | 378 | if( db_exists("SELECT 1 FROM onremote WHERE rid=%d", rid) ){ |
| 369 | 379 | return; |
| 370 | 380 | } |
| 371 | 381 | blob_zero(&uuid); |
| 372 | 382 | db_blob(&uuid, "SELECT uuid FROM blob WHERE rid=%d AND size>=0", rid); |
| | @@ -384,29 +394,31 @@ |
| 384 | 394 | if( uuid_is_shunned(blob_str(pUuid)) ){ |
| 385 | 395 | blob_reset(&uuid); |
| 386 | 396 | return; |
| 387 | 397 | } |
| 388 | 398 | if( pXfer->mxSend<=blob_size(pXfer->pOut) ){ |
| 389 | | - blob_appendf(pXfer->pOut, "igot %b\n", pUuid); |
| 399 | + const char *zFormat = isPriv ? "igot %b 1\n" : "igot %b\n"; |
| 400 | + blob_appendf(pXfer->pOut, zFormat, pUuid); |
| 390 | 401 | pXfer->nIGotSent++; |
| 391 | 402 | blob_reset(&uuid); |
| 392 | 403 | return; |
| 393 | 404 | } |
| 394 | 405 | if( nativeDelta ){ |
| 395 | | - size = send_delta_native(pXfer, rid, pUuid); |
| 406 | + size = send_delta_native(pXfer, rid, isPriv, pUuid); |
| 396 | 407 | if( size ){ |
| 397 | 408 | pXfer->nDeltaSent++; |
| 398 | 409 | } |
| 399 | 410 | } |
| 400 | 411 | if( size==0 ){ |
| 401 | 412 | content_get(rid, &content); |
| 402 | 413 | |
| 403 | 414 | if( !nativeDelta && blob_size(&content)>100 ){ |
| 404 | | - size = send_delta_parent(pXfer, rid, &content, pUuid); |
| 415 | + size = send_delta_parent(pXfer, rid, isPriv, &content, pUuid); |
| 405 | 416 | } |
| 406 | 417 | if( size==0 ){ |
| 407 | 418 | int size = blob_size(&content); |
| 419 | + if( isPriv ) blob_append(pXfer->pOut, "private\n", -1); |
| 408 | 420 | blob_appendf(pXfer->pOut, "file %b %d\n", pUuid, size); |
| 409 | 421 | blob_append(pXfer->pOut, blob_buffer(&content), size); |
| 410 | 422 | pXfer->nFileSent++; |
| 411 | 423 | }else{ |
| 412 | 424 | pXfer->nDeltaSent++; |
| | @@ -426,33 +438,35 @@ |
| 426 | 438 | const char *zUuid; |
| 427 | 439 | const char *zDelta; |
| 428 | 440 | int szU; |
| 429 | 441 | int szC; |
| 430 | 442 | int rc; |
| 443 | + int isPrivate; |
| 431 | 444 | static Stmt q1; |
| 432 | 445 | |
| 446 | + isPrivate = content_is_private(rid); |
| 447 | + if( isPrivate && pXfer->syncPrivate==0 ) return; |
| 433 | 448 | db_static_prepare(&q1, |
| 434 | 449 | "SELECT uuid, size, content," |
| 435 | 450 | " (SELECT uuid FROM delta, blob" |
| 436 | 451 | " WHERE delta.rid=:rid AND delta.srcid=blob.rid)" |
| 437 | 452 | " FROM blob" |
| 438 | 453 | " WHERE rid=:rid" |
| 439 | 454 | " AND size>=0" |
| 440 | 455 | " AND uuid NOT IN shun" |
| 441 | | - " AND rid NOT IN private", |
| 442 | | - rid |
| 443 | 456 | ); |
| 444 | 457 | db_bind_int(&q1, ":rid", rid); |
| 445 | 458 | rc = db_step(&q1); |
| 446 | 459 | if( rc==SQLITE_ROW ){ |
| 447 | 460 | zUuid = db_column_text(&q1, 0); |
| 448 | 461 | szU = db_column_int(&q1, 1); |
| 449 | 462 | szC = db_column_bytes(&q1, 2); |
| 450 | 463 | zContent = db_column_raw(&q1, 2); |
| 451 | 464 | zDelta = db_column_text(&q1, 3); |
| 465 | + if( isPrivate ) blob_append(pXfer->pOut, "private\n", -1); |
| 452 | 466 | blob_appendf(pXfer->pOut, "cfile %s ", zUuid); |
| 453 | | - if( zDelta ){ |
| 467 | + if( zDelta ){ |
| 454 | 468 | blob_appendf(pXfer->pOut, "%s ", zDelta); |
| 455 | 469 | pXfer->nDeltaSent++; |
| 456 | 470 | }else{ |
| 457 | 471 | pXfer->nFileSent++; |
| 458 | 472 | } |
| | @@ -472,11 +486,11 @@ |
| 472 | 486 | static void request_phantoms(Xfer *pXfer, int maxReq){ |
| 473 | 487 | Stmt q; |
| 474 | 488 | db_prepare(&q, |
| 475 | 489 | "SELECT uuid FROM phantom JOIN blob USING(rid)" |
| 476 | 490 | " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid) %s", |
| 477 | | - (pXfer->sendPrivate ? "" : |
| 491 | + (pXfer->syncPrivate ? "" : |
| 478 | 492 | " AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)") |
| 479 | 493 | ); |
| 480 | 494 | while( db_step(&q)==SQLITE_ROW && maxReq-- > 0 ){ |
| 481 | 495 | const char *zUuid = db_column_text(&q, 0); |
| 482 | 496 | blob_appendf(pXfer->pOut, "gimme %s\n", zUuid); |
| | @@ -668,11 +682,11 @@ |
| 668 | 682 | ** Send igot messages for every private artifact |
| 669 | 683 | */ |
| 670 | 684 | static int send_private(Xfer *pXfer){ |
| 671 | 685 | int cnt = 0; |
| 672 | 686 | Stmt q; |
| 673 | | - if( pXfer->sendPrivate ){ |
| 687 | + if( pXfer->syncPrivate ){ |
| 674 | 688 | db_prepare(&q, "SELECT uuid FROM private JOIN blob USING(rid)"); |
| 675 | 689 | while( db_step(&q)==SQLITE_ROW ){ |
| 676 | 690 | blob_appendf(pXfer->pOut, "igot %s 1\n", db_column_text(&q,0)); |
| 677 | 691 | cnt++; |
| 678 | 692 | } |
| | @@ -1088,19 +1102,19 @@ |
| 1088 | 1102 | ** |
| 1089 | 1103 | ** The client issue pragmas to try to influence the behavior of the |
| 1090 | 1104 | ** server. These are requests only. Unknown pragmas are silently |
| 1091 | 1105 | ** ignored. |
| 1092 | 1106 | */ |
| 1093 | | - if( blob_eq(&xfer.aToken[0], "set") && xfer.nToken>=2 ){ |
| 1107 | + if( blob_eq(&xfer.aToken[0], "pragma") && xfer.nToken>=2 ){ |
| 1094 | 1108 | /* pragma send-private |
| 1095 | 1109 | ** |
| 1096 | 1110 | ** If the user has the "x" privilege (which must be set explicitly - |
| 1097 | 1111 | ** it is not automatic with "a" or "s") then this pragma causes |
| 1098 | 1112 | ** private information to be pulled in addition to public records. |
| 1099 | 1113 | */ |
| 1100 | 1114 | if( blob_eq(&xfer.aToken[1], "send-private") ){ |
| 1101 | | - if( g.okPrivate ) xfer.sendPrivate = 1; |
| 1115 | + if( g.okPrivate ) xfer.syncPrivate = 1; |
| 1102 | 1116 | } |
| 1103 | 1117 | }else |
| 1104 | 1118 | |
| 1105 | 1119 | /* Unknown message |
| 1106 | 1120 | */ |
| | @@ -1120,15 +1134,15 @@ |
| 1120 | 1134 | ** cause the client to create phantoms for all artifacts, which will |
| 1121 | 1135 | ** in turn make sure that the entire repository is sent efficiently |
| 1122 | 1136 | ** and expeditiously. |
| 1123 | 1137 | */ |
| 1124 | 1138 | send_all(&xfer); |
| 1125 | | - if( xfer.sendPrivate ) send_private(&xfer); |
| 1139 | + if( xfer.syncPrivate ) send_private(&xfer); |
| 1126 | 1140 | }else if( isPull ){ |
| 1127 | 1141 | create_cluster(); |
| 1128 | 1142 | send_unclustered(&xfer); |
| 1129 | | - if( xfer.sendPrivate ) send_private(&xfer); |
| 1143 | + if( xfer.syncPrivate ) send_private(&xfer); |
| 1130 | 1144 | } |
| 1131 | 1145 | if( recvConfig ){ |
| 1132 | 1146 | configure_finalize_receive(); |
| 1133 | 1147 | } |
| 1134 | 1148 | manifest_crosslink_end(); |
| | @@ -1231,11 +1245,11 @@ |
| 1231 | 1245 | xfer.pIn = &recv; |
| 1232 | 1246 | xfer.pOut = &send; |
| 1233 | 1247 | xfer.mxSend = db_get_int("max-upload", 250000); |
| 1234 | 1248 | if( privateFlag ){ |
| 1235 | 1249 | g.okPrivate = 1; |
| 1236 | | - xfer.sendPrivate = 1; |
| 1250 | + xfer.syncPrivate = 1; |
| 1237 | 1251 | } |
| 1238 | 1252 | |
| 1239 | 1253 | assert( pushFlag | pullFlag | cloneFlag | configRcvMask | configSendMask ); |
| 1240 | 1254 | db_begin_transaction(); |
| 1241 | 1255 | db_record_repository_filename(0); |
| | @@ -1247,10 +1261,14 @@ |
| 1247 | 1261 | blob_zero(&recv); |
| 1248 | 1262 | blob_zero(&xfer.err); |
| 1249 | 1263 | blob_zero(&xfer.line); |
| 1250 | 1264 | origConfigRcvMask = 0; |
| 1251 | 1265 | |
| 1266 | + |
| 1267 | + /* Send the send-private pragma if we are trying to sync private data */ |
| 1268 | + if( privateFlag ) blob_append(&send, "pragma send-private\n", -1); |
| 1269 | + |
| 1252 | 1270 | /* |
| 1253 | 1271 | ** Always begin with a clone, pull, or push message |
| 1254 | 1272 | */ |
| 1255 | 1273 | if( cloneFlag ){ |
| 1256 | 1274 | blob_appendf(&send, "clone 3 %d\n", cloneSeqno); |
| | @@ -1281,17 +1299,10 @@ |
| 1281 | 1299 | zCookie = db_get("cookie", 0); |
| 1282 | 1300 | if( zCookie ){ |
| 1283 | 1301 | blob_appendf(&send, "cookie %s\n", zCookie); |
| 1284 | 1302 | } |
| 1285 | 1303 | |
| 1286 | | - /* Send a pragma to alert the server that we want private content if |
| 1287 | | - ** doing a private push, pull, sync, or clone. |
| 1288 | | - */ |
| 1289 | | - if( privateFlag ){ |
| 1290 | | - blob_append(&send, "pragma send-private\n", -1); |
| 1291 | | - } |
| 1292 | | - |
| 1293 | 1304 | /* Generate gimme cards for phantoms and leaf cards |
| 1294 | 1305 | ** for all leaves. |
| 1295 | 1306 | */ |
| 1296 | 1307 | if( pullFlag || (cloneFlag && cloneSeqno==1) ){ |
| 1297 | 1308 | request_phantoms(&xfer, mxPhantomReq); |
| | @@ -1360,10 +1371,13 @@ |
| 1360 | 1371 | break; |
| 1361 | 1372 | } |
| 1362 | 1373 | lastPctDone = -1; |
| 1363 | 1374 | blob_reset(&send); |
| 1364 | 1375 | rArrivalTime = db_double(0.0, "SELECT julianday('now')"); |
| 1376 | + |
| 1377 | + /* Send the send-private pragma if we are trying to sync private data */ |
| 1378 | + if( privateFlag ) blob_append(&send, "pragma send-private\n", -1); |
| 1365 | 1379 | |
| 1366 | 1380 | /* Begin constructing the next message (which might never be |
| 1367 | 1381 | ** sent) by beginning with the pull or push cards |
| 1368 | 1382 | */ |
| 1369 | 1383 | if( pullFlag ){ |
| 1370 | 1384 | |