Fossil

Check-in [c56af61e5e]
Login

Check-in [c56af61e5e]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Infrastructure changes that will allow the client-side sync to be run from a web interface - the status messages now go to CGI output if the sync is run from a web page. This is a partial implementation of the "SyncNow" button. The button itself has not yet been added.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: c56af61e5e40db613bd649b676ce72810367435d
User & Date: drh 2010-04-22 15:48:25.000
References
2010-05-02
21:10 New ticket [7995323ab2] ignore-glob setting does not work on directory names. ... (artifact: bc269c330e user: anonymous)
20:27 New ticket [a90a412aef] fossil tag command does not accept -m / -M options. ... (artifact: 59d6aa0e2e user: anonymous)
Context
2010-04-26
15:36
allow "class" attributes in wiki html markup, so CSS is more useful ... (check-in: 99c26fccba user: ron tags: trunk)
2010-04-22
15:48
Infrastructure changes that will allow the client-side sync to be run from a web interface - the status messages now go to CGI output if the sync is run from a web page. This is a partial implementation of the "SyncNow" button. The button itself has not yet been added. ... (check-in: c56af61e5e user: drh tags: trunk)
15:18
Back out check-in [fc23960258211b5bc]. This will close ticket [a534227710d3e5] but re-open ticket [3b1533a090eebd09d]. ... (check-in: f7ec914037 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/db.c.
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
  z = vmprintf(zFormat, ap);
  va_end(ap);
  if( g.xferPanic ){
    cgi_reset_content();
    @ error Database\serror:\s%F(z)
    cgi_reply();
  }
  if( g.cgiPanic ){
    g.cgiPanic = 0;
    cgi_printf("<h1>Database Error</h1>\n"
               "<pre>%h</pre><p>%s</p>", z, zRebuildMsg);
    cgi_reply();
  }else{
    fprintf(stderr, "%s: %s\n\n%s", g.argv[0], z, zRebuildMsg);
  }
  db_force_rollback();







|
|







74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
  z = vmprintf(zFormat, ap);
  va_end(ap);
  if( g.xferPanic ){
    cgi_reset_content();
    @ error Database\serror:\s%F(z)
    cgi_reply();
  }
  if( g.cgiOutput ){
    g.cgiOutput = 0;
    cgi_printf("<h1>Database Error</h1>\n"
               "<pre>%h</pre><p>%s</p>", z, zRebuildMsg);
    cgi_reply();
  }else{
    fprintf(stderr, "%s: %s\n\n%s", g.argv[0], z, zRebuildMsg);
  }
  db_force_rollback();
Changes to src/http.c.
53
54
55
56
57
58
59




60

61
62
63
64
65
66
67
  blob_zero(&nonce);
  blob_zero(&pw);
  sha1sum_blob(pPayload, &nonce);
  blob_copy(&pw, &nonce);
  zLogin = g.urlUser;
  if( g.urlPasswd ){
    zPw = g.urlPasswd;




  }else{

    url_prompt_for_password();
    zPw = g.urlPasswd;
    if( !g.dontKeepUrl ) db_set("last-sync-pw", zPw, 0);
  }

  /* The login card wants the SHA1 hash of the password, so convert the
  ** password to its SHA1 hash it it isn't already a SHA1 hash.







>
>
>
>

>







53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
  blob_zero(&nonce);
  blob_zero(&pw);
  sha1sum_blob(pPayload, &nonce);
  blob_copy(&pw, &nonce);
  zLogin = g.urlUser;
  if( g.urlPasswd ){
    zPw = g.urlPasswd;
  }else if( g.cgiOutput ){
    /* Password failure while doing a sync from the web interface */
    cgi_printf("*** incorrect or missing password for user %h\n", zLogin);
    zPw = 0;
  }else{
    /* Password failure while doing a sync from the command-line interface */
    url_prompt_for_password();
    zPw = g.urlPasswd;
    if( !g.dontKeepUrl ) db_set("last-sync-pw", zPw, 0);
  }

  /* The login card wants the SHA1 hash of the password, so convert the
  ** password to its SHA1 hash it it isn't already a SHA1 hash.
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
      }
    }else if( rc==302 && strncasecmp(zLine, "location:", 9)==0 ){
      int i, j;
      for(i=9; zLine[i] && zLine[i]==' '; i++){}
      if( zLine[i]==0 ) fossil_fatal("malformed redirect: %s", zLine);
      j = strlen(zLine) - 1; 
      if( j>4 && strcmp(&zLine[j-4],"/xfer")==0 ) zLine[j-4] = 0;
      printf("redirect to %s\n", &zLine[i]);
      url_parse(&zLine[i]);
      transport_close();
      http_exchange(pSend, pReply, useLogin);
      return;
    }
  }
  if( rc!=200 ){







|







226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
      }
    }else if( rc==302 && strncasecmp(zLine, "location:", 9)==0 ){
      int i, j;
      for(i=9; zLine[i] && zLine[i]==' '; i++){}
      if( zLine[i]==0 ) fossil_fatal("malformed redirect: %s", zLine);
      j = strlen(zLine) - 1; 
      if( j>4 && strcmp(&zLine[j-4],"/xfer")==0 ) zLine[j-4] = 0;
      fossil_print("redirect to %s\n", &zLine[i]);
      url_parse(&zLine[i]);
      transport_close();
      http_exchange(pSend, pReply, useLogin);
      return;
    }
  }
  if( rc!=200 ){
Changes to src/main.c.
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
  char *zExtra;           /* Extra path information past the webpage name */
  char *zBaseURL;         /* Full text of the URL being served */
  char *zTop;             /* Parent directory of zPath */
  const char *zContentType;  /* The content type of the input HTTP request */
  int iErrPriority;       /* Priority of current error message */
  char *zErrMsg;          /* Text of an error message */
  Blob cgiIn;             /* Input to an xfer www method */
  int cgiPanic;           /* Write error messages to CGI */
  int xferPanic;          /* Write error messages in XFER protocol */
  int fullHttpReply;      /* True for full HTTP reply.  False for CGI reply */
  Th_Interp *interp;      /* The TH1 interpreter */
  FILE *httpIn;           /* Accept HTTP input from here */
  FILE *httpOut;          /* Send HTTP output here */
  int xlinkClusterOnly;   /* Set when cloning.  Only process clusters */
  int fTimeFormat;        /* 1 for UTC.  2 for localtime.  0 not yet selected */







