| ︙ | | | ︙ | |
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
|
return 0;
}
blob_append(pBlob, rbuf, read);
}
return blob_size(pBlob);
}
#endif
/*
** Make a single attempt to talk to the server. Return TRUE on success
** and FALSE on a failure.
**
** pHeader contains the HTTP header. pPayload contains the content.
** The content of the reply is written into pReply. pReply is assumed
** to be uninitialized prior to this call.
**
** If an error occurs, this routine return false, resets pReply and
** closes the persistent connection, if any.
*/
static int http_send_recv(Blob *pHeader, Blob *pPayload, Blob *pReply){
int closeConnection=1; /* default to closing the connection */
int rc;
int iLength;
int iHttpVersion;
int i;
int nRead;
char zLine[2000];
if( pSocket==0 && http_open_socket() ){
return 0;
}
iLength = -1;
#ifdef __MINGW32__
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
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
|
return 0;
}
blob_append(pBlob, rbuf, read);
}
return blob_size(pBlob);
}
#endif
/*
** zLine is a line from the header of an HTTP reply. Find the
** "argument" to this header line. The argument is the first non-whitespace
** character following the first ":" in the line. The argument consists of
** non-whitespace and non-semicolon characters. Zero-terminate the argument
** before returning.
*/
static char *header_arg(char *zIn){
char *z;
while( *zIn && *zIn!=':' ){ zIn++; }
if( *zIn==':' ){ zIn++; }
while( isspace(*zIn) ){ zIn++; }
for(z=zIn; *z && *z!=';' && !isspace(*z); z++){}
*z = 0;
return zIn;
}
/*
** Make a single attempt to talk to the server. Return TRUE on success
** and FALSE on a failure.
**
** pHeader contains the HTTP header. pPayload contains the content.
** The content of the reply is written into pReply. pReply is assumed
** to be uninitialized prior to this call.
**
** pPayload has already been compressed and/or encrypted prior to being
** passed into this function. pReply will be decrypted and/or decompressed
** as required by this function, based on the Content-Type of the reply.
**
** If an error occurs, this routine return false, resets pReply and
** closes the persistent connection, if any.
*/
static int http_send_recv(Blob *pHeader, Blob *pPayload, Blob *pReply){
int closeConnection=1; /* default to closing the connection */
int rc;
int iLength;
int iHttpVersion;
int i;
int nRead;
int needDecrypt = 0;
int needDecompress = 0;
char zLine[2000];
if( pSocket==0 && http_open_socket() ){
return 0;
}
iLength = -1;
#ifdef __MINGW32__
|
| ︙ | | | ︙ | |
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
|
if( sscanf(zLine, "HTTP/1.%d %d", &iHttpVersion, &rc)!=2 ) goto write_err;
if( rc!=200 ) goto write_err;
if( iHttpVersion==0 ){
closeConnection = 1;
}else{
closeConnection = 0;
}
} else if( strncasecmp(zLine, "content-length:", 15)==0 ){
iLength = atoi(&zLine[16]);
}else if( strncasecmp(zLine, "connection:", 11)==0 ){
for(i=12; isspace(zLine[i]); i++){}
if( zLine[i]=='c' || zLine[i]=='C' ){
closeConnection = 1;
}else if( zLine[i]=='k' || zLine[i]=='K' ){
closeConnection = 0;
}
}
}
if( iLength<0 ) goto write_err;
nRead = socket_read_blob(pReply, pSocket, iLength);
#else
rc = fwrite(blob_buffer(pHeader), 1, blob_size(pHeader), pSocket);
if( rc!=blob_size(pHeader) ) goto write_err;
rc = fwrite(blob_buffer(pPayload), 1, blob_size(pPayload), pSocket);
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
|
>
|
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
|
if( sscanf(zLine, "HTTP/1.%d %d", &iHttpVersion, &rc)!=2 ) goto write_err;
if( rc!=200 ) goto write_err;
if( iHttpVersion==0 ){
closeConnection = 1;
}else{
closeConnection = 0;
}
}else if( strncasecmp(zLine,"content-length:",15)==0 ){
iLength = atoi(header_arg(zLine));
}else if( strncasecmp(zLine, "connection:", 11)==0 ){
int c = header_arg(zLine)[0];
if( c=='c' || c=='C' ){
closeConnection = 1; /* Connection: close */
}else if( c=='k' || c=='K' ){
closeConnection = 0; /* Connection: keep-alive */
}
}else if( strncasecmp(zLine, "content-type:", 13)==0 ){
const char *zType = header_arg(zLine);
if( strcmp(zType, "application/x-fossil")==0 ){
needDecompress = 1;
needDecrypt = 0;
}else if( strcmp(zType, "application/x-fossil-secure")==0 ){
needDecompress = 1;
needDecrypt = 1;
}
}
}
if( iLength<0 ) goto write_err;
nRead = socket_read_blob(pReply, pSocket, iLength);
#else
rc = fwrite(blob_buffer(pHeader), 1, blob_size(pHeader), pSocket);
if( rc!=blob_size(pHeader) ) goto write_err;
rc = fwrite(blob_buffer(pPayload), 1, blob_size(pPayload), pSocket);
|
| ︙ | | | ︙ | |
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
|
closeConnection = 0; /* Connection: keep-alive */
}
while( fgets(zLine, sizeof(zLine), pSocket) ){
for(i=0; zLine[i] && zLine[i]!='\n' && zLine[i]!='\r'; i++){}
if( i==0 ) break;
zLine[i] = 0;
if( strncasecmp(zLine,"content-length:",15)==0 ){
iLength = atoi(&zLine[16]);
}else if( strncasecmp(zLine, "connection:", 11)==0 ){
for(i=12; isspace(zLine[i]); i++){}
if( zLine[i]=='c' || zLine[i]=='C' ){
closeConnection = 1; /* Connection: close */
}else if( zLine[i]=='k' || zLine[i]=='K' ){
closeConnection = 0; /* Connection: keep-alive */
}
}
}
if( iLength<0 ) goto write_err;
nRead = blob_read_from_channel(pReply, pSocket, iLength);
#endif
if( nRead!=iLength ){
blob_reset(pReply);
goto write_err;
}
if( closeConnection ){
http_close();
}
return 1;
write_err:
http_close();
return 0;
}
|
|
|
|
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
|
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
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
|
closeConnection = 0; /* Connection: keep-alive */
}
while( fgets(zLine, sizeof(zLine), pSocket) ){
for(i=0; zLine[i] && zLine[i]!='\n' && zLine[i]!='\r'; i++){}
if( i==0 ) break;
zLine[i] = 0;
if( strncasecmp(zLine,"content-length:",15)==0 ){
iLength = atoi(header_arg(zLine));
}else if( strncasecmp(zLine, "connection:", 11)==0 ){
int c = header_arg(zLine)[0];
if( c=='c' || c=='C' ){
closeConnection = 1; /* Connection: close */
}else if( c=='k' || c=='K' ){
closeConnection = 0; /* Connection: keep-alive */
}
}else if( strncasecmp(zLine, "content-type:", 13)==0 ){
const char *zType = header_arg(zLine);
if( strcmp(zType, "application/x-fossil")==0 ){
needDecompress = 1;
needDecrypt = 0;
}else if( strcmp(zType, "application/x-fossil-secure")==0 ){
needDecompress = 1;
needDecrypt = 1;
}
}
}
if( iLength<0 ) goto write_err;
nRead = blob_read_from_channel(pReply, pSocket, iLength);
#endif
if( nRead!=iLength ){
blob_reset(pReply);
goto write_err;
}
if( closeConnection ){
http_close();
}
if( needDecrypt ){
blob_decrypt(pReply, g.urlPasswd, pReply);
}
if( needDecompress ){
blob_uncompress(pReply, pReply);
}
return 1;
write_err:
http_close();
return 0;
}
|
| ︙ | | | ︙ | |
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
|
}
blob_reset(&nonce);
blob_reset(&pw);
blob_reset(&sig);
/* Construct the payload, which includes the login card.
*/
if( g.fHttpTrace ){
payload = login;
blob_append(&payload, blob_buffer(pSend), blob_size(pSend));
}else{
blob_compress2(&login, pSend, &payload);
blob_reset(&login);
}
/* Construct the HTTP request header
*/
blob_zero(&hdr);
i = strlen(g.urlPath);
if( i>0 && g.urlPath[i-1]=='/' ){
zSep = "";
}else{
zSep = "/";
}
blob_appendf(&hdr, "POST %s%sxfer HTTP/1.1\r\n", g.urlPath, zSep);
blob_appendf(&hdr, "Host: %s\r\n", g.urlHostname);
blob_appendf(&hdr, "User-Agent: Fossil/" MANIFEST_VERSION "\r\n");
if( g.fHttpTrace ){
blob_appendf(&hdr, "Content-Type: application/x-fossil-debug\r\n");
}else{
blob_appendf(&hdr, "Content-Type: application/x-fossil\r\n");
}
blob_appendf(&hdr, "Content-Length: %d\r\n\r\n", blob_size(&payload));
if( g.fHttpTrace ){
|
>
>
>
>
|
>
>
|
|
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
|
}
blob_reset(&nonce);
blob_reset(&pw);
blob_reset(&sig);
/* Construct the payload, which includes the login card.
*/
if( g.fHttpSecure && g.urlPasswd[0] ){
blob_compress(pSend, pSend);
payload = login;
blob_encrypt(pSend, g.urlPasswd, &payload);
}else if( g.fHttpTrace ){
payload = login;
blob_append(&payload, blob_buffer(pSend), blob_size(pSend));
}else{
blob_compress2(&login, pSend, &payload);
blob_reset(&login);
}
/* Construct the HTTP request header
*/
blob_zero(&hdr);
i = strlen(g.urlPath);
if( i>0 && g.urlPath[i-1]=='/' ){
zSep = "";
}else{
zSep = "/";
}
blob_appendf(&hdr, "POST %s%sxfer HTTP/1.1\r\n", g.urlPath, zSep);
blob_appendf(&hdr, "Host: %s\r\n", g.urlHostname);
blob_appendf(&hdr, "User-Agent: Fossil/" MANIFEST_VERSION "\r\n");
if( g.fHttpSecure && g.urlPasswd[0] ){
blob_appendf(&hdr, "Content-Type: application/x-fossil-secure\r\n");
}else if( g.fHttpTrace ){
blob_appendf(&hdr, "Content-Type: application/x-fossil-debug\r\n");
}else{
blob_appendf(&hdr, "Content-Type: application/x-fossil\r\n");
}
blob_appendf(&hdr, "Content-Length: %d\r\n\r\n", blob_size(&payload));
if( g.fHttpTrace ){
|
| ︙ | | | ︙ | |
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
|
if( cnt>=2 ){
fossil_fatal("connection to server failed");
}
blob_reset(&hdr);
blob_reset(&payload);
/* Process the reply. pRecv contains only the payload of the
** reply message, not the header.
*/
if( g.fHttpTrace ){
printf("HTTP RECEIVE:\n%s\n=======================\n", blob_str(pRecv));
}else{
blob_uncompress(pRecv, pRecv);
}
}
/*
** Make sure the socket to the HTTP server is closed
*/
|
|
>
<
<
|
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
|
if( cnt>=2 ){
fossil_fatal("connection to server failed");
}
blob_reset(&hdr);
blob_reset(&payload);
/* Process the reply. pRecv contains only the payload of the
** reply message, not the header. pRecv has already been decrypted
** and decompressed
*/
if( g.fHttpTrace ){
printf("HTTP RECEIVE:\n%s\n=======================\n", blob_str(pRecv));
}
}
/*
** Make sure the socket to the HTTP server is closed
*/
|
| ︙ | | | ︙ | |