Pl_AES_PDF::flush(bool strip_padding)
{
    assert(this->offset == this->buf_size);

    if (first)
    {
	first = false;
	if (this->cbc_mode)
	{
	    if (encrypt)
	    {
		// Set cbc_block to the initialization vector, and if
		// not zero, write it to the output stream.
		initializeVector();
                if (! (this->use_zero_iv || this->use_specified_iv))
                {
                    getNext()->write(this->cbc_block, this->buf_size);
                }
	    }
	    else if (this->use_zero_iv || this->use_specified_iv)
            {
                // Initialize vector with zeroes; zero vector was not
                // written to the beginning of the input file.
                initializeVector();
            }
            else
	    {
		// Take the first block of input as the initialization
		// vector.  There's nothing to write at this time.
		memcpy(this->cbc_block, this->inbuf, this->buf_size);
		this->offset = 0;
		return;
	    }
	}
    }

    if (this->encrypt)
    {
	if (this->cbc_mode)
	{
	    for (unsigned int i = 0; i < this->buf_size; ++i)
	    {
		this->inbuf[i] ^= this->cbc_block[i];
	    }
	}
	rijndaelEncrypt(this->rk, this->nrounds, this->inbuf, this->outbuf);
	if (this->cbc_mode)
	{
	    memcpy(this->cbc_block, this->outbuf, this->buf_size);
	}
    }
    else
    {
	rijndaelDecrypt(this->rk, this->nrounds, this->inbuf, this->outbuf);
	if (this->cbc_mode)
	{
	    for (unsigned int i = 0; i < this->buf_size; ++i)
	    {
		this->outbuf[i] ^= this->cbc_block[i];
	    }
	    memcpy(this->cbc_block, this->inbuf, this->buf_size);
	}
    }
    unsigned int bytes = this->buf_size;
    if (strip_padding)
    {
	unsigned char last = this->outbuf[this->buf_size - 1];
	if (last <= this->buf_size)
	{
	    bool strip = true;
	    for (unsigned int i = 1; i <= last; ++i)
	    {
		if (this->outbuf[this->buf_size - i] != last)
		{
		    strip = false;
		    break;
		}
	    }
	    if (strip)
	    {
		bytes -= last;
	    }
	}
    }
    getNext()->write(this->outbuf, bytes);
    this->offset = 0;
}
Pl_AES_PDF::flush(bool strip_padding)
{
    assert(this->offset == this->buf_size);

    if (first)
    {
	first = false;
	if (this->cbc_mode)
	{
	    if (encrypt)
	    {
		 
		 
		initializeVector();
                if (! (this->use_zero_iv || this->use_specified_iv))
                {
                    getNext()->write(this->cbc_block, this->buf_size);
                }
	    }
	    else if (this->use_zero_iv || this->use_specified_iv)
            {
                 
                 
                initializeVector();
            }
            else
	    {
		 
		 
		memcpy(this->cbc_block, this->inbuf, this->buf_size);
		this->offset = 0;
		return;
	    }
	}
    }

    if (this->encrypt)
    {
	if (this->cbc_mode)
	{
	    for (unsigned int i = 0; i < this->buf_size; ++i)
	    {
		this->inbuf[i] ^= this->cbc_block[i];
	    }
	}
	rijndaelEncrypt(this->rk, this->nrounds, this->inbuf, this->outbuf);
	if (this->cbc_mode)
	{
	    memcpy(this->cbc_block, this->outbuf, this->buf_size);
	}
    }
    else
    {
	rijndaelDecrypt(this->rk, this->nrounds, this->inbuf, this->outbuf);
	if (this->cbc_mode)
	{
	    for (unsigned int i = 0; i < this->buf_size; ++i)
	    {
		this->outbuf[i] ^= this->cbc_block[i];
	    }
	    memcpy(this->cbc_block, this->inbuf, this->buf_size);
	}
    }
    unsigned int bytes = this->buf_size;
    if (strip_padding)
    {
	unsigned char last = this->outbuf[this->buf_size - 1];
	if (last <= this->buf_size)
	{
	    bool strip = true;
	    for (unsigned int i = 1; i <= last; ++i)
	    {
		if (this->outbuf[this->buf_size - i] != last)
		{
		    strip = false;
		    break;
		}
	    }
	    if (strip)
	    {
		bytes -= last;
	    }
	}
    }
    getNext()->write(this->outbuf, bytes);
    this->offset = 0;
}