| | @@ -205,10 +205,50 @@ |
| 205 | 205 | if( save_httpauth_prompt() ){ |
| 206 | 206 | set_httpauth(zHttpAuth); |
| 207 | 207 | } |
| 208 | 208 | return zHttpAuth; |
| 209 | 209 | } |
| 210 | + |
| 211 | +/* |
| 212 | +** Send content pSend to the the server identified by g.url using the |
| 213 | +** external program given by g.zHttpCmd. Capture the reply from that |
| 214 | +** program and load it into pReply. |
| 215 | +** |
| 216 | +** This routine implements the --transport-command option for "fossil sync". |
| 217 | +*/ |
| 218 | +static int http_exchange_external( |
| 219 | + Blob *pSend, /* Message to be sent */ |
| 220 | + Blob *pReply, /* Write the reply here */ |
| 221 | + int mHttpFlags, /* Flags. See above */ |
| 222 | + const char *zAltMimetype /* Alternative mimetype if not NULL */ |
| 223 | +){ |
| 224 | + char *zUplink; |
| 225 | + char *zDownlink; |
| 226 | + char *zCmd; |
| 227 | + int rc; |
| 228 | + |
| 229 | + zUplink = fossil_temp_filename(); |
| 230 | + zDownlink = fossil_temp_filename(); |
| 231 | + zCmd = mprintf("%s %$ %$ %$", g.zHttpCmd, g.url.canonical,zUplink,zDownlink); |
| 232 | + blob_write_to_file(pSend, zUplink); |
| 233 | + if( g.fHttpTrace ){ |
| 234 | + fossil_print("RUN: %s\n", zCmd); |
| 235 | + } |
| 236 | + rc = fossil_system(zCmd); |
| 237 | + if( rc ){ |
| 238 | + fossil_warning("Transport command failed: %s\n", zCmd); |
| 239 | + } |
| 240 | + fossil_free(zCmd); |
| 241 | + file_delete(zUplink); |
| 242 | + if( file_size(zDownlink, ExtFILE)<0 ){ |
| 243 | + blob_zero(pReply); |
| 244 | + }else{ |
| 245 | + blob_read_from_file(pReply, zDownlink, ExtFILE); |
| 246 | + file_delete(zDownlink); |
| 247 | + } |
| 248 | + return rc; |
| 249 | +} |
| 210 | 250 | |
| 211 | 251 | /* |
| 212 | 252 | ** Sign the content in pSend, compress it, and send it to the server |
| 213 | 253 | ** via HTTP or HTTPS. Get a reply, uncompress the reply, and store the reply |
| 214 | 254 | ** in pRecv. pRecv is assumed to be uninitialized when |
| | @@ -235,10 +275,15 @@ |
| 235 | 275 | int iHttpVersion; /* Which version of HTTP protocol server uses */ |
| 236 | 276 | char *zLine; /* A single line of the reply header */ |
| 237 | 277 | int i; /* Loop counter */ |
| 238 | 278 | int isError = 0; /* True if the reply is an error message */ |
| 239 | 279 | int isCompressed = 1; /* True if the reply is compressed */ |
| 280 | + |
| 281 | + if( g.zHttpCmd!=0 ){ |
| 282 | + /* Handle the --transport-command option for "fossil sync" and similar */ |
| 283 | + return http_exchange_external(pSend,pReply,mHttpFlags,zAltMimetype); |
| 284 | + } |
| 240 | 285 | |
| 241 | 286 | if( transport_open(&g.url) ){ |
| 242 | 287 | fossil_warning("%s", transport_errmsg(&g.url)); |
| 243 | 288 | return 1; |
| 244 | 289 | } |
| | @@ -519,11 +564,11 @@ |
| 519 | 564 | db_find_and_open_repository(OPEN_OK_NOT_FOUND|OPEN_ANY_SCHEMA, 0); |
| 520 | 565 | verify_all_options(); |
| 521 | 566 | if( g.argc<3 || g.argc>5 ){ |
| 522 | 567 | usage("URL ?PAYLOAD? ?OUTPUT?"); |
| 523 | 568 | } |
| 524 | | - zInFile = g.argc==4 ? g.argv[3] : 0; |
| 569 | + zInFile = g.argc>=4 ? g.argv[3] : 0; |
| 525 | 570 | if( g.argc==5 ){ |
| 526 | 571 | if( zOutFile ){ |
| 527 | 572 | fossil_fatal("output file specified twice: \"--out %s\" and \"%s\"", |
| 528 | 573 | zOutFile, g.argv[4]); |
| 529 | 574 | } |
| 530 | 575 | |