Fossil

Check-in [59002d5e]
Login

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

Overview
Comment:Factor the sync password out of the last-sync-url configuration setting. Store the password separately. Prompt the user for the password if it is missing.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | experimental
Files: files | file ages | folders
SHA1: 59002d5e35918d83a54b07c9a3982467afa35339
User & Date: drh 2010-01-21 18:13:33
Context
2010-01-21
19:51
Better reporting of failed logins by the server back to the client. check-in: b030521c user: drh tags: experimental
18:13
Factor the sync password out of the last-sync-url configuration setting. Store the password separately. Prompt the user for the password if it is missing. check-in: 59002d5e user: drh tags: experimental
2010-01-20
21:51
Fix a bug in file change detection introduced by check-in [d7a583e697]. Don't use that check-in, nor [30f23e3f5c]. check-in: 1abc8a94 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/configure.c.

443
444
445
446
447
448
449

450
451
452
453
454
455
456


457
458
459
460
461

462
463

464
465
466
467
468
469
470
    db_multi_exec("%s", blob_str(&in));
    configure_finalize_receive();
    db_end_transaction(0);
  }else
  if( strncmp(zMethod, "pull", n)==0 || strncmp(zMethod, "push", n)==0 ){
    int mask;
    const char *zServer;

    url_proxy_options();
    if( g.argc!=4 && g.argc!=5 ){
      usage("pull AREA ?URL?");
    }
    mask = find_area(g.argv[3]);
    if( g.argc==5 ){
      zServer = g.argv[4];


    }else{
      zServer = db_get("last-sync-url", 0);
      if( zServer==0 ){
        fossil_fatal("no server specified");
      }

    }
    url_parse(zServer);

    user_select();
    if( strncmp(zMethod, "push", n)==0 ){
      client_sync(0,0,0,0,mask);
    }else{
      client_sync(0,0,0,mask,0);
    }
  }else







>







>
>





>


>







443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
    db_multi_exec("%s", blob_str(&in));
    configure_finalize_receive();
    db_end_transaction(0);
  }else
  if( strncmp(zMethod, "pull", n)==0 || strncmp(zMethod, "push", n)==0 ){
    int mask;
    const char *zServer;
    const char *zPw;
    url_proxy_options();
    if( g.argc!=4 && g.argc!=5 ){
      usage("pull AREA ?URL?");
    }
    mask = find_area(g.argv[3]);
    if( g.argc==5 ){
      zServer = g.argv[4];
      zPw = 0;
      g.dontKeepUrl = 1;
    }else{
      zServer = db_get("last-sync-url", 0);
      if( zServer==0 ){
        fossil_fatal("no server specified");
      }
      zPw = db_get("last-sync-pw", 0);
    }
    url_parse(zServer);
    if( g.urlPasswd==0 && zPw ) g.urlPasswd = mprintf("%s", zPw);
    user_select();
    if( strncmp(zMethod, "push", n)==0 ){
      client_sync(0,0,0,0,mask);
    }else{
      client_sync(0,0,0,mask,0);
    }
  }else

Changes to src/http.c.

42
43
44
45
46
47
48




49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

