Index: src/setup.c ================================================================== --- src/setup.c +++ src/setup.c @@ -917,10 +917,19 @@ @ to this many bytes, uncompressed. If the client requires more data @ than this, then the client will issue multiple HTTP requests. @ Values below 1 million are not recommended. 5 million is a @ reasonable number.

+ @
+ entry_attribute("Download time limit", 11, "max-download-time", "mxdwnt", + "30"); + + @

Fossil tries to spend less than this many seconds gathering + @ the out-bound data of sync, clone, and pull packets. + @ If the client request takes longer, a partial reply is given similar + @ to the download packet limit. 30s is a reasonable default.

+ @
onoff_attribute( "Enable hyperlinks for \"nobody\" based on User-Agent and Javascript", "auto-hyperlink", "autohyperlink", 1); @

Enable hyperlinks (the equivalent of the "h" permission) for all users Index: src/xfer.c ================================================================== --- src/xfer.c +++ src/xfer.c @@ -18,10 +18,12 @@ ** This file contains code to implement the file transfer protocol. */ #include "config.h" #include "xfer.h" +#include + /* ** This structure holds information about the current state of either ** a client or a server that is participating in xfer. */ typedef struct Xfer Xfer; @@ -40,10 +42,11 @@ int nDeltaRcvd; /* Number of deltas received */ int nDanglingFile; /* Number of dangling deltas received */ int mxSend; /* Stop sending "file" with pOut reaches this size */ u8 syncPrivate; /* True to enable syncing private content */ u8 nextIsPrivate; /* If true, next "file" received is a private */ + time_t maxTime; /* Time when this transfer should be finished */ }; /* ** The input blob contains a UUID. Convert it into a record ID. @@ -393,11 +396,12 @@ } if( uuid_is_shunned(blob_str(pUuid)) ){ blob_reset(&uuid); return; } - if( pXfer->mxSend<=blob_size(pXfer->pOut) ){ + if( (pXfer->maxTime != -1 && time(NULL) >= pXfer->maxTime) || + pXfer->mxSend<=blob_size(pXfer->pOut) ){ const char *zFormat = isPriv ? "igot %b 1\n" : "igot %b\n"; blob_appendf(pXfer->pOut, zFormat, pUuid); pXfer->nIGotSent++; blob_reset(&uuid); return; @@ -867,10 +871,11 @@ } blob_zero(&xfer.err); xfer.pIn = &g.cgiIn; xfer.pOut = cgi_output_blob(); xfer.mxSend = db_get_int("max-download", 5000000); + xfer.maxTime = time(NULL) + db_get_int("max-download-time", 30); g.xferPanic = 1; db_begin_transaction(); db_multi_exec( "CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);" @@ -1034,11 +1039,12 @@ if( iVers>=3 ){ cgi_set_content_type("application/x-fossil-uncompressed"); } blob_is_int(&xfer.aToken[2], &seqno); max = db_int(0, "SELECT max(rid) FROM blob"); - while( xfer.mxSend>blob_size(xfer.pOut) && seqno<=max ){ + while( xfer.mxSend>blob_size(xfer.pOut) && seqno<=max){ + if( time(NULL) >= xfer.maxTime ) break; if( iVers>=3 ){ send_compressed_file(&xfer, seqno); }else{ send_file(&xfer, seqno, 0, 1); } @@ -1328,10 +1334,11 @@ socket_global_init(); memset(&xfer, 0, sizeof(xfer)); xfer.pIn = &recv; xfer.pOut = &send; xfer.mxSend = db_get_int("max-upload", 250000); + xfer.maxTime = -1; if( syncFlags & SYNC_PRIVATE ){ g.perm.Private = 1; xfer.syncPrivate = 1; }