Diff
Not logged in

Differences From:

File src/xfer.c part of check-in [2bd0690fe8] - Add the "all rebuild" subcommand. Be more aggressive about adding repositories to the repository list. by drh on 2008-10-17 12:31:26. [view]

To:

File src/xfer.c part of check-in [6b0b57a924] - 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. by drh on 2008-10-25 17:51:37. [view]

@@ -482,8 +482,30 @@
   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;
@@ -508,8 +530,10 @@
   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);
@@ -679,26 +703,52 @@
     ){
       if( g.okRead ){
         char *zName = blob_str(&xfer.aToken[1]);
         if( configure_is_exportable(zName) ){
-          if( zName[0]!='@' ){
-            char *zValue = db_get(zName, 0);
-            if( zValue ){
-              blob_appendf(xfer.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(xfer.pOut, "config %s %d\n%s\n", zName,
-               blob_size(&content), blob_str(&content));
-            blob_reset(&content);
-          }
+          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.
@@ -742,8 +792,11 @@
     send_all(&xfer);
   }else if( isPull ){
     create_cluster();
     send_unclustered(&xfer);
+  }
+  if( recvConfig ){
+    configure_finalize_receive();
   }
   db_end_transaction(0);
 }
 
@@ -794,17 +847,23 @@
 ** 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, int pullFlag, int cloneFlag, int configMask){
+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 origConfigMask;     /* Original value of configMask */
+  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 */
@@ -815,9 +874,9 @@
   xfer.pIn = &recv;
   xfer.pOut = &send;
   xfer.mxSend = db_get_int("max-upload", 250000);
 
-  assert( pushFlag || pullFlag || cloneFlag || configMask );
+  assert( pushFlag | pullFlag | cloneFlag | configRcvMask | configSendMask );
   assert( !g.urlIsFile );          /* This only works for networking */
 
   db_begin_transaction();
   db_record_repository_filename(0);
@@ -828,9 +887,9 @@
   blob_zero(&send);
   blob_zero(&recv);
   blob_zero(&xfer.err);
   blob_zero(&xfer.line);
-  origConfigMask = configMask;
+  origConfigRcvMask = configRcvMask;
 
   /*
   ** Always begin with a clone, pull, or push message
   */
@@ -873,20 +932,32 @@
       nCard += send_unclustered(&xfer);
     }
 
     /* Send configuration parameter requests */
-    if( configMask ){
+    if( configRcvMask ){
       const char *zName;
-      zName = configure_first_name(configMask);
+      zName = configure_first_name(configRcvMask);
       while( zName ){
         blob_appendf(&send, "reqconfig %s\n", zName);
-        zName = configure_next_name(configMask);
+        zName = configure_next_name(configRcvMask);
         nCard++;
       }
-      if( configMask & (CONFIGSET_USER|CONFIGSET_TKT) ){
+      if( configRcvMask & (CONFIGSET_USER|CONFIGSET_TKT) ){
         configure_prepare_to_receive(0);
       }
-      configMask = 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 */
@@ -1007,15 +1078,20 @@
         const char *zName = blob_str(&xfer.aToken[1]);
         Blob content;
         blob_zero(&content);
         blob_extract(xfer.pIn, size, &content);
-        if( configure_is_exportable(zName) & origConfigMask ){
+        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++;
@@ -1067,12 +1143,12 @@
       }
       blobarray_reset(xfer.aToken, xfer.nToken);
       blob_reset(&xfer.line);
     }
-    if( origConfigMask & (CONFIGSET_TKT|CONFIGSET_USER) ){
+    if( origConfigRcvMask & (CONFIGSET_TKT|CONFIGSET_USER) ){
       configure_finalize_receive();
     }
-    origConfigMask = 0;
+    origConfigRcvMask = 0;
     printf(zValueFormat, "Received:",
             blob_size(&recv), nCard,
             xfer.nFileRcvd, xfer.nDeltaRcvd + xfer.nDanglingFile);
     blob_reset(&recv);