|







76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
  char *zExtra;           /* Extra path information past the webpage name */
  char *zBaseURL;         /* Full text of the URL being served */
  char *zTop;             /* Parent directory of zPath */
  const char *zContentType;  /* The content type of the input HTTP request */
  int iErrPriority;       /* Priority of current error message */
  char *zErrMsg;          /* Text of an error message */
  Blob cgiIn;             /* Input to an xfer www method */
  int cgiOutput;          /* Write error and status messages to CGI */
  int xferPanic;          /* Write error messages in XFER protocol */
  int fullHttpReply;      /* True for full HTTP reply.  False for CGI reply */
  Th_Interp *interp;      /* The TH1 interpreter */
  FILE *httpIn;           /* Accept HTTP input from here */
  FILE *httpOut;          /* Send HTTP output here */
  int xlinkClusterOnly;   /* Set when cloning.  Only process clusters */
  int fTimeFormat;        /* 1 for UTC.  2 for localtime.  0 not yet selected */
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
  char *z;
  va_list ap;
  static int once = 1;
  mainInFatalError = 1;
  va_start(ap, zFormat);
  z = vmprintf(zFormat, ap);
  va_end(ap);
  if( g.cgiPanic && once ){
    once = 0;
    cgi_printf("<p><font color=\"red\">%h</font></p>", z);
    cgi_reply();
  }else{
    fprintf(stderr, "%s: %s\n", g.argv[0], z);
  }
  db_force_rollback();
  exit(1);
}
void fossil_fatal(const char *zFormat, ...){
  char *z;
  va_list ap;
  mainInFatalError = 1;
  va_start(ap, zFormat);
  z = vmprintf(zFormat, ap);
  va_end(ap);
  if( g.cgiPanic ){
    g.cgiPanic = 0;
    cgi_printf("<p><font color=\"red\">%h</font></p>", z);
    cgi_reply();
  }else{
    fprintf(stderr, "%s: %s\n", g.argv[0], z);
  }
  db_force_rollback();
  exit(1);







|
















|
|







276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
  char *z;
  va_list ap;
  static int once = 1;
  mainInFatalError = 1;
  va_start(ap, zFormat);
  z = vmprintf(zFormat, ap);
  va_end(ap);
  if( g.cgiOutput && once ){
    once = 0;
    cgi_printf("<p><font color=\"red\">%h</font></p>", z);
    cgi_reply();
  }else{
    fprintf(stderr, "%s: %s\n", g.argv[0], z);
  }
  db_force_rollback();
  exit(1);
}
void fossil_fatal(const char *zFormat, ...){
  char *z;
  va_list ap;
  mainInFatalError = 1;
  va_start(ap, zFormat);
  z = vmprintf(zFormat, ap);
  va_end(ap);
  if( g.cgiOutput ){
    g.cgiOutput = 0;
    cgi_printf("<p><font color=\"red\">%h</font></p>", z);
    cgi_reply();
  }else{
    fprintf(stderr, "%s: %s\n", g.argv[0], z);
  }
  db_force_rollback();
  exit(1);
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
  char *z;
  va_list ap;
  if( mainInFatalError ) return;
  mainInFatalError = 1;
  va_start(ap, zFormat);
  z = vmprintf(zFormat, ap);
  va_end(ap);
  if( g.cgiPanic ){
    g.cgiPanic = 0;
    cgi_printf("<p><font color=\"red\">%h</font></p>", z);
    cgi_reply();
  }else{
    fprintf(stderr, "%s: %s\n", g.argv[0], z);
  }
  db_force_rollback();
  exit(1);
}


