示例#1
0
// send the request body to the client after having been handled by a DM plugin
void DataBuffer::out(Socket *sock) throw(std::exception)
{
    if (dontsendbody) {
#ifdef DGDEBUG
        std::cout << "dontsendbody true; not sending" << std::endl;
#endif
        return;
    }
    (*sock).readyForOutput(timeout); // exceptions on timeout or error

    if (tempfilefd > -1) {
// must have been too big for ram so stream from disk in blocks
#ifdef DGDEBUG
        std::cout << "Sending " << tempfilesize - bytesalreadysent << " bytes from temp file (" << bytesalreadysent << " already sent)" << std::endl;
#endif
        off_t sent = bytesalreadysent;
        int rc;

        if (lseek(tempfilefd, bytesalreadysent, SEEK_SET) < 0)
            throw std::runtime_error(std::string("Can't write to socket: ") + strerror(errno));

        while (sent < tempfilesize) {
            rc = readEINTR(tempfilefd, data, buffer_length);
#ifdef DGDEBUG
            std::cout << "reading temp file rc:" << rc << std::endl;
#endif
            if (rc < 0) {
#ifdef DGDEBUG
                std::cout << "error reading temp file so throwing exception" << std::endl;
#endif
                throw std::exception();
            }
            if (rc == 0) {
#ifdef DGDEBUG
                std::cout << "got zero bytes reading temp file" << std::endl;
#endif
                break; // should never happen
            }
            // as it's cached to disk the buffer must be reasonably big
            if (!sock->writeToSocket(data, rc, 0, timeout)) {
                throw std::runtime_error(std::string("Can't write to socket: ") + strerror(errno));
            }
            sent += rc;
#ifdef DGDEBUG
            std::cout << "total sent from temp:" << sent << std::endl;
#endif
        }
        close(tempfilefd);
        tempfilefd = -1;
        tempfilesize = 0;
        unlink(tempfilepath.toCharArray());
    } else {
#ifdef DGDEBUG
        std::cout << "Sending " << buffer_length - bytesalreadysent << " bytes from RAM (" << buffer_length << " in buffer; " << bytesalreadysent << " already sent)" << std::endl;
#endif
        // it's in RAM, so just send it, no streaming from disk
        if (buffer_length != 0) {
            if (!sock->writeToSocket(data + bytesalreadysent, buffer_length - bytesalreadysent, 0, timeout))
                throw std::exception();
        } else {
            if (!sock->writeToSocket("\r\n\r\n", 4, 0, timeout))
                throw std::exception();
        }
    }
}
示例#2
0
// send file contents for scanning
int icapinstance::scanFile(HTTPHeader * requestheader, HTTPHeader * docheader, const char *user,
	int filtergroup, const char *ip, const char *filename, NaughtyFilter * checkme,
	const String *disposition, const String *mimetype)
{
	lastmessage = lastvirusname = "";
	int filefd = open(filename, O_RDONLY);
	if (filefd < 0) {
#ifdef DGDEBUG
		std::cerr << "Error opening file (" << filename << "): " << strerror(errno) << std::endl;
#endif
		lastmessage = "Error opening file to send to ICAP";
		syslog(LOG_ERR, "Error opening file to send to ICAP: %s", strerror(errno));
		return DGCS_SCANERROR;
	}
	lseek(filefd, 0, SEEK_SET);
	unsigned int filesize = lseek(filefd, 0, SEEK_END);

	Socket icapsock;
	if (not doHeaders(icapsock, requestheader, docheader, filesize)) {
		icapsock.close();
		close(filefd);
		return DGCS_SCANERROR;
	}

	lseek(filefd, 0, SEEK_SET);
	unsigned int sent = 0;
	char *data = new char[previewsize];
	char *object = new char[100];
	int objectsize = 0;

#ifdef DGDEBUG
	std::cerr << "About to send file data to icap" << std::endl;
	if (usepreviews && (filesize > previewsize))
		std::cerr << "Sending preview first" << std::endl;
#endif
	if (usepreviews && (filesize > previewsize)) {
		try {
			while (sent < previewsize) {
				int rc = readEINTR(filefd, data, previewsize);
				if (rc < 0) {
					throw std::runtime_error("could not read from file");
				}
				if (rc == 0) {
					break;  // should never happen
				}
				if (!icapsock.writeToSocket(data, rc, 0, o.content_scanner_timeout)) {
					throw std::runtime_error("could not write to socket");
				}
				memcpy(object, data, (rc > 100) ? 100 : rc);
				objectsize += (rc > 100) ? 100 : rc;
				sent += rc;
			}
			icapsock.writeString("\r\n0\r\n\r\n");
			int rc = doScan(icapsock, docheader, object, objectsize, checkme);
			if (rc != ICAP_CONTINUE) {
				delete[] data;
				close(filefd);
				return rc;
			}
			// some servers send "continue" immediately followed by another response
			if (icapsock.checkForInput()) {
				int rc = doScan(icapsock, docheader, object, objectsize, checkme);
				if (rc != ICAP_NODATA) {
					delete[] data;
					close(filefd);
					return rc;
				}
			}
			char objectsizehex[32];
			snprintf(objectsizehex, sizeof(objectsizehex), "%x\r\n", filesize-previewsize);
			icapsock.writeString(objectsizehex);
		} catch (std::exception& e) {
#ifdef DGDEBUG
			std::cerr << "Exception sending message preview to ICAP: " << e.what() << std::endl;
#endif
			icapsock.close();
			lastmessage = "Exception sending message preview to ICAP";
			syslog(LOG_ERR, "Exception sending message preview to ICAP: %s", e.what());
			delete[] data;
			close(filefd);
			// this *might* just be an early response & closed connection
			if (icapsock.checkForInput()) {
				int rc = doScan(icapsock, docheader, object, objectsize, checkme);
				if (rc != ICAP_NODATA)
					return rc;
			}
			return DGCS_SCANERROR;		
		}
	}

	delete[] data;
	data = new char[256 * 1024];  // 256k

	try {
		while (sent < filesize) {
			int rc = readEINTR(filefd, data, 256 * 1024);
#ifdef DGDEBUG
			std::cout << "reading icap file rc: " << rc << std::endl;
#endif
			if (rc < 0) {
#ifdef DGDEBUG
				std::cout << "error reading icap file so throwing exception" << std::endl;
#endif
				throw std::runtime_error("could not read from file");
			}
			if (rc == 0) {
#ifdef DGDEBUG
				std::cout << "got zero bytes reading icap file" << std::endl;
#endif
				break;  // should never happen
			}
			memcpy(object + objectsize, data, (rc > (100-objectsize)) ? (100-objectsize) : rc);
			objectsize += (rc > (100-objectsize)) ? (100-objectsize) : rc;
			icapsock.writeToSockete(data, rc, 0, o.content_scanner_timeout);
			sent += rc;
		}
#ifdef DGDEBUG
		std::cout << "total sent to icap: " << sent << std::endl;
#endif
		icapsock.writeString("\r\n0\r\n\r\n");  // end marker
#ifdef DGDEBUG
		std::cout << "file was sent to icap" << std::endl;
#endif
	}
	catch(std::exception & e) {
#ifdef DGDEBUG
		std::cerr << "Exception sending file to ICAP: " << e.what() << std::endl;
#endif
		lastmessage = "Exception sending file to ICAP";
		syslog(LOG_ERR, "Exception sending file to ICAP: %s", e.what());
		delete[]data;
		close(filefd);
		// this *might* just be an early response & closed connection
		if (icapsock.checkForInput()) {
			int rc = doScan(icapsock, docheader, object, objectsize, checkme);
			if (rc != ICAP_NODATA)
				return rc;
		}
		return DGCS_SCANERROR;
	}
	close(filefd);
	delete[] data;
	return doScan(icapsock, docheader, object, objectsize, checkme);
}