Fossil SCM

Use POST instead of GET for the /xfer method. Other bug fixes in the URL parser.

drh 2007-07-30 14:28 trunk
Commit e621b6dbe310661d111e8caba43bdac40fd9693b
+20 -5
--- src/http.c
+++ src/http.c
@@ -157,19 +157,34 @@
157157
Blob login, nonce, sig, pw, payload, hdr;
158158
const char *zSep;
159159
int i;
160160
int cnt = 0;
161161
162
- user_select();
163162
blob_zero(&nonce);
164163
blob_zero(&pw);
165164
db_blob(&nonce, "SELECT hex(randomblob(20))");
166165
blob_copy(&pw, &nonce);
167
- db_blob(&pw, "SELECT pw FROM user WHERE uid=%d", g.userUid);
168
- sha1sum_blob(&pw, &sig);
169166
blob_zero(&login);
170
- blob_appendf(&login, "login %s %b %b\n", g.zLogin, &nonce, &sig);
167
+ if( g.urlUser==0 ){
168
+ user_select();
169
+ db_blob(&pw, "SELECT pw FROM user WHERE uid=%d", g.userUid);
170
+ sha1sum_blob(&pw, &sig);
171
+ blob_appendf(&login, "login %s %b %b\n", g.zLogin, &nonce, &sig);
172
+ }else{
173
+ if( g.urlPasswd==0 ){
174
+ if( strcmp(g.urlUser,"anonymous")!=0 ){
175
+ char *zPrompt = mprintf("password for %s", g.urlUser);
176
+ Blob x;
177
+ prompt_for_password(zPrompt, &x, 0);
178
+ free(zPrompt);
179
+ blob_append(&pw, blob_buffer(&x), blob_size(&x));
180
+ blob_reset(&x);
181
+ }
182
+ }
183
+ sha1sum_blob(&pw, &sig);
184
+ blob_appendf(&login, "login %s %b %b\n", g.urlUser, &nonce, &sig);
185
+ }
171186
blob_reset(&nonce);
172187
blob_reset(&pw);
173188
blob_reset(&sig);
174189
if( g.fHttpTrace ){
175190
payload = login;
@@ -183,11 +198,11 @@
183198
if( i>0 && g.urlPath[i-1]=='/' ){
184199
zSep = "";
185200
}else{
186201
zSep = "/";
187202
}
188
- blob_appendf(&hdr, "GET %s%sxfer HTTP/1.1\r\n", g.urlPath, zSep);
203
+ blob_appendf(&hdr, "POST %s%sxfer HTTP/1.1\r\n", g.urlPath, zSep);
189204
if( g.fHttpTrace ){
190205
blob_appendf(&hdr, "Content-Type: application/x-fossil-debug\r\n");
191206
}else{
192207
blob_appendf(&hdr, "Content-Type: application/x-fossil\r\n");
193208
}
194209
--- src/http.c
+++ src/http.c
@@ -157,19 +157,34 @@
157 Blob login, nonce, sig, pw, payload, hdr;
158 const char *zSep;
159 int i;
160 int cnt = 0;
161
162 user_select();
163 blob_zero(&nonce);
164 blob_zero(&pw);
165 db_blob(&nonce, "SELECT hex(randomblob(20))");
166 blob_copy(&pw, &nonce);
167 db_blob(&pw, "SELECT pw FROM user WHERE uid=%d", g.userUid);
168 sha1sum_blob(&pw, &sig);
169 blob_zero(&login);
170 blob_appendf(&login, "login %s %b %b\n", g.zLogin, &nonce, &sig);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171 blob_reset(&nonce);
172 blob_reset(&pw);
173 blob_reset(&sig);
174 if( g.fHttpTrace ){
175 payload = login;
@@ -183,11 +198,11 @@
183 if( i>0 && g.urlPath[i-1]=='/' ){
184 zSep = "";
185 }else{
186 zSep = "/";
187 }
188 blob_appendf(&hdr, "GET %s%sxfer HTTP/1.1\r\n", g.urlPath, zSep);
189 if( g.fHttpTrace ){
190 blob_appendf(&hdr, "Content-Type: application/x-fossil-debug\r\n");
191 }else{
192 blob_appendf(&hdr, "Content-Type: application/x-fossil\r\n");
193 }
194
--- src/http.c
+++ src/http.c
@@ -157,19 +157,34 @@
157 Blob login, nonce, sig, pw, payload, hdr;
158 const char *zSep;
159 int i;
160 int cnt = 0;
161
 
162 blob_zero(&nonce);
163 blob_zero(&pw);
164 db_blob(&nonce, "SELECT hex(randomblob(20))");
165 blob_copy(&pw, &nonce);
 
 
166 blob_zero(&login);
167 if( g.urlUser==0 ){
168 user_select();
169 db_blob(&pw, "SELECT pw FROM user WHERE uid=%d", g.userUid);
170 sha1sum_blob(&pw, &sig);
171 blob_appendf(&login, "login %s %b %b\n", g.zLogin, &nonce, &sig);
172 }else{
173 if( g.urlPasswd==0 ){
174 if( strcmp(g.urlUser,"anonymous")!=0 ){
175 char *zPrompt = mprintf("password for %s", g.urlUser);
176 Blob x;
177 prompt_for_password(zPrompt, &x, 0);
178 free(zPrompt);
179 blob_append(&pw, blob_buffer(&x), blob_size(&x));
180 blob_reset(&x);
181 }
182 }
183 sha1sum_blob(&pw, &sig);
184 blob_appendf(&login, "login %s %b %b\n", g.urlUser, &nonce, &sig);
185 }
186 blob_reset(&nonce);
187 blob_reset(&pw);
188 blob_reset(&sig);
189 if( g.fHttpTrace ){
190 payload = login;
@@ -183,11 +198,11 @@
198 if( i>0 && g.urlPath[i-1]=='/' ){
199 zSep = "";
200 }else{
201 zSep = "/";
202 }
203 blob_appendf(&hdr, "POST %s%sxfer HTTP/1.1\r\n", g.urlPath, zSep);
204 if( g.fHttpTrace ){
205 blob_appendf(&hdr, "Content-Type: application/x-fossil-debug\r\n");
206 }else{
207 blob_appendf(&hdr, "Content-Type: application/x-fossil\r\n");
208 }
209
+13 -9
--- src/login.c
+++ src/login.c
@@ -203,19 +203,23 @@
203203
g.isAnon = 0;
204204
}
205205
206206
/* Check the login cookie to see if it matches a known valid user.
207207
*/
208
- if( uid==0 && (zCookie = P(login_cookie_name()))!=0 ){
209
- uid = db_int(0,
210
- "SELECT 1 FROM user"
211
- " WHERE uid=%d"
212
- " AND cookie=%Q"
213
- " AND ipaddr=%Q"
214
- " AND cexpire>julianday('now')",
215
- atoi(zCookie), zCookie, zRemoteAddr
216
- );
208
+ if( uid==0 ){
209
+ if( (zCookie = P(login_cookie_name()))!=0 ){
210
+ uid = db_int(0,
211
+ "SELECT uid FROM user"
212
+ " WHERE uid=%d"
213
+ " AND cookie=%Q"
214
+ " AND ipaddr=%Q"
215
+ " AND cexpire>julianday('now')",
216
+ atoi(zCookie), zCookie, zRemoteAddr
217
+ );
218
+ }else{
219
+ uid = db_int(0, "SELECT uid FROM user WHERE login='anonymous'");
220
+ }
217221
}
218222
219223
if( uid==0 ){
220224
g.isAnon = 1;
221225
g.zLogin = "";
222226
--- src/login.c
+++ src/login.c
@@ -203,19 +203,23 @@
203 g.isAnon = 0;
204 }
205
206 /* Check the login cookie to see if it matches a known valid user.
207 */
208 if( uid==0 && (zCookie = P(login_cookie_name()))!=0 ){
209 uid = db_int(0,
210 "SELECT 1 FROM user"
211 " WHERE uid=%d"
212 " AND cookie=%Q"
213 " AND ipaddr=%Q"
214 " AND cexpire>julianday('now')",
215 atoi(zCookie), zCookie, zRemoteAddr
216 );
 
 
 
 
217 }
218
219 if( uid==0 ){
220 g.isAnon = 1;
221 g.zLogin = "";
222
--- src/login.c
+++ src/login.c
@@ -203,19 +203,23 @@
203 g.isAnon = 0;
204 }
205
206 /* Check the login cookie to see if it matches a known valid user.
207 */
208 if( uid==0 ){
209 if( (zCookie = P(login_cookie_name()))!=0 ){
210 uid = db_int(0,
211 "SELECT uid FROM user"
212 " WHERE uid=%d"
213 " AND cookie=%Q"
214 " AND ipaddr=%Q"
215 " AND cexpire>julianday('now')",
216 atoi(zCookie), zCookie, zRemoteAddr
217 );
218 }else{
219 uid = db_int(0, "SELECT uid FROM user WHERE login='anonymous'");
220 }
221 }
222
223 if( uid==0 ){
224 g.isAnon = 1;
225 g.zLogin = "";
226
+2
--- src/main.c
+++ src/main.c
@@ -69,10 +69,12 @@
6969
7070
int urlIsFile; /* True if a "file:" url */
7171
char *urlName; /* Hostname for http: or filename for file: */
7272
int urlPort; /* TCP port number for http: */
7373
char *urlPath; /* Pathname for http: */
74
+ char *urlUser; /* User id for http: */
75
+ char *urlPasswd; /* Password for http: */
7476
char *urlCanonical; /* Canonical representation of the URL */
7577
7678
const char *zLogin; /* Login name. "" if not logged in. */
7779
int isAnon; /* True if logged in anoymously */
7880
int noPswd; /* Logged in without password (on 127.0.0.1) */
7981
--- src/main.c
+++ src/main.c
@@ -69,10 +69,12 @@
69
70 int urlIsFile; /* True if a "file:" url */
71 char *urlName; /* Hostname for http: or filename for file: */
72 int urlPort; /* TCP port number for http: */
73 char *urlPath; /* Pathname for http: */
 
 
74 char *urlCanonical; /* Canonical representation of the URL */
75
76 const char *zLogin; /* Login name. "" if not logged in. */
77 int isAnon; /* True if logged in anoymously */
78 int noPswd; /* Logged in without password (on 127.0.0.1) */
79
--- src/main.c
+++ src/main.c
@@ -69,10 +69,12 @@
69
70 int urlIsFile; /* True if a "file:" url */
71 char *urlName; /* Hostname for http: or filename for file: */
72 int urlPort; /* TCP port number for http: */
73 char *urlPath; /* Pathname for http: */
74 char *urlUser; /* User id for http: */
75 char *urlPasswd; /* Password for http: */
76 char *urlCanonical; /* Canonical representation of the URL */
77
78 const char *zLogin; /* Login name. "" if not logged in. */
79 int isAnon; /* True if logged in anoymously */
80 int noPswd; /* Logged in without password (on 127.0.0.1) */
81
+38 -3
--- src/url.c
+++ src/url.c
@@ -31,20 +31,38 @@
3131
**
3232
** g.urlIsFile True if this is a file URL
3333
** g.urlName Hostname for HTTP:. Filename for FILE:
3434
** g.urlPort Port name for HTTP.
3535
** g.urlPath Path name for HTTP.
36
+** g.urlUser Userid.
37
+** g.urlPasswd Password.
3638
** g.urlCanonical The URL in canonical form
3739
**
40
+** HTTP url format is:
41
+**
42
+** http://userid:password@host:port/path?query#fragment
43
+**
3844
*/
3945
void url_parse(const char *zUrl){
4046
int i, j, c;
41
- char *zFile;
47
+ char *zFile = 0;
4248
if( strncmp(zUrl, "http:", 5)==0 ){
4349
g.urlIsFile = 0;
44
- for(i=7; (c=zUrl[i])!=0 && c!=':' && c!='/'; i++){}
45
- g.urlName = mprintf("%.*s", i-7, &zUrl[7]);
50
+ for(i=7; (c=zUrl[i])!=0 && c!='/' && c!='@'; i++){}
51
+ if( c=='@' ){
52
+ for(j=7; j<i && zUrl[j]!=':'; j++){}
53
+ g.urlUser = mprintf("%.*s", j-7, &zUrl[7]);
54
+ if( j<i ){
55
+ g.urlPasswd = mprintf("%.*s", i-j-1, &zUrl[j+1]);
56
+ }
57
+ for(j=i+1; (c=zUrl[j])!=0 && c!='/' && c!=':'; j++){}
58
+ g.urlName = mprintf("%.*s", j-i-1, &zUrl[i+1]);
59
+ i = j;
60
+ }else{
61
+ for(i=7; (c=zUrl[i])!=0 && c!='/' && c!=':'; i++){}
62
+ g.urlName = mprintf("%.*s", i-7, &zUrl[7]);
63
+ }
4664
for(j=0; g.urlName[j]; j++){ g.urlName[j] = tolower(g.urlName[j]); }
4765
if( c==':' ){
4866
g.urlPort = 0;
4967
i++;
5068
while( (c = zUrl[i])!=0 && isdigit(c) ){
@@ -88,5 +106,22 @@
88106
g.urlName = mprintf("%b", &cfile);
89107
g.urlCanonical = mprintf("file://%T", g.urlName);
90108
blob_reset(&cfile);
91109
}
92110
}
111
+
112
+/*
113
+** COMMAND: test-urlparser
114
+*/
115
+void cmd_test_urlparser(void){
116
+ if( g.argc!=3 ){
117
+ usage("URL");
118
+ }
119
+ url_parse(g.argv[2]);
120
+ printf("g.urlIsFile = %d\n", g.urlIsFile);
121
+ printf("g.urlName = %s\n", g.urlName);
122
+ printf("g.urlPort = %d\n", g.urlPort);
123
+ printf("g.urlPath = %s\n", g.urlPath);
124
+ printf("g.urlUser = %s\n", g.urlUser);
125
+ printf("g.urlPasswd = %s\n", g.urlPasswd);
126
+ printf("g.urlCanonical = %s\n", g.urlCanonical);
127
+}
93128
--- src/url.c
+++ src/url.c
@@ -31,20 +31,38 @@
31 **
32 ** g.urlIsFile True if this is a file URL
33 ** g.urlName Hostname for HTTP:. Filename for FILE:
34 ** g.urlPort Port name for HTTP.
35 ** g.urlPath Path name for HTTP.
 
 
36 ** g.urlCanonical The URL in canonical form
37 **
 
 
 
 
38 */
39 void url_parse(const char *zUrl){
40 int i, j, c;
41 char *zFile;
42 if( strncmp(zUrl, "http:", 5)==0 ){
43 g.urlIsFile = 0;
44 for(i=7; (c=zUrl[i])!=0 && c!=':' && c!='/'; i++){}
45 g.urlName = mprintf("%.*s", i-7, &zUrl[7]);
 
 
 
 
 
 
 
 
 
 
 
 
46 for(j=0; g.urlName[j]; j++){ g.urlName[j] = tolower(g.urlName[j]); }
47 if( c==':' ){
48 g.urlPort = 0;
49 i++;
50 while( (c = zUrl[i])!=0 && isdigit(c) ){
@@ -88,5 +106,22 @@
88 g.urlName = mprintf("%b", &cfile);
89 g.urlCanonical = mprintf("file://%T", g.urlName);
90 blob_reset(&cfile);
91 }
92 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
--- src/url.c
+++ src/url.c
@@ -31,20 +31,38 @@
31 **
32 ** g.urlIsFile True if this is a file URL
33 ** g.urlName Hostname for HTTP:. Filename for FILE:
34 ** g.urlPort Port name for HTTP.
35 ** g.urlPath Path name for HTTP.
36 ** g.urlUser Userid.
37 ** g.urlPasswd Password.
38 ** g.urlCanonical The URL in canonical form
39 **
40 ** HTTP url format is:
41 **
42 ** http://userid:password@host:port/path?query#fragment
43 **
44 */
45 void url_parse(const char *zUrl){
46 int i, j, c;
47 char *zFile = 0;
48 if( strncmp(zUrl, "http:", 5)==0 ){
49 g.urlIsFile = 0;
50 for(i=7; (c=zUrl[i])!=0 && c!='/' && c!='@'; i++){}
51 if( c=='@' ){
52 for(j=7; j<i && zUrl[j]!=':'; j++){}
53 g.urlUser = mprintf("%.*s", j-7, &zUrl[7]);
54 if( j<i ){
55 g.urlPasswd = mprintf("%.*s", i-j-1, &zUrl[j+1]);
56 }
57 for(j=i+1; (c=zUrl[j])!=0 && c!='/' && c!=':'; j++){}
58 g.urlName = mprintf("%.*s", j-i-1, &zUrl[i+1]);
59 i = j;
60 }else{
61 for(i=7; (c=zUrl[i])!=0 && c!='/' && c!=':'; i++){}
62 g.urlName = mprintf("%.*s", i-7, &zUrl[7]);
63 }
64 for(j=0; g.urlName[j]; j++){ g.urlName[j] = tolower(g.urlName[j]); }
65 if( c==':' ){
66 g.urlPort = 0;
67 i++;
68 while( (c = zUrl[i])!=0 && isdigit(c) ){
@@ -88,5 +106,22 @@
106 g.urlName = mprintf("%b", &cfile);
107 g.urlCanonical = mprintf("file://%T", g.urlName);
108 blob_reset(&cfile);
109 }
110 }
111
112 /*
113 ** COMMAND: test-urlparser
114 */
115 void cmd_test_urlparser(void){
116 if( g.argc!=3 ){
117 usage("URL");
118 }
119 url_parse(g.argv[2]);
120 printf("g.urlIsFile = %d\n", g.urlIsFile);
121 printf("g.urlName = %s\n", g.urlName);
122 printf("g.urlPort = %d\n", g.urlPort);
123 printf("g.urlPath = %s\n", g.urlPath);
124 printf("g.urlUser = %s\n", g.urlUser);
125 printf("g.urlPasswd = %s\n", g.urlPasswd);
126 printf("g.urlCanonical = %s\n", g.urlCanonical);
127 }
128
+9 -5
--- src/user.c
+++ src/user.c
@@ -54,12 +54,12 @@
5454
char *z = getpass(zPrompt);
5555
strip_string(pPassphrase, z);
5656
}
5757
5858
/*
59
-** Prompt the user for a passphrase used to encrypt the private key
60
-** portion of an RSA key pair.
59
+** Prompt the user for a password. Store the result in the pPassphrase
60
+** blob.
6161
**
6262
** Behavior is controlled by the verify parameter:
6363
**
6464
** 0 Just ask once.
6565
**
@@ -66,11 +66,15 @@
6666
** 1 If the first answer is a non-empty string, ask for
6767
** verification. Repeat if the two strings do not match.
6868
**
6969
** 2 Ask twice, repeat if the strings do not match.
7070
*/
71
-static void get_passphrase(const char *zPrompt, Blob *pPassphrase, int verify){
71
+void prompt_for_password(
72
+ const char *zPrompt,
73
+ Blob *pPassphrase,
74
+ int verify
75
+){
7276
Blob secondTry;
7377
blob_zero(pPassphrase);
7478
blob_zero(&secondTry);
7579
while(1){
7680
prompt_for_passphrase(zPrompt, pPassphrase);
@@ -117,11 +121,11 @@
117121
if( n>=2 && strncmp(g.argv[2],"new",n)==0 ){
118122
Blob passwd, login, contact;
119123
120124
prompt_user("login: ", &login);
121125
prompt_user("contact-info: ", &contact);
122
- get_passphrase("password: ", &passwd, 1);
126
+ prompt_for_password("password: ", &passwd, 1);
123127
db_multi_exec(
124128
"INSERT INTO user(login,pw,cap,info)"
125129
"VALUES(%B,%B,'jnor',%B)",
126130
&login, &passwd, &contact
127131
);
@@ -149,11 +153,11 @@
149153
uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", g.argv[3]);
150154
if( uid==0 ){
151155
fossil_fatal("no such user: %s", g.argv[3]);
152156
}
153157
zPrompt = mprintf("new passwd for %s: ", g.argv[3]);
154
- get_passphrase(zPrompt, &pw, 1);
158
+ prompt_for_password(zPrompt, &pw, 1);
155159
if( blob_size(&pw)==0 ){
156160
printf("password unchanged\n");
157161
}else{
158162
db_multi_exec("UPDATE user SET pw=%B WHERE uid=%d", &pw, uid);
159163
}
160164
--- src/user.c
+++ src/user.c
@@ -54,12 +54,12 @@
54 char *z = getpass(zPrompt);
55 strip_string(pPassphrase, z);
56 }
57
58 /*
59 ** Prompt the user for a passphrase used to encrypt the private key
60 ** portion of an RSA key pair.
61 **
62 ** Behavior is controlled by the verify parameter:
63 **
64 ** 0 Just ask once.
65 **
@@ -66,11 +66,15 @@
66 ** 1 If the first answer is a non-empty string, ask for
67 ** verification. Repeat if the two strings do not match.
68 **
69 ** 2 Ask twice, repeat if the strings do not match.
70 */
71 static void get_passphrase(const char *zPrompt, Blob *pPassphrase, int verify){
 
 
 
 
72 Blob secondTry;
73 blob_zero(pPassphrase);
74 blob_zero(&secondTry);
75 while(1){
76 prompt_for_passphrase(zPrompt, pPassphrase);
@@ -117,11 +121,11 @@
117 if( n>=2 && strncmp(g.argv[2],"new",n)==0 ){
118 Blob passwd, login, contact;
119
120 prompt_user("login: ", &login);
121 prompt_user("contact-info: ", &contact);
122 get_passphrase("password: ", &passwd, 1);
123 db_multi_exec(
124 "INSERT INTO user(login,pw,cap,info)"
125 "VALUES(%B,%B,'jnor',%B)",
126 &login, &passwd, &contact
127 );
@@ -149,11 +153,11 @@
149 uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", g.argv[3]);
150 if( uid==0 ){
151 fossil_fatal("no such user: %s", g.argv[3]);
152 }
153 zPrompt = mprintf("new passwd for %s: ", g.argv[3]);
154 get_passphrase(zPrompt, &pw, 1);
155 if( blob_size(&pw)==0 ){
156 printf("password unchanged\n");
157 }else{
158 db_multi_exec("UPDATE user SET pw=%B WHERE uid=%d", &pw, uid);
159 }
160
--- src/user.c
+++ src/user.c
@@ -54,12 +54,12 @@
54 char *z = getpass(zPrompt);
55 strip_string(pPassphrase, z);
56 }
57
58 /*
59 ** Prompt the user for a password. Store the result in the pPassphrase
60 ** blob.
61 **
62 ** Behavior is controlled by the verify parameter:
63 **
64 ** 0 Just ask once.
65 **
@@ -66,11 +66,15 @@
66 ** 1 If the first answer is a non-empty string, ask for
67 ** verification. Repeat if the two strings do not match.
68 **
69 ** 2 Ask twice, repeat if the strings do not match.
70 */
71 void prompt_for_password(
72 const char *zPrompt,
73 Blob *pPassphrase,
74 int verify
75 ){
76 Blob secondTry;
77 blob_zero(pPassphrase);
78 blob_zero(&secondTry);
79 while(1){
80 prompt_for_passphrase(zPrompt, pPassphrase);
@@ -117,11 +121,11 @@
121 if( n>=2 && strncmp(g.argv[2],"new",n)==0 ){
122 Blob passwd, login, contact;
123
124 prompt_user("login: ", &login);
125 prompt_user("contact-info: ", &contact);
126 prompt_for_password("password: ", &passwd, 1);
127 db_multi_exec(
128 "INSERT INTO user(login,pw,cap,info)"
129 "VALUES(%B,%B,'jnor',%B)",
130 &login, &passwd, &contact
131 );
@@ -149,11 +153,11 @@
153 uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", g.argv[3]);
154 if( uid==0 ){
155 fossil_fatal("no such user: %s", g.argv[3]);
156 }
157 zPrompt = mprintf("new passwd for %s: ", g.argv[3]);
158 prompt_for_password(zPrompt, &pw, 1);
159 if( blob_size(&pw)==0 ){
160 printf("password unchanged\n");
161 }else{
162 db_multi_exec("UPDATE user SET pw=%B WHERE uid=%d", &pw, uid);
163 }
164
+2
--- src/xfer.c
+++ src/xfer.c
@@ -360,10 +360,11 @@
360360
cgi_reset_content();
361361
@ error wrong\sproject
362362
nErr++;
363363
break;
364364
}
365
+ login_check_credentials();
365366
if( blob_eq(&aToken[0], "pull") ){
366367
if( !g.okRead ){
367368
cgi_reset_content();
368369
@ error not\sauthorized\sto\sread
369370
nErr++;
@@ -385,10 +386,11 @@
385386
/* clone
386387
**
387388
** The client knows nothing. Tell all.
388389
*/
389390
if( blob_eq(&aToken[0], "clone") ){
391
+ login_check_credentials();
390392
if( !g.okRead ){
391393
cgi_reset_content();
392394
@ error not\sauthorized\sto\sread
393395
nErr++;
394396
break;
395397
--- src/xfer.c
+++ src/xfer.c
@@ -360,10 +360,11 @@
360 cgi_reset_content();
361 @ error wrong\sproject
362 nErr++;
363 break;
364 }
 
365 if( blob_eq(&aToken[0], "pull") ){
366 if( !g.okRead ){
367 cgi_reset_content();
368 @ error not\sauthorized\sto\sread
369 nErr++;
@@ -385,10 +386,11 @@
385 /* clone
386 **
387 ** The client knows nothing. Tell all.
388 */
389 if( blob_eq(&aToken[0], "clone") ){
 
390 if( !g.okRead ){
391 cgi_reset_content();
392 @ error not\sauthorized\sto\sread
393 nErr++;
394 break;
395
--- src/xfer.c
+++ src/xfer.c
@@ -360,10 +360,11 @@
360 cgi_reset_content();
361 @ error wrong\sproject
362 nErr++;
363 break;
364 }
365 login_check_credentials();
366 if( blob_eq(&aToken[0], "pull") ){
367 if( !g.okRead ){
368 cgi_reset_content();
369 @ error not\sauthorized\sto\sread
370 nErr++;
@@ -385,10 +386,11 @@
386 /* clone
387 **
388 ** The client knows nothing. Tell all.
389 */
390 if( blob_eq(&aToken[0], "clone") ){
391 login_check_credentials();
392 if( !g.okRead ){
393 cgi_reset_content();
394 @ error not\sauthorized\sto\sread
395 nErr++;
396 break;
397

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button