67
68
69
70
71
72
73
74
75
76
77
78
static void http_build_login_card(Blob *pPayload, Blob *pLogin){
  Blob nonce;          /* The nonce */
  const char *zLogin;  /* The user login name */
  const char *zPw;     /* The user password */
  Blob pw;             /* The nonce with user password appended */
  Blob sig;            /* The signature field */





  blob_zero(&nonce);
  blob_zero(&pw);
  sha1sum_blob(pPayload, &nonce);
  blob_copy(&pw, &nonce);
  blob_zero(pLogin);
  if( g.urlUser==0 ){
    user_select();
    zPw = db_text("", "SELECT pw FROM user WHERE uid=%d", g.userUid);
    zLogin = g.zLogin;
  }else{
    if( g.urlPasswd==0 ){
      if( strcmp(g.urlUser,"anonymous")!=0 ){
        char *zPrompt = mprintf("password for %s: ", g.urlUser);
        Blob x;
        prompt_for_password(zPrompt, &x, 0);
        free(zPrompt);
        g.urlPasswd = blob_str(&x);
      }else{

        g.urlPasswd = "";
      }
    }
    zPw = g.urlPasswd;
    zLogin = g.urlUser;
  }

  /* 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.
  **
  ** Except, if the password begins with "*" then use the characters
  ** after the "*" as a cleartext password.  Put an "*" at the beginning







>
>
>
>




|
|
|
<
<

<
<
|
|
|
|
|
<
>
|
<
<
<
<







42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59


60


61
62
63
64
65

66
67




68
69
70
71
72
73
74
static void http_build_login_card(Blob *pPayload, Blob *pLogin){
  Blob nonce;          /* The nonce */
  const char *zLogin;  /* The user login name */
  const char *zPw;     /* The user password */
  Blob pw;             /* The nonce with user password appended */
  Blob sig;            /* The signature field */

  blob_zero(pLogin);
  if( g.urlUser==0 || strcmp(g.urlUser, "anonymous")==0 ){
     return;  /* If no login card for users "nobody" and "anonymous" */
  }
  blob_zero(&nonce);
  blob_zero(&pw);
  sha1sum_blob(pPayload, &nonce);
  blob_copy(&pw, &nonce);
  zLogin = g.urlUser;
  if( g.urlPasswd ){
    zPw = g.urlPasswd;


  }else{


    char *zPrompt = mprintf("password for %s: ", g.urlUser);
    Blob x;
    prompt_for_password(zPrompt, &x, 0);
    free(zPrompt);
    zPw = blob_str(&x);

    if( !g.dontKeepUrl ) db_set("last-sync-pw", zPw, 0);
    g.urlPasswd = mprintf("%s", zPw);




  }

  /* 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.
  **
  ** Except, if the password begins with "*" then use the characters
  ** after the "*" as a cleartext password.  Put an "*" at the beginning

Changes to src/main.c.

99
100
101
102
103
104
105

106
107
108
109
110
111
112
  int urlPort;            /* TCP port number for http: or https: */
  int urlDfltPort;        /* The default port for the given protocol */
  char *urlPath;          /* Pathname for http: */
  char *urlUser;          /* User id for http: */
  char *urlPasswd;        /* Password for http: */
  char *urlCanonical;     /* Canonical representation of the URL */
  char *urlProxyAuth;     /* Proxy-Authorizer: string */


  const char *zLogin;     /* Login name.  "" if not logged in. */
  int noPswd;             /* Logged in without password (on 127.0.0.1) */
  int userUid;            /* Integer user id */

  /* Information used to populate the RCVFROM table */
  int rcvid;              /* The rcvid.  0 if not yet defined. */







>







99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
  int urlPort;            /* TCP port number for http: or https: */
  int urlDfltPort;        /* The default port for the given protocol */
  char *urlPath;          /* Pathname for http: */
  char *urlUser;          /* User id for http: */
  char *urlPasswd;        /* Password for http: */
  char *urlCanonical;     /* Canonical representation of the URL */
  char *urlProxyAuth;     /* Proxy-Authorizer: string */
  int dontKeepUrl;        /* Do not persist the URL */

  const char *zLogin;     /* Login name.  "" if not logged in. */
  int noPswd;             /* Logged in without password (on 127.0.0.1) */
  int userUid;            /* Integer user id */

  /* Information used to populate the RCVFROM table */
  int rcvid;              /* The rcvid.  0 if not yet defined. */

Changes to src/sync.c.

77
78
79
80
81
82
83

84
85
86
87
88
89

90
91
92
93
94
95
96
97
98
99




100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
...
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218

219
220











221





222
223
224
225
226
227
228
229
230
231
232
233
234

** This routine processes the command-line argument for push, pull,
** and sync.  If a command-line argument is given, that is the URL
** of a server to sync against.  If no argument is given, use the
** most recently synced URL.  Remember the current URL for next time.
*/
void process_sync_args(void){
  const char *zUrl = 0;

  int urlOptional = find_option("autourl",0,0)!=0;
  int dontKeepUrl = find_option("once",0,0)!=0;
  url_proxy_options();
  db_find_and_open_repository(1);
  if( g.argc==2 ){
    zUrl = db_get("last-sync-url", 0);

  }else if( g.argc==3 ){
    zUrl = g.argv[2];
  }
  if( zUrl==0 ){
    if( urlOptional ) exit(0);
    usage("URL");
  }
  url_parse(zUrl);
  if( !dontKeepUrl ){
    db_set("last-sync-url", g.urlIsFile ? g.urlCanonical : zUrl, 0);




  }
  user_select();
  if( g.argc==2 ){
    if( g.urlPort!=g.urlDfltPort ){
      printf("Server:    %s://%s:%d%s\n",
              g.urlProtocol, g.urlName, g.urlPort, g.urlPath);
    }else{
      printf("Server:    %s://%s%s\n", g.urlProtocol, g.urlName, g.urlPath);
    }
  }
  url_enable_proxy("via proxy: ");
}

/*
** COMMAND: pull
**
................................................................................
  process_sync_args();
  client_sync(1,1,0,0,0);
}

/*
** COMMAND: remote-url
**
** Usage: %fossil remote-url ?URL|off? --show-pw
**
** Query and/or change the default server URL used by the "pull", "push",
** and "sync" commands.
**
** The userid and password are of the URL are not printed unless
** the --show-pw option is used on the command-line.
**
** The remote-url is set automatically by a "clone" command or by any
** "sync", "push", or "pull" command that specifies an explicit URL.
** The default remote-url is used by auto-syncing and by "sync", "push",
** "pull" that omit the server URL.
**
** See also: clone, push, pull, sync
*/
void remote_url_cmd(void){
  char *zUrl;
  int showPw = find_option("show-pw",0,0)!=0;
  db_find_and_open_repository(1);
  if( g.argc!=2 && g.argc!=3 ){
    usage("remote-url ?URL|off?");
  }
  if( g.argc==3 ){
    if( strcmp(g.argv[2],"off")==0 ){
      db_unset("last-sync-url", 0);

    }else{
      url_parse(g.argv[2]);











      db_set("last-sync-url", g.urlIsFile ? g.urlCanonical : g.argv[2], 0);





    }
  }
  zUrl = db_get("last-sync-url", 0);
  if( zUrl==0 ){
    printf("off\n");
    return;
  }else if( showPw ){
    g.urlCanonical = zUrl;
  }else{
    url_parse(zUrl);
  }
  printf("%s\n", g.urlCanonical);
}








>

|




>








|
|
>
>
>
>



<
|
<
<
<
<







 







|




<
<
<









|







>


>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>






<
<


<
|
|
>
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108

109




110
111
112
113
114
115
116
...
188
189
190
191
192
193
194
195
196
197
198
199



200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242


243
244

245
246
247
** This routine processes the command-line argument for push, pull,
** and sync.  If a command-line argument is given, that is the URL
** of a server to sync against.  If no argument is given, use the
** most recently synced URL.  Remember the current URL for next time.
*/
void process_sync_args(void){
  const char *zUrl = 0;
  const char *zPw = 0;
  int urlOptional = find_option("autourl",0,0)!=0;
  g.dontKeepUrl = find_option("once",0,0)!=0;
  url_proxy_options();
  db_find_and_open_repository(1);
  if( g.argc==2 ){
    zUrl = db_get("last-sync-url", 0);
    zPw = db_get("last-sync-pw", 0);
  }else if( g.argc==3 ){
    zUrl = g.argv[2];
  }
  if( zUrl==0 ){
    if( urlOptional ) exit(0);
    usage("URL");
  }
  url_parse(zUrl);
  if( !g.dontKeepUrl ){
    db_set("last-sync-url", g.urlCanonical, 0);
    if( g.urlPasswd ) db_set("last-sync-pw", g.urlPasswd, 0);
  }
  if( g.urlUser!=0 && g.urlPasswd==0 ){
    g.urlPasswd = mprintf("%s", zPw);
  }
  user_select();
  if( g.argc==2 ){

    printf("Server:    %s\n", g.urlCanonical);




  }
  url_enable_proxy("via proxy: ");
}

/*
** COMMAND: pull
**
................................................................................
  process_sync_args();
  client_sync(1,1,0,0,0);
}

/*
** COMMAND: remote-url
**
** Usage: %fossil remote-url ?URL|off?  ?--password PASSWORD?
**
** Query and/or change the default server URL used by the "pull", "push",
** and "sync" commands.
**



** The remote-url is set automatically by a "clone" command or by any
** "sync", "push", or "pull" command that specifies an explicit URL.
** The default remote-url is used by auto-syncing and by "sync", "push",
** "pull" that omit the server URL.
**
** See also: clone, push, pull, sync
*/
void remote_url_cmd(void){
  char *zUrl;
  const char *zPw = find_option("password", 0, 1);
  db_find_and_open_repository(1);
  if( g.argc!=2 && g.argc!=3 ){
    usage("remote-url ?URL|off?");
  }
  if( g.argc==3 ){
    if( strcmp(g.argv[2],"off")==0 ){
      db_unset("last-sync-url", 0);
      db_unset("last-sync-pw", 0);
    }else{
      url_parse(g.argv[2]);
      if( g.urlUser && g.urlPasswd==0 ){
        if( zPw ){
          g.urlPasswd = mprintf("%s", zPw);
        }else{
          char *zPrompt = mprintf("password for %s: ", g.urlUser);
          Blob x;
          prompt_for_password(zPrompt, &x, 0);
          free(zPrompt);
          g.urlPasswd = blob_str(&x);
        }
      }
      db_set("last-sync-url", g.urlCanonical, 0);
      if( g.urlPasswd ){
        db_set("last-sync-pw", g.urlPasswd, 0);
      }else{
        db_unset("last-sync-pw", 0);
      }
    }
  }
  zUrl = db_get("last-sync-url", 0);
  if( zUrl==0 ){
    printf("off\n");
    return;


  }else{
    url_parse(zUrl);

    printf("%s\n", g.urlCanonical);
  }
}

Changes to src/url.c.

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

54
55
56
57
58
59
60
..
71
72
73
74
75
76
77

78
79
80

81
82
83
84
85
86
87
..
92
93
94
95
96
97
98
99

100

101
102

103

104

105
106
107
108
109
110
111
**      g.urlName        Hostname for HTTP: or HTTPS:.  Filename for FILE:
**      g.urlPort        TCP port number for HTTP or HTTPS.
**      g.urlDfltPort    Default TCP port number (80 or 443).
**      g.urlPath        Path name for HTTP or HTTPS.
**      g.urlUser        Userid.
**      g.urlPasswd      Password.
**      g.urlHostname    HOST:PORT or just HOST if port is the default.
**      g.urlCanonical   The URL in canonical form, omitting userid/password
**
** HTTP url format is:
**
**     http://userid:password@host:port/path?query#fragment
**
*/
void url_parse(const char *zUrl){
  int i, j, c;
  char *zFile = 0;
  if( strncmp(zUrl, "http://", 7)==0 || strncmp(zUrl, "https://", 8)==0 ){
    int iStart;

    g.urlIsFile = 0;
    if( zUrl[4]=='s' ){
      g.urlIsHttps = 1;
      g.urlProtocol = "https";
      g.urlDfltPort = 443;
      iStart = 8;
    }else{
................................................................................
      if( j<i ){
        g.urlPasswd = mprintf("%.*s", i-j-1, &zUrl[j+1]);
        dehttpize(g.urlPasswd);
      }
      for(j=i+1; (c=zUrl[j])!=0 && c!='/' && c!=':'; j++){}
      g.urlName = mprintf("%.*s", j-i-1, &zUrl[i+1]);
      i = j;

    }else{
      for(i=iStart; (c=zUrl[i])!=0 && c!='/' && c!=':'; i++){}
      g.urlName = mprintf("%.*s", i-iStart, &zUrl[iStart]);

    }
    for(j=0; g.urlName[j]; j++){ g.urlName[j] = tolower(g.urlName[j]); }
    if( c==':' ){
      g.urlPort = 0;
      i++;
      while( (c = zUrl[i])!=0 && isdigit(c) ){
        g.urlPort = g.urlPort*10 + c - '0';
................................................................................
      g.urlPort = g.urlDfltPort;
      g.urlHostname = g.urlName;
    }
    g.urlPath = mprintf(&zUrl[i]);
    dehttpize(g.urlName);
    dehttpize(g.urlPath);
    if( g.urlDfltPort==g.urlPort ){
      g.urlCanonical = mprintf("%s://%T%T",

                               g.urlProtocol, g.urlName, g.urlPath);

    }else{
      g.urlCanonical = mprintf("%s://%T:%d%T",

                               g.urlProtocol, g.urlName, g.urlPort, g.urlPath);

    }

  }else if( strncmp(zUrl, "file:", 5)==0 ){
    g.urlIsFile = 1;
    if( zUrl[5]=='/' && zUrl[6]=='/' ){
      i = 7;
    }else{
      i = 5;
    }







|











>







 







>



>







 







|
>
|
>

|
>
|
>

>







35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
..
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
..
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
**      g.urlName        Hostname for HTTP: or HTTPS:.  Filename for FILE:
**      g.urlPort        TCP port number for HTTP or HTTPS.
**      g.urlDfltPort    Default TCP port number (80 or 443).
**      g.urlPath        Path name for HTTP or HTTPS.
**      g.urlUser        Userid.
**      g.urlPasswd      Password.
**      g.urlHostname    HOST:PORT or just HOST if port is the default.
**      g.urlCanonical   The URL in canonical form, omitting password
**
** HTTP url format is:
**
**     http://userid:password@host:port/path?query#fragment
**
*/
void url_parse(const char *zUrl){
  int i, j, c;
  char *zFile = 0;
  if( strncmp(zUrl, "http://", 7)==0 || strncmp(zUrl, "https://", 8)==0 ){
    int iStart;
    char *zLogin;
    g.urlIsFile = 0;
    if( zUrl[4]=='s' ){
      g.urlIsHttps = 1;
      g.urlProtocol = "https";
      g.urlDfltPort = 443;
      iStart = 8;
    }else{
................................................................................
      if( j<i ){
        g.urlPasswd = mprintf("%.*s", i-j-1, &zUrl[j+1]);
        dehttpize(g.urlPasswd);
      }
      for(j=i+1; (c=zUrl[j])!=0 && c!='/' && c!=':'; j++){}
      g.urlName = mprintf("%.*s", j-i-1, &zUrl[i+1]);
      i = j;
      zLogin = mprintf("%t@", g.urlUser);
    }else{
      for(i=iStart; (c=zUrl[i])!=0 && c!='/' && c!=':'; i++){}
      g.urlName = mprintf("%.*s", i-iStart, &zUrl[iStart]);
      zLogin = mprintf("");
    }
    for(j=0; g.urlName[j]; j++){ g.urlName[j] = tolower(g.urlName[j]); }
    if( c==':' ){
      g.urlPort = 0;
      i++;
      while( (c = zUrl[i])!=0 && isdigit(c) ){
        g.urlPort = g.urlPort*10 + c - '0';
................................................................................
      g.urlPort = g.urlDfltPort;
      g.urlHostname = g.urlName;
    }
    g.urlPath = mprintf(&zUrl[i]);
    dehttpize(g.urlName);
    dehttpize(g.urlPath);
    if( g.urlDfltPort==g.urlPort ){
      g.urlCanonical = mprintf(
        "%s://%s%T%T", 
        g.urlProtocol, zLogin, g.urlName, g.urlPath
      );
    }else{
      g.urlCanonical = mprintf(
        "%s://%s%T:%d%T",
        g.urlProtocol, zLogin, g.urlName, g.urlPort, g.urlPath
      );
    }
    free(zLogin);
  }else if( strncmp(zUrl, "file:", 5)==0 ){
    g.urlIsFile = 1;
    if( zUrl[5]=='/' && zUrl[6]=='/' ){
      i = 7;
    }else{
      i = 5;
    }

Changes to src/xfer.c.

430
431
432
433
434
435
436


437
438
439
440
441
442
443
....
1206
1207
1208
1209
1210
1211
1212
1213



1214
1215
1216
1217








1218
1219
1220
1221
1222
1223
1224
1225
      login_set_capabilities(zCap);
      g.userUid = db_column_int(&q, 2);
      g.zLogin = mprintf("%b", pLogin);
      g.zNonce = mprintf("%b", pNonce);
      if( g.fHttpTrace ){
        fprintf(stderr, "# login [%s] with capabilities [%s]\n", g.zLogin,zCap);
      }


    }
  }
  db_finalize(&q);

  if( rc==0 ){
    /* If the login was successful. */
    login_set_anon_nobody_capabilities();
................................................................................
      */
      if( blob_eq(&xfer.aToken[0], "cookie") && xfer.nToken==2 ){
        db_set("cookie", blob_str(&xfer.aToken[1]), 0);
      }else

      /*   message MESSAGE
      **
      ** Print a message.  Similar to "error" but does not stop processing



      */        
      if( blob_eq(&xfer.aToken[0],"message") && xfer.nToken==2 ){
        char *zMsg = blob_terminate(&xfer.aToken[1]);
        defossilize(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







>
>







 







|
>
>
>




>
>
>
>
>
>
>
>
|







430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
....
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
      login_set_capabilities(zCap);
      g.userUid = db_column_int(&q, 2);
      g.zLogin = mprintf("%b", pLogin);
      g.zNonce = mprintf("%b", pNonce);
      if( g.fHttpTrace ){
        fprintf(stderr, "# login [%s] with capabilities [%s]\n", g.zLogin,zCap);
      }
    }else{
      @ message login\sfailed
    }
  }
  db_finalize(&q);

  if( rc==0 ){
    /* If the login was successful. */
    login_set_anon_nobody_capabilities();
................................................................................
      */
      if( blob_eq(&xfer.aToken[0], "cookie") && xfer.nToken==2 ){
        db_set("cookie", blob_str(&xfer.aToken[1]), 0);
      }else

      /*   message MESSAGE
      **
      ** Print a message.  Similar to "error" but does not stop processing.
      **
      ** 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( strcmp(zMsg, "login failed")==0 ){
          if( cloneFlag && nCycle==0 ){
            zMsg = 0;
          }else{
            if( !g.dontKeepUrl ) db_unset("last-sync-pw", 0);
            g.urlPasswd = 0;
          }
        }
        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