in src/generic/formdata.c [555:695]
long readAndDumpBody(Tcl_Interp * interp, Tcl_Channel in,
const char *boundary, int *isLast,
Tcl_Obj * tmpFileName, long upLoadFileSize,
int filePermissions, long *bytesSkipped)
{
Tcl_Channel out;
Tcl_Obj *curline = NULL;
Tcl_Obj *prevline = NULL;
long tmp = 0;
long readBytes = 0;
long writtenBytes = 0;
long rBytes = 0;
long rBytesPrev = 0;
long wBytes = 0;
/* --------------------------------------------------------------------------
* sanity
* ----------------------------------------------------------------------- */
if ((in == NULL) || (boundary == NULL) || (tmpFileName == NULL))
return 0;
/* --------------------------------------------------------------------------
* open file
* ----------------------------------------------------------------------- */
if ((out = Tcl_OpenFileChannel(NULL, Tcl_GetString(tmpFileName),
"w", filePermissions)) == NULL)
return 0;
/* --------------------------------------------------------------------------
* switch output to "binary"
* ----------------------------------------------------------------------- */
if (Tcl_SetChannelOption(interp, out, "-translation", "binary")
== TCL_ERROR) {
LOG_MSG(interp, WRITE_LOG, __FILE__, __LINE__,
"web::dispatch (file upload)",
WEBLOG_INFO, "error setting translation to binary ", NULL);
return 0;
}
/* --------------------------------------------------------------------------
* first line
* ----------------------------------------------------------------------- */
prevline = Tcl_NewObj();
Tcl_IncrRefCount(prevline);
rBytesPrev = Tcl_GetsObj(in, prevline);
if (rBytesPrev != -1) {
/* ------------------------------------------------------------------------
* read line-by-line, write delayed
* --------------------------------------------------------------------- */
curline = Tcl_NewObj();
Tcl_IncrRefCount(curline);
while ((rBytes = Tcl_GetsObj(in, curline)) != -1) {
int isBoundary = 0;
/* ----------------------------------------------------------------------
* test for boundary
* ------------------------------------------------------------------- */
if (mimeSplitIsBoundary(curline, prevline, boundary, isLast) ==
TCL_OK) {
isBoundary = 1;
readBytes += rBytesPrev - 1; /* we truncated CR */
}
else {
readBytes += rBytesPrev + 1; /* add newline */
}
/* ----------------------------------------------------------------------
* test for upload limit
* ------------------------------------------------------------------- */
if ((upLoadFileSize > 0) && (writtenBytes <= upLoadFileSize)) {
/* --------------------------------------------------------------------
* partial or full write ?
* ----------------------------------------------------------------- */
if ((writtenBytes + rBytesPrev) <= upLoadFileSize) {
/* still room to write all we read */
if ((wBytes = Tcl_WriteObj(out, prevline)) != -1) {
writtenBytes += wBytes;
if (!isBoundary) {
if (writtenBytes <= (upLoadFileSize - 1)) {
/* still room for newline */
if (Tcl_Eof(in) == 0) /* not yet at end-of-file */
if ((tmp =
Tcl_WriteChars(out, "\n", 1)) != -1)
writtenBytes += tmp;
}
}
}
}
else {
/* just dump part of input */
if ((wBytes = Tcl_WriteChars(out, Tcl_GetString(prevline),
upLoadFileSize -
writtenBytes)) != -1) {
writtenBytes += wBytes;
}
}
}
if (isBoundary)
break;
/* ----------------------------------------------------------------------
* update prevline
* ------------------------------------------------------------------- */
Tcl_DecrRefCount(prevline);
prevline = curline;
curline = Tcl_NewObj();
Tcl_IncrRefCount(curline);
rBytesPrev = rBytes;
}
Tcl_DecrRefCount(curline);
}
Tcl_Close(NULL, out);
Tcl_DecrRefCount(prevline);
*bytesSkipped = (readBytes - writtenBytes);
return writtenBytes;
}