/* Print a warning message */
void fossil_warning(const char *zFormat, ...){
  char *z;
  va_list ap;
  va_start(ap, zFormat);
  z = vmprintf(zFormat, ap);
  va_end(ap);
  if( g.cgiPanic ){
    cgi_printf("<p><font color=\"red\">%h</font></p>", z);
  }else{
    fprintf(stderr, "%s: %s\n", g.argv[0], z);
  }
}

/*







|
|

















|







321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
  char *z;
  va_list ap;
  if( mainInFatalError ) return;
  mainInFatalError = 1;
  va_start(ap, zFormat);
  z = vmprintf(zFormat, ap);
  va_end(ap);
  if( g.cgiOutput ){
    g.cgiOutput = 0;
    cgi_printf("<p><font color=\"red\">%h</font></p>", z);
    cgi_reply();
  }else{
    fprintf(stderr, "%s: %s\n", g.argv[0], z);
  }
  db_force_rollback();
  exit(1);
}


/* Print a warning message */
void fossil_warning(const char *zFormat, ...){
  char *z;
  va_list ap;
  va_start(ap, zFormat);
  z = vmprintf(zFormat, ap);
  va_end(ap);
  if( g.cgiOutput ){
    cgi_printf("<p><font color=\"red\">%h</font></p>", z);
  }else{
    fprintf(stderr, "%s: %s\n", g.argv[0], z);
  }
}

/*
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
  setmode(_fileno(g.httpIn), _O_BINARY);
#endif
#ifdef __EMX__
  /* Similar hack for OS/2 */
  setmode(fileno(g.httpOut), O_BINARY);
  setmode(fileno(g.httpIn), O_BINARY);
