eBookReaderSwitch/mupdf/platform/gl/gl-form.c

411 lines
9.3 KiB
C

#include "gl-app.h"
#include <string.h>
#include <stdio.h>
#ifndef PATH_MAX
#define PATH_MAX 2048
#endif
#include "mupdf/helpers/pkcs7-check.h"
#include "mupdf/helpers/pkcs7-openssl.h"
static pdf_widget *sig_widget;
static char sig_designated_name[500];
static enum pdf_signature_error sig_cert_error;
static enum pdf_signature_error sig_digest_error;
static int sig_subsequent_edits;
static char cert_filename[PATH_MAX];
static struct input cert_password;
static void do_sign(void)
{
pdf_pkcs7_signer *signer = NULL;
fz_var(signer);
fz_try(ctx)
{
signer = pkcs7_openssl_read_pfx(ctx, cert_filename, cert_password.text);
pdf_sign_signature(ctx, pdf, sig_widget, signer);
ui_show_warning_dialog("Signed document successfully.");
}
fz_always(ctx)
{
if (signer)
signer->drop(signer);
}
fz_catch(ctx)
ui_show_warning_dialog("%s", fz_caught_message(ctx));
if (pdf_update_page(ctx, sig_widget->page))
render_page();
}
static void do_clear_signature(void)
{
fz_try(ctx)
{
pdf_clear_signature(ctx, pdf, sig_widget);
ui_show_warning_dialog("Signature cleared successfully.");
}
fz_catch(ctx)
ui_show_warning_dialog("%s", fz_caught_message(ctx));
if (pdf_update_page(ctx, sig_widget->page))
render_page();
}
static void cert_password_dialog(void)
{
int is;
ui_dialog_begin(400, (ui.gridsize+4)*3);
{
ui_layout(T, X, NW, 2, 2);
ui_label("Password:");
is = ui_input(&cert_password, 200, 1);
ui_layout(B, X, NW, 2, 2);
ui_panel_begin(0, ui.gridsize, 0, 0, 0);
{
ui_layout(R, NONE, S, 0, 0);
if (ui_button("Cancel"))
ui.dialog = NULL;
ui_spacer();
if (ui_button("Okay") || is == UI_INPUT_ACCEPT)
{
ui.dialog = NULL;
do_sign();
}
}
ui_panel_end();
}
ui_dialog_end();
}
static int cert_file_filter(const char *fn)
{
return !!strstr(fn, ".pfx");
}
static void cert_file_dialog(void)
{
if (ui_open_file(cert_filename))
{
if (cert_filename[0] != 0)
{
ui_input_init(&cert_password, "");
ui.focus = &cert_password;
ui.dialog = cert_password_dialog;
}
else
ui.dialog = NULL;
}
}
static void sig_sign_dialog(void)
{
const char *label = pdf_field_label(ctx, sig_widget->obj);
ui_dialog_begin(400, (ui.gridsize+4)*3 + ui.lineheight*10);
{
ui_layout(T, X, NW, 2, 2);
ui_label("%s", label);
ui_spacer();
ui_label("Would you like to sign this field?");
ui_layout(B, X, NW, 2, 2);
ui_panel_begin(0, ui.gridsize, 0, 0, 0);
{
ui_layout(R, NONE, S, 0, 0);
if (ui_button("Cancel") || (!ui.focus && ui.key == KEY_ESCAPE))
ui.dialog = NULL;
ui_spacer();
if (!(pdf_field_flags(ctx, sig_widget->obj) & PDF_FIELD_IS_READ_ONLY))
{
if (ui_button("Sign"))
{
fz_strlcpy(cert_filename, filename, sizeof cert_filename);
ui_init_open_file(".", cert_file_filter);
ui.dialog = cert_file_dialog;
}
}
}
ui_panel_end();
}
ui_dialog_end();
}
static void sig_verify_dialog(void)
{
const char *label = pdf_field_label(ctx, sig_widget->obj);
ui_dialog_begin(400, (ui.gridsize+4)*3 + ui.lineheight*10);
{
ui_layout(T, X, NW, 2, 2);
ui_label("%s", label);
ui_spacer();
ui_label("Designated name: %s.", sig_designated_name);
ui_spacer();
if (sig_cert_error)
ui_label("Certificate error: %s", pdf_signature_error_description(sig_cert_error));
else
ui_label("Certificate is trusted.");
ui_spacer();
if (sig_digest_error)
ui_label("Digest error: %s", pdf_signature_error_description(sig_digest_error));
else if (sig_subsequent_edits)
ui_label("The signature is valid but there have been edits since signing.");
else
ui_label("The document is unchanged since signing.");
ui_layout(B, X, NW, 2, 2);
ui_panel_begin(0, ui.gridsize, 0, 0, 0);
{
ui_layout(L, NONE, S, 0, 0);
if (ui_button("Clear"))
{
ui.dialog = NULL;
do_clear_signature();
}
ui_layout(R, NONE, S, 0, 0);
if (ui_button("Close") || (!ui.focus && ui.key == KEY_ESCAPE))
ui.dialog = NULL;
}
ui_panel_end();
}
ui_dialog_end();
}
static void show_sig_dialog(pdf_widget *widget)
{
fz_try(ctx)
{
sig_widget = widget;
if (pdf_signature_is_signed(ctx, pdf, widget->obj))
{
sig_cert_error = pdf_check_certificate(ctx, pdf, widget->obj);
sig_digest_error = pdf_check_digest(ctx, pdf, widget->obj);
sig_subsequent_edits = pdf_signature_incremental_change_since_signing(ctx, pdf, widget->obj);
pdf_signature_designated_name(ctx, pdf, widget->obj, sig_designated_name, sizeof(sig_designated_name));
ui.dialog = sig_verify_dialog;
}
else
{
ui.dialog = sig_sign_dialog;
}
}
fz_catch(ctx)
ui_show_warning_dialog("%s", fz_caught_message(ctx));
}
static pdf_widget *tx_widget;
static struct input tx_input;
static void tx_dialog(void)
{
int ff = pdf_field_flags(ctx, tx_widget->obj);
const char *label = pdf_field_label(ctx, tx_widget->obj);
int tx_h = (ff & PDF_TX_FIELD_IS_MULTILINE) ? 10 : 1;
int lbl_h = ui_break_lines((char*)label, NULL, 20, 394, NULL);
int is;
ui_dialog_begin(400, (ui.gridsize+4)*3 + ui.lineheight*(tx_h+lbl_h-2));
{
ui_layout(T, X, NW, 2, 2);
ui_label("%s", label);
is = ui_input(&tx_input, 200, tx_h);
ui_layout(B, X, NW, 2, 2);
ui_panel_begin(0, ui.gridsize, 0, 0, 0);
{
ui_layout(R, NONE, S, 0, 0);
if (ui_button("Cancel") || (!ui.focus && ui.key == KEY_ESCAPE))
ui.dialog = NULL;
ui_spacer();
if (ui_button("Okay") || is == UI_INPUT_ACCEPT)
{
pdf_set_text_field_value(ctx, tx_widget, tx_input.text);
if (pdf_update_page(ctx, tx_widget->page))
render_page();
ui.dialog = NULL;
}
}
ui_panel_end();
}
ui_dialog_end();
}
void show_tx_dialog(pdf_widget *widget)
{
ui_input_init(&tx_input, pdf_field_value(ctx, widget->obj));
ui.focus = &tx_input;
ui.dialog = tx_dialog;
tx_widget = widget;
}
static pdf_widget *ch_widget;
static void ch_dialog(void)
{
const char *label;
const char *value;
char **options;
int n, choice;
int label_h;
label = pdf_field_label(ctx, ch_widget->obj);
label_h = ui_break_lines((char*)label, NULL, 20, 394, NULL);
n = pdf_choice_widget_options(ctx, ch_widget, 0, NULL);
options = fz_malloc_array(ctx, n, char *);
pdf_choice_widget_options(ctx, ch_widget, 0, (const char **)options);
value = pdf_field_value(ctx, ch_widget->obj);
ui_dialog_begin(400, (ui.gridsize+4)*3 + ui.lineheight*(label_h-1));
{
ui_layout(T, X, NW, 2, 2);
ui_label("%s", label);
choice = ui_select("Widget/Ch", value, (const char **)options, n);
if (choice >= 0)
pdf_set_choice_field_value(ctx, ch_widget, options[choice]);
ui_layout(B, X, NW, 2, 2);
ui_panel_begin(0, ui.gridsize, 0, 0, 0);
{
ui_layout(R, NONE, S, 0, 0);
if (ui_button("Cancel") || (!ui.focus && ui.key == KEY_ESCAPE))
ui.dialog = NULL;
ui_spacer();
if (ui_button("Okay"))
{
if (pdf_update_page(ctx, ch_widget->page))
render_page();
ui.dialog = NULL;
}
}
ui_panel_end();
}
ui_dialog_end();
fz_free(ctx, options);
}
void do_widget_canvas(fz_irect canvas_area)
{
pdf_widget *widget;
fz_rect bounds;
fz_irect area;
if (!pdf)
return;
for (widget = pdf_first_widget(ctx, page); widget; widget = pdf_next_widget(ctx, widget))
{
bounds = pdf_bound_widget(ctx, widget);
bounds = fz_transform_rect(bounds, view_page_ctm);
area = fz_irect_from_rect(bounds);
if (ui_mouse_inside(canvas_area) && ui_mouse_inside(area))
{
if (!widget->is_hot)
pdf_annot_event_enter(ctx, widget);
widget->is_hot = 1;
ui.hot = widget;
if (!ui.active && ui.down)
{
ui.active = widget;
pdf_annot_event_down(ctx, widget);
if (selected_annot != widget)
{
if (selected_annot && pdf_annot_type(ctx, selected_annot) == PDF_ANNOT_WIDGET)
pdf_annot_event_blur(ctx, selected_annot);
selected_annot = widget;
pdf_annot_event_focus(ctx, widget);
}
}
}
else
{
if (widget->is_hot)
pdf_annot_event_exit(ctx, widget);
widget->is_hot = 0;
}
/* Set is_hot and is_active to select current appearance */
widget->is_active = (ui.active == widget && ui.down);
if (showform)
{
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glColor4f(0, 0, 1, 0.1f);
glRectf(area.x0, area.y0, area.x1, area.y1);
glDisable(GL_BLEND);
}
if (ui.active == widget || (!ui.active && ui.hot == widget))
{
glLineStipple(1, 0xAAAA);
glEnable(GL_LINE_STIPPLE);
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
glEnable(GL_BLEND);
glColor4f(1, 1, 1, 1);
glBegin(GL_LINE_LOOP);
glVertex2f(area.x0-0.5f, area.y0-0.5f);
glVertex2f(area.x1+0.5f, area.y0-0.5f);
glVertex2f(area.x1+0.5f, area.y1+0.5f);
glVertex2f(area.x0-0.5f, area.y1+0.5f);
glEnd();
glDisable(GL_BLEND);
glDisable(GL_LINE_STIPPLE);
}
if (ui.hot == widget && ui.active == widget && !ui.down)
{
pdf_annot_event_up(ctx, widget);
if (pdf_widget_type(ctx, widget) == PDF_WIDGET_TYPE_SIGNATURE)
{
show_sig_dialog(widget);
}
else
{
if (pdf_field_flags(ctx, widget->obj) & PDF_FIELD_IS_READ_ONLY)
continue;
switch (pdf_widget_type(ctx, widget))
{
default:
break;
case PDF_WIDGET_TYPE_CHECKBOX:
case PDF_WIDGET_TYPE_RADIOBUTTON:
pdf_toggle_widget(ctx, widget);
break;
case PDF_WIDGET_TYPE_TEXT:
show_tx_dialog(widget);
break;
case PDF_WIDGET_TYPE_COMBOBOX:
case PDF_WIDGET_TYPE_LISTBOX:
ui.dialog = ch_dialog;
ch_widget = widget;
break;
}
}
}
}
if (pdf_update_page(ctx, page))
render_page();
}