Diff
Not logged in

Differences From:

File src/xfer.c part of check-in [327823e39b] - Continuing work on the new HTTP transport mechanism. Make it more obvious where in the code extensions to support file: and https: belong. by drh on 2009-03-30 00:58:20. [view]

To:

File src/xfer.c part of check-in [7a2c37063a] - merge trunk into creole branch by bob on 2009-09-22 07:49:39. Also file src/xfer.c part of check-in [39a144eb5c] - Make sure that bringing up the "/xfer" URL in a web-browser does something sensible (it redirects to the homepage.) Ticket 1d7bbe30aad51. by drh on 2009-09-16 14:50:24. [view]

@@ -98,8 +98,11 @@
 ** content of DELTASRC.
 **
 ** If any error occurs, write a message into pErr which has already
 ** be initialized to an empty string.
+**
+** Any artifact successfully received by this routine is considered to
+** be public and is therefore removed from the "private" table.
 */
 static void xfer_accept_file(Xfer *pXfer){
   int n;
   int rid;
@@ -126,12 +129,12 @@
   if( pXfer->nToken==4 ){
     Blob src;
     srcid = rid_from_uuid(&pXfer->aToken[2], 1);
     if( content_get(srcid, &src)==0 ){
-      content_put(&content, blob_str(&pXfer->aToken[1]), srcid);
-      blob_appendf(pXfer->pOut, "gimme %b\n", &pXfer->aToken[2]);
-      pXfer->nGimmeSent++;
+      rid = content_put(&content, blob_str(&pXfer->aToken[1]), srcid);
       pXfer->nDanglingFile++;
+      db_multi_exec("DELETE FROM phantom WHERE rid=%d", rid);
+      content_make_public(rid);
       return;
     }
     pXfer->nDeltaRcvd++;
     blob_delta_apply(&src, &content, &content);
@@ -147,9 +150,9 @@
   blob_reset(&hash);
   if( rid==0 ){
     blob_appendf(&pXfer->err, "%s", g.zErrMsg);
   }else{
-    /* db_multi_exec("DELETE FROM phantom WHERE rid=%d", rid); */
+    content_make_public(rid);
     manifest_crosslink(rid, &content);
   }
   remote_has(rid);
 }
@@ -158,8 +161,10 @@
 ** Try to send a file as a delta against its parent.
 ** If successful, return the number of bytes in the delta.
 ** If we cannot generate an appropriate delta, then send
 ** nothing and return zero.
+**
+** Never send a delta against a private artifact.
 */
 static int send_delta_parent(
   Xfer *pXfer,            /* The transfer context */
   int rid,                /* record id of the file to send */
@@ -186,9 +191,9 @@
 
   for(i=0; srcId==0 && i<count(azQuery); i++){
     srcId = db_int(0, azQuery[i], rid);
   }
-  if( srcId>0 && content_get(srcId, &src) ){
+  if( srcId>0 && !content_is_private(srcId) && content_get(srcId, &src) ){
     char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", srcId);
     blob_delta_create(&src, pContent, &delta);
     size = blob_size(&delta);
     if( size>=blob_size(pContent)-50 ){
@@ -211,8 +216,10 @@
 ** Try to send a file as a native delta.
 ** If successful, return the number of bytes in the delta.
 ** If we cannot generate an appropriate delta, then send
 ** nothing and return zero.
+**
+** Never send a delta against a private artifact.
 */
 static int send_delta_native(
   Xfer *pXfer,            /* The transfer context */
   int rid,                /* record id of the file to send */
@@ -222,9 +229,9 @@
   int size = 0;
   int srcId;
 
   srcId = db_int(0, "SELECT srcid FROM delta WHERE rid=%d", rid);
-  if( srcId>0 ){
+  if( srcId>0 && !content_is_private(srcId) ){
     blob_zero(&src);
     db_blob(&src, "SELECT uuid FROM blob WHERE rid=%d", srcId);
     if( uuid_is_shunned(blob_str(&src)) ){
       blob_reset(&src);
@@ -252,13 +259,18 @@
 ** from the rid.
 **
 ** Try to send the file as a native delta if nativeDelta is true, or
 ** as a parent delta if nativeDelta is false.
+**
+** It should never be the case that rid is a private artifact.  But
+** as a precaution, this routine does check on rid and if it is private
+** this routine becomes a no-op.
 */
 static void send_file(Xfer *pXfer, int rid, Blob *pUuid, int nativeDelta){
   Blob content, uuid;
   int size = 0;
 
+  if( content_is_private(rid) ) return;
   if( db_exists("SELECT 1 FROM onremote WHERE rid=%d", rid) ){
      return;
   }
   blob_zero(&uuid);
@@ -310,14 +322,18 @@
 }
 
 /*
 ** Send a gimme message for every phantom.
+**
+** It should not be possible to have a private phantom.  But just to be
+** sure, take care not to send any "gimme" messagse on private artifacts.
 */
 static void request_phantoms(Xfer *pXfer, int maxReq){
   Stmt q;
   db_prepare(&q,
     "SELECT uuid FROM phantom JOIN blob USING(rid)"
     " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)"
+    "   AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)"
   );
   while( db_step(&q)==SQLITE_ROW && maxReq-- > 0 ){
     const char *zUuid = db_column_text(&q, 0);
     blob_appendf(pXfer->pOut, "gimme %s\n", zUuid);
@@ -367,11 +383,17 @@
 ** http_exchange() routine.
 */
 void check_login(Blob *pLogin, Blob *pNonce, Blob *pSig){
   Stmt q;
-  int rc;
-
-  db_prepare(&q, "SELECT pw, cap, uid FROM user WHERE login=%B", pLogin);
+  int rc = -1;
+
+  db_prepare(&q,
+     "SELECT pw, cap, uid FROM user"
+     " WHERE login=%B"
+     "   AND login NOT IN ('anonymous','nobody','developer','reader')"
+     "   AND length(pw)>0",
+     pLogin
+  );
   if( db_step(&q)==SQLITE_ROW ){
     Blob pw, combined, hash;
     blob_zero(&pw);
     db_ephemeral_blob(&q, 0, &pw);
@@ -392,8 +414,13 @@
       g.zNonce = mprintf("%b", pNonce);
     }
   }
   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.
@@ -403,9 +430,9 @@
 ** It just might require an extra round trip or two.
 */
 static void send_unsent(Xfer *pXfer){
   Stmt q;
-  db_prepare(&q, "SELECT rid FROM unsent");
+  db_prepare(&q, "SELECT rid FROM unsent EXCEPT SELECT rid FROM private");
   while( db_step(&q)==SQLITE_ROW ){
     int rid = db_column_int(&q, 0);
     send_file(pXfer, rid, 0, 0);
   }
@@ -422,8 +449,15 @@
 static void create_cluster(void){
   Blob cluster, cksum;
   Stmt q;
   int nUncl;
+
+  /* We should not ever get any private artifacts in the unclustered table.
+  ** But if we do (because of a bug) now is a good time to delete them. */
+  db_multi_exec(
+    "DELETE FROM unclustered WHERE rid IN (SELECT rid FROM private)"
+  );
+
   nUncl = db_int(0, "SELECT count(*) FROM unclustered"
                     " WHERE NOT EXISTS(SELECT 1 FROM phantom"
                                       " WHERE rid=unclustered.rid)");
   if( nUncl<100 ){
@@ -457,8 +491,9 @@
   int cnt = 0;
   db_prepare(&q,
     "SELECT uuid FROM unclustered JOIN blob USING(rid)"
     " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)"
+    "   AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)"
   );
   while( db_step(&q)==SQLITE_ROW ){
     blob_appendf(pXfer->pOut, "igot %s\n", db_column_text(&q, 0));
     cnt++;
@@ -474,8 +509,9 @@
   Stmt q;
   db_prepare(&q,
     "SELECT uuid FROM blob "
     " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)"
+    "   AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)"
   );
   while( db_step(&q)==SQLITE_ROW ){
     blob_appendf(pXfer->pOut, "igot %s\n", db_column_text(&q, 0));
   }
@@ -533,8 +569,11 @@
   int nGimme = 0;
   int size;
   int recvConfig = 0;
 
+  if( strcmp(PD("REQUEST_METHOD","POST"),"POST") ){
+     fossil_redirect_home();
+  }
   memset(&xfer, 0, sizeof(xfer));
   blobarray_zero(xfer.aToken, count(xfer.aToken));
   cgi_set_content_type(g.zContentType);
   blob_zero(&xfer.err);
@@ -546,8 +585,9 @@
   db_begin_transaction();
   db_multi_exec(
      "CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);"
   );
+  manifest_crosslink_begin();
   while( blob_line(xfer.pIn, &xfer.line) ){
     if( blob_buffer(&xfer.line)[0]=='#' ) continue;
     xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken));
 
@@ -797,8 +837,9 @@
   }
   if( recvConfig ){
     configure_finalize_receive();
   }
+  manifest_crosslink_end();
   db_end_transaction(0);
 }
 
 /*
@@ -864,14 +905,20 @@
   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 */
+  int nSent, nRcvd;       /* Bytes sent and received (after compression) */
   Blob send;              /* Text we are sending to the server */
   Blob recv;              /* Reply we got back from the server */
   Xfer xfer;              /* Transfer data */
   const char *zSCode = db_get("server-code", "x");
   const char *zPCode = db_get("project-code", 0);
 
+  if( db_get_boolean("dont-push", 0) ) pushFlag = 0;
+  if( pushFlag + pullFlag + cloneFlag == 0
+     && configRcvMask==0 && configSendMask==0 ) return;
+
+  transport_stats(0, 0, 1);
   socket_global_init();
   memset(&xfer, 0, sizeof(xfer));
   xfer.pIn = &recv;
   xfer.pOut = &send;
@@ -906,8 +953,9 @@
   if( pushFlag ){
     blob_appendf(&send, "push %s %s\n", zSCode, zPCode);
     nCard++;
   }
+  manifest_crosslink_begin();
   printf(zLabelFormat, "", "Bytes", "Cards", "Artifacts", "Deltas");
 
   while( go ){
     int newPhantom = 0;
@@ -959,13 +1007,11 @@
       configSendMask = 0;
     }
 
     /* Append randomness to the end of the message */
-#if 1   /* Enable this after all servers have upgraded */
     zRandomness = db_text(0, "SELECT hex(randomblob(20))");
     blob_appendf(&send, "# %s\n", zRandomness);
     free(zRandomness);
-#endif
 
     /* Exchange messages with the server */
     nFileSend = xfer.nFileSent + xfer.nDeltaSent;
     printf(zValueFormat, "Send:",
@@ -1038,9 +1084,11 @@
        && blob_eq(&xfer.aToken[0], "igot")
        && blob_is_uuid(&xfer.aToken[1])
       ){
         int rid = rid_from_uuid(&xfer.aToken[1], 0);
-        if( rid==0 && (pullFlag || cloneFlag) ){
+        if( rid>0 ){
+          content_make_public(rid);
+        }else if( pullFlag || cloneFlag ){
           rid = content_new(blob_str(&xfer.aToken[1]));
           if( rid ) newPhantom = 1;
         }
         remote_has(rid);
@@ -1135,8 +1183,14 @@
       }else
 
       /* Unknown message */
       {
+        if( blob_str(&xfer.aToken[0])[0]=='<' ){
+          fossil_fatal(
+            "server replies with HTML instead of fossil sync protocol:\n%b",
+            &recv
+          );
+        }
         blob_appendf(&xfer.err, "unknown command: %b", &xfer.aToken[0]);
       }
 
       if( blob_size(&xfer.err) ){
@@ -1176,9 +1230,13 @@
     if( xfer.nFileSent+xfer.nDeltaSent>0 ){
       go = 1;
     }
   };
+  transport_stats(&nSent, &nRcvd, 1);
+  printf("Total network traffic: %d bytes sent, %d bytes received\n",
+         nSent, nRcvd);
   transport_close();
   socket_global_shutdown();
   db_multi_exec("DROP TABLE onremote");
+  manifest_crosslink_end();
   db_end_transaction(0);
 }