#endif
  g.cgiPanic = 1;
  blob_read_from_file(&config, zFile);
  while( blob_line(&config, &line) ){
    if( !blob_token(&line, &key) ) continue;
    if( blob_buffer(&key)[0]=='#' ) continue;
    if( blob_eq(&key, "debug:") && blob_token(&line, &value) ){
      g.fDebug = fopen(blob_str(&value), "a");
      blob_reset(&value);







|







809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
  setmode(_fileno(g.httpIn), _O_BINARY);
#endif
#ifdef __EMX__
  /* Similar hack for OS/2 */
  setmode(fileno(g.httpOut), O_BINARY);
  setmode(fileno(g.httpIn), O_BINARY);
#endif
  g.cgiOutput = 1;
  blob_read_from_file(&config, zFile);
  while( blob_line(&config, &line) ){
    if( !blob_token(&line, &key) ) continue;
    if( blob_buffer(&key)[0]=='#' ) continue;
    if( blob_eq(&key, "debug:") && blob_token(&line, &value) ){
      g.fDebug = fopen(blob_str(&value), "a");
      blob_reset(&value);
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
void cmd_http(void){
  const char *zIpAddr;
  const char *zNotFound;
  zNotFound = find_option("notfound", 0, 1);
  if( g.argc!=2 && g.argc!=3 && g.argc!=6 ){
    cgi_panic("no repository specified");
  }
  g.cgiPanic = 1;
  g.fullHttpReply = 1;
  if( g.argc==6 ){
    g.httpIn = fopen(g.argv[3], "rb");
    g.httpOut = fopen(g.argv[4], "wb");
    zIpAddr = g.argv[5];
  }else{
    g.httpIn = stdin;







|







907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
void cmd_http(void){
  const char *zIpAddr;
  const char *zNotFound;
  zNotFound = find_option("notfound", 0, 1);
  if( g.argc!=2 && g.argc!=3 && g.argc!=6 ){
    cgi_panic("no repository specified");
  }
  g.cgiOutput = 1;
  g.fullHttpReply = 1;
  if( g.argc==6 ){
    g.httpIn = fopen(g.argv[3], "rb");
    g.httpOut = fopen(g.argv[4], "wb");
    zIpAddr = g.argv[5];
  }else{
    g.httpIn = stdin;
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
    fossil_fatal("unable to listen on TCP socket %d", iPort);
  }
  g.httpIn = stdin;
  g.httpOut = stdout;
  if( g.fHttpTrace || g.fSqlTrace ){
    fprintf(stderr, "====== SERVER pid %d =======\n", getpid());
  }
  g.cgiPanic = 1;
  find_server_repository(isUiCmd);
  g.zRepositoryName = enter_chroot_jail(g.zRepositoryName);
  cgi_handle_http_request(0);
  process_one_web_page(zNotFound);
#else
  /* Win32 implementation */
  if( isUiCmd ){







|







1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
    fossil_fatal("unable to listen on TCP socket %d", iPort);
  }
  g.httpIn = stdin;
  g.httpOut = stdout;
  if( g.fHttpTrace || g.fSqlTrace ){
    fprintf(stderr, "====== SERVER pid %d =======\n", getpid());
  }
  g.cgiOutput = 1;
  find_server_repository(isUiCmd);
  g.zRepositoryName = enter_chroot_jail(g.zRepositoryName);
  cgi_handle_http_request(0);
  process_one_web_page(zNotFound);
#else
  /* Win32 implementation */
  if( isUiCmd ){
Changes to src/printf.c.
802
803
804
805
806
807
808















  g.iErrPriority = iPriority;
}
void fossil_error_reset(void){
  free(g.zErrMsg);
  g.zErrMsg = 0;
  g.iErrPriority = 0;
}






















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
  g.iErrPriority = iPriority;
}
void fossil_error_reset(void){
  free(g.zErrMsg);
  g.zErrMsg = 0;
  g.iErrPriority = 0;
}

/*
** Write output for user consumption.  If g.cgiOutput is enabled, then
** send the output as part of the CGI reply.  If g.cgiOutput is false,
** then write on standard output.
*/
void fossil_print(const char *zFormat, ...){
  va_list ap;
  va_start(ap, zFormat);
  if( g.cgiOutput ){
    cgi_vprintf(zFormat, ap);
  }else{
    vprintf(zFormat, ap);
  }
}
Changes to src/style.c.
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
    Th_Store("login", g.zLogin);
  }
  if( g.thTrace ) Th_Trace("BEGIN_HEADER_SCRIPT<br />\n", -1);
  Th_Render(zHeader);
  if( g.thTrace ) Th_Trace("END_HEADER<br />\n", -1);
  Th_Unstore("title");   /* Avoid collisions with ticket field names */
  cgi_destination(CGI_BODY);
  g.cgiPanic = 1;
  headerHasBeenGenerated = 1;
}

/*
** Draw the footer at the bottom of the page.
*/
void style_footer(void){







|







108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
    Th_Store("login", g.zLogin);
  }
  if( g.thTrace ) Th_Trace("BEGIN_HEADER_SCRIPT<br />\n", -1);
  Th_Render(zHeader);
  if( g.thTrace ) Th_Trace("END_HEADER<br />\n", -1);
  Th_Unstore("title");   /* Avoid collisions with ticket field names */
  cgi_destination(CGI_BODY);
  g.cgiOutput = 1;
  headerHasBeenGenerated = 1;
}

/*
** Draw the footer at the bottom of the page.
*/
void style_footer(void){
Changes to src/th_main.c.
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
static void sendText(const char *z, int n, int encode){
  if( enableOutput && n ){
    if( n<0 ) n = strlen(z);
    if( encode ){
      z = htmlize(z, n);
      n = strlen(z);
    }
    if( g.cgiPanic ){
      cgi_append_content(z, n);
    }else{
      fwrite(z, 1, n, stdout);
    }
    if( encode ) free((char*)z);
  }
}







|







93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
static void sendText(const char *z, int n, int encode){
  if( enableOutput && n ){
    if( n<0 ) n = strlen(z);
    if( encode ){
      z = htmlize(z, n);
      n = strlen(z);
    }
    if( g.cgiOutput ){
      cgi_append_content(z, n);
    }else{
      fwrite(z, 1, n, stdout);
    }
    if( encode ) free((char*)z);
  }
}
Changes to src/xfer.c.
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
    nCardSent++;
  }
  if( pushFlag ){
    blob_appendf(&send, "push %s %s\n", zSCode, zPCode);
    nCardSent++;
  }
  manifest_crosslink_begin();
  printf(zLabelFormat, "", "Bytes", "Cards", "Artifacts", "Deltas");

  while( go ){
    int newPhantom = 0;
    char *zRandomness;

    /* Send make the most recently received cookie.  Let the server
    ** figure out if this is a cookie that it cares about.







|







990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
    nCardSent++;
  }
  if( pushFlag ){
    blob_appendf(&send, "push %s %s\n", zSCode, zPCode);
    nCardSent++;
  }
  manifest_crosslink_begin();
  fossil_print(zLabelFormat, "", "Bytes", "Cards", "Artifacts", "Deltas");

  while( go ){
    int newPhantom = 0;
    char *zRandomness;

    /* Send make the most recently received cookie.  Let the server
    ** figure out if this is a cookie that it cares about.
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
    */
    zRandomness = db_text(0, "SELECT hex(randomblob(20))");
    blob_appendf(&send, "# %s\n", zRandomness);
    free(zRandomness);

    /* Exchange messages with the server */
    nFileSend = xfer.nFileSent + xfer.nDeltaSent;
    printf(zValueFormat, "Send:",
            blob_size(&send), nCardSent+xfer.nGimmeSent+xfer.nIGotSent,
            xfer.nFileSent, xfer.nDeltaSent);
    nCardSent = 0;
    nCardRcvd = 0;
    xfer.nFileSent = 0;
    xfer.nDeltaSent = 0;
    xfer.nGimmeSent = 0;
    xfer.nIGotSent = 0;
    fflush(stdout);







|
|
|







1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
    */
    zRandomness = db_text(0, "SELECT hex(randomblob(20))");
    blob_appendf(&send, "# %s\n", zRandomness);
    free(zRandomness);

    /* Exchange messages with the server */
    nFileSend = xfer.nFileSent + xfer.nDeltaSent;
    fossil_print(zValueFormat, "Send:",
                 blob_size(&send), nCardSent+xfer.nGimmeSent+xfer.nIGotSent,
                 xfer.nFileSent, xfer.nDeltaSent);
    nCardSent = 0;
    nCardRcvd = 0;
    xfer.nFileSent = 0;
    xfer.nDeltaSent = 0;
    xfer.nGimmeSent = 0;
    xfer.nIGotSent = 0;
    fflush(stdout);
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
    /* Process the reply that came back from the server */
    while( blob_line(&recv, &xfer.line) ){
      if( blob_buffer(&xfer.line)[0]=='#' ){
        continue;
      }
      xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken));
      nCardRcvd++;
      if (!g.fQuiet) {
        printf("\r%d", nCardRcvd);
        fflush(stdout);
      }

      /*   file UUID SIZE \n CONTENT
      **   file UUID DELTASRC SIZE \n CONTENT
      **







|







1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
    /* Process the reply that came back from the server */
    while( blob_line(&recv, &xfer.line) ){
      if( blob_buffer(&xfer.line)[0]=='#' ){
        continue;
      }
      xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken));
      nCardRcvd++;
      if( !g.cgiOutput && !g.fQuiet ){
        printf("\r%d", nCardRcvd);
        fflush(stdout);
      }

      /*   file UUID SIZE \n CONTENT
      **   file UUID DELTASRC SIZE \n CONTENT
      **
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
      **
      ** If the "login failed" message is seen, clear the sync password prior
      ** to the next cycle.
      */        
      if( blob_eq(&xfer.aToken[0],"message") && xfer.nToken==2 ){
        char *zMsg = blob_terminate(&xfer.aToken[1]);
        defossilize(zMsg);
        if( zMsg ) printf("\rServer says: %s\n", zMsg);
      }else

      /*   error MESSAGE
      **
      ** Report an error and abandon the sync session.
      **
      ** Except, when cloning we will sometimes get an error on the







|







1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
      **
      ** If the "login failed" message is seen, clear the sync password prior
      ** to the next cycle.
      */        
      if( blob_eq(&xfer.aToken[0],"message") && xfer.nToken==2 ){
        char *zMsg = blob_terminate(&xfer.aToken[1]);
        defossilize(zMsg);
        if( zMsg ) fossil_print("\rServer says: %s\n", zMsg);
      }else

      /*   error MESSAGE
      **
      ** Report an error and abandon the sync session.
      **
      ** Except, when cloning we will sometimes get an error on the
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
      blob_reset(&xfer.line);
    }
    if( origConfigRcvMask & (CONFIGSET_TKT|CONFIGSET_USER) ){
      configure_finalize_receive();
    }
    origConfigRcvMask = 0;
    if( nCardRcvd>0 ){
      printf(zValueFormat, "Received:",
              blob_size(&recv), nCardRcvd,
              xfer.nFileRcvd, xfer.nDeltaRcvd + xfer.nDanglingFile);
    }
    blob_reset(&recv);
    nCycle++;

    /* If we received one or more files on the previous exchange but
    ** there are still phantoms, then go another round.
    */







|
|
|







1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
      blob_reset(&xfer.line);
    }
    if( origConfigRcvMask & (CONFIGSET_TKT|CONFIGSET_USER) ){
      configure_finalize_receive();
    }
    origConfigRcvMask = 0;
    if( nCardRcvd>0 ){
      fossil_print(zValueFormat, "Received:",
                   blob_size(&recv), nCardRcvd,
                   xfer.nFileRcvd, xfer.nDeltaRcvd + xfer.nDanglingFile);
    }
    blob_reset(&recv);
    nCycle++;

    /* If we received one or more files on the previous exchange but
    ** there are still phantoms, then go another round.
    */
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
      go = 1;
    }

    /* If this is a clone, the go at least two rounds */
    if( cloneFlag && nCycle==1 ) go = 1;
  };
  transport_stats(&nSent, &nRcvd, 1);
  printf("Total network traffic: %d bytes sent, %d bytes received\n",
         nSent, nRcvd);
  transport_close();
  transport_global_shutdown();
  db_multi_exec("DROP TABLE onremote");
  manifest_crosslink_end();
  db_end_transaction(0);
}







|
|






1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
      go = 1;
    }

    /* If this is a clone, the go at least two rounds */
    if( cloneFlag && nCycle==1 ) go = 1;
  };
  transport_stats(&nSent, &nRcvd, 1);
  fossil_print("Total network traffic: %d bytes sent, %d bytes received\n",
               nSent, nRcvd);
  transport_close();
  transport_global_shutdown();
  db_multi_exec("DROP TABLE onremote");
  manifest_crosslink_end();
  db_end_transaction(0);
}