Esempio n. 1
0
def test_image_direct_embed(infile):
    img = Image.open(os.path.join(IMG_DIR, infile))

    w = IncrementalPdfFileWriter(BytesIO(MINIMAL))
    image_ref = images.pil_image(img, w)
    page_ref, resources = w.find_page_for_modification(0)
    resources[pdf_name('/XObject')] = generic.DictionaryObject(
        {pdf_name('/Img'): image_ref})
    w.update_container(resources)
    content_stream: generic.StreamObject = page_ref.get_object()['/Contents']
    content_stream._data = \
        content_stream.data + b' q 50 0 0 50 5 5 cm /Img Do Q'
    content_stream._encoded_data = None
    w.update_container(content_stream)
    w.write_in_place()

    # TODO flatten and do a visual comparison

    image_obj = image_ref.get_object()
    if 'indexed' in infile:
        assert '/SMask' not in image_obj
    else:
        assert '/SMask' in image_obj
Esempio n. 2
0
def append_signature_field(pdf_out: IncrementalPdfFileWriter,
                           sig_field_spec: SigFieldSpec):
    """
    Append signature fields to a PDF file.

    :param pdf_out:
        Incremental writer to house the objects.
    :param sig_field_spec:
        A :class:`.SigFieldSpec` object describing the signature field
        to add.
    """
    root = pdf_out.root

    page_ref = pdf_out.find_page_for_modification(sig_field_spec.on_page)[0]
    # use default appearance
    field_created, sig_field_ref = _prepare_sig_field(
        sig_field_spec.sig_field_name,
        root,
        update_writer=pdf_out,
        existing_fields_only=False,
        box=sig_field_spec.box,
        include_on_page=page_ref,
        lock_sig_flags=False)
    if not field_created:
        raise PdfWriteError('Signature field with name %s already exists.' %
                            sig_field_spec.sig_field_name)

    sig_field = sig_field_ref.get_object()
    if sig_field_spec.seed_value_dict is not None:
        # /SV must be an indirect reference as per the spec
        sv_ref = pdf_out.add_object(
            sig_field_spec.seed_value_dict.as_pdf_object())
        sig_field[pdf_name('/SV')] = sv_ref

    lock = sig_field_spec.format_lock_dictionary()
    if lock is not None:
        sig_field[pdf_name('/Lock')] = pdf_out.add_object(lock)
Esempio n. 3
0
def _prepare_sig_field(sig_field_name,
                       root,
                       update_writer: IncrementalPdfFileWriter,
                       existing_fields_only=False,
                       lock_sig_flags=True,
                       **kwargs):
    """
    Returns a tuple of a boolean and a reference to a signature field.
    The boolean is ``True`` if the field was created, and ``False`` otherwise.
    """
    if sig_field_name is None:  # pragma: nocover
        raise ValueError

    try:
        form = root['/AcroForm']

        try:
            fields = form['/Fields']
        except KeyError:
            raise ValueError('/AcroForm has no /Fields')

        candidates = enumerate_sig_fields_in(fields, with_name=sig_field_name)
        sig_field_ref = None
        try:
            field_name, value, sig_field_ref = next(candidates)
            if value is not None:
                raise SigningError(
                    'Signature field with name %s appears to be filled already.'
                    % sig_field_name)
        except StopIteration:
            if existing_fields_only:
                raise SigningError(
                    'No empty signature field with name %s found.' %
                    sig_field_name)
        form_created = False
    except KeyError:
        # we have to create the form
        if existing_fields_only:
            raise SigningError('This file does not contain a form.')
        # no AcroForm present, so create one
        form = generic.DictionaryObject()
        root[pdf_name('/AcroForm')] = update_writer.add_object(form)
        fields = generic.ArrayObject()
        form[pdf_name('/Fields')] = fields
        # now we need to mark the root as updated
        update_writer.update_root()
        form_created = True
        sig_field_ref = None

    if sig_field_ref is not None:
        return False, sig_field_ref

    if '.' in sig_field_name:
        raise NotImplementedError(
            "Creating fields deep in the form hierarchy is not supported"
            "right now.")

    # no signature field exists, so create one
    # default: grab a reference to the first page
    page_ref = update_writer.find_page_for_modification(0)[0]
    sig_form_kwargs = {'include_on_page': page_ref}
    sig_form_kwargs.update(**kwargs)
    sig_field = SignatureFormField(sig_field_name,
                                   writer=update_writer,
                                   **sig_form_kwargs)
    sig_field_ref = sig_field.reference
    fields.append(sig_field_ref)

    # make sure /SigFlags is present. If not, create it
    sig_flags = 3 if lock_sig_flags else 1
    form.setdefault(pdf_name('/SigFlags'), generic.NumberObject(sig_flags))
    # if a field was added to an existing form, register an extra update
    if not form_created:
        update_writer.update_container(fields)
    return True, sig_field_ref