long readAndDumpBody()

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;
}