blob: e90c1407ea0b12345c5bb70c0db42266c63d2a98 [file] [log] [blame]
//========================================================================
//
// JSInfo.cc
//
// This file is licensed under the GPLv2 or later
//
// Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
// Copyright (C) 2016, 2017 Albert Astals Cid <aacid@kde.org>
// Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by the LiMux project of the city of Munich
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
//
//========================================================================
#include "config.h"
#include <stdio.h>
#include "Object.h"
#include "Dict.h"
#include "Annot.h"
#include "PDFDoc.h"
#include "JSInfo.h"
#include "Link.h"
#include "Form.h"
#include "UnicodeMap.h"
#include "UTF.h"
// #include "Win32Console.h"
JSInfo::JSInfo(PDFDoc *docA, int firstPage) {
doc = docA;
currentPage = firstPage + 1;
}
JSInfo::~JSInfo() {
}
void JSInfo::printJS(const GooString *js) {
Unicode *u = nullptr;
char buf[8];
int i, n, len;
if (!js || !js->getCString())
return;
len = TextStringToUCS4(js, &u);
for (i = 0; i < len; i++) {
n = uniMap->mapUnicode(u[i], buf, sizeof(buf));
fwrite(buf, 1, n, file);
}
gfree(u);
}
void JSInfo::scanLinkAction(LinkAction *link, const char *action, bool deleteLink) {
if (!link)
return;
if (link->getKind() == actionJavaScript) {
hasJS = gTrue;
if (print) {
LinkJavaScript *linkjs = static_cast<LinkJavaScript *>(link);
const GooString *s = linkjs->getScript();
if (s && s->getCString()) {
fprintf(file, "%s:\n", action);
printJS(s);
fputs("\n\n", file);
}
}
}
if (link->getKind() == actionRendition) {
LinkRendition *linkr = static_cast<LinkRendition *>(link);
if (linkr->getScript()) {
hasJS = gTrue;
if (print) {
const GooString *s = linkr->getScript();
if (s && s->getCString()) {
fprintf(file, "%s (Rendition):\n", action);
printJS(s);
fputs("\n\n", file);
}
}
}
}
if (deleteLink)
delete link;
}
void JSInfo::scanJS(int nPages) {
print = gFalse;
file = nullptr;
scan(nPages);
}
void JSInfo::scanJS(int nPages, FILE *fout, UnicodeMap *uMap) {
print = gTrue;
file = fout;
uniMap = uMap;
scan(nPages);
}
void JSInfo::scan(int nPages) {
Page *page;
Annots *annots;
int lastPage;
hasJS = gFalse;
// Names
int numNames = doc->getCatalog()->numJS();
if (numNames > 0) {
hasJS = gTrue;
if (print) {
for (int i = 0; i < numNames; i++) {
fprintf(file, "Name Dictionary \"%s\":\n", doc->getCatalog()->getJSName(i)->getCString());
GooString *js = doc->getCatalog()->getJS(i);
printJS(js);
delete js;
fputs("\n\n", file);
}
}
}
// document actions
scanLinkAction(doc->getCatalog()->getAdditionalAction(Catalog::actionCloseDocument),
"Before Close Document");
scanLinkAction(doc->getCatalog()->getAdditionalAction(Catalog::actionSaveDocumentStart),
"Before Save Document");
scanLinkAction(doc->getCatalog()->getAdditionalAction(Catalog::actionSaveDocumentFinish),
"After Save Document");
scanLinkAction(doc->getCatalog()->getAdditionalAction(Catalog::actionPrintDocumentStart),
"Before Print Document");
scanLinkAction(doc->getCatalog()->getAdditionalAction(Catalog::actionPrintDocumentFinish),
"After Print Document");
// form field actions
if (doc->getCatalog()->getFormType() == Catalog::AcroForm) {
Form *form = doc->getCatalog()->getForm();
for (int i = 0; i < form->getNumFields(); i++) {
FormField *field = form->getRootField(i);
for (int j = 0; j < field->getNumWidgets(); j++) {
FormWidget *widget = field->getWidget(j);
scanLinkAction(widget->getActivationAction(),
"Field Activated", false);
scanLinkAction(widget->getAdditionalAction(Annot::actionFieldModified),
"Field Modified");
scanLinkAction(widget->getAdditionalAction(Annot::actionFormatField),
"Format Field");
scanLinkAction(widget->getAdditionalAction(Annot::actionValidateField),
"Validate Field");
scanLinkAction(widget->getAdditionalAction(Annot::actionCalculateField),
"Calculate Field");
}
}
}
// scan pages
if (currentPage > doc->getNumPages()) {
return;
}
lastPage = currentPage + nPages;
if (lastPage > doc->getNumPages() + 1) {
lastPage = doc->getNumPages() + 1;
}
for (int pg = currentPage; pg < lastPage; ++pg) {
page = doc->getPage(pg);
if (!page) continue;
// page actions (open, close)
scanLinkAction(page->getAdditionalAction(Page::actionOpenPage), "Page Open");
scanLinkAction(page->getAdditionalAction(Page::actionClosePage), "Page Close");
// annotation actions (links, screen, widget)
annots = page->getAnnots();
for (int i = 0; i < annots->getNumAnnots(); ++i) {
if (annots->getAnnot(i)->getType() == Annot::typeLink) {
AnnotLink *annot = static_cast<AnnotLink *>(annots->getAnnot(i));
scanLinkAction(annot->getAction(), "Link Annotation Activated", false);
} else if (annots->getAnnot(i)->getType() == Annot::typeScreen) {
AnnotScreen *annot = static_cast<AnnotScreen *>(annots->getAnnot(i));
scanLinkAction(annot->getAction(),
"Screen Annotation Activated", false);
scanLinkAction(annot->getAdditionalAction(Annot::actionCursorEntering),
"Screen Annotation Cursor Enter");
scanLinkAction(annot->getAdditionalAction(Annot::actionCursorLeaving),
"Screen Annotation Cursor Leave");
scanLinkAction(annot->getAdditionalAction(Annot::actionMousePressed),
"Screen Annotation Mouse Pressed");
scanLinkAction(annot->getAdditionalAction(Annot::actionMouseReleased),
"Screen Annotation Mouse Released");
scanLinkAction(annot->getAdditionalAction(Annot::actionFocusIn),
"Screen Annotation Focus In");
scanLinkAction(annot->getAdditionalAction(Annot::actionFocusOut),
"Screen Annotation Focus Out");
scanLinkAction(annot->getAdditionalAction(Annot::actionPageOpening),
"Screen Annotation Page Open");
scanLinkAction(annot->getAdditionalAction(Annot::actionPageClosing),
"Screen Annotation Page Close");
scanLinkAction(annot->getAdditionalAction(Annot::actionPageVisible),
"Screen Annotation Page Visible");
scanLinkAction(annot->getAdditionalAction(Annot::actionPageInvisible),
"Screen Annotation Page Invisible");
} else if (annots->getAnnot(i)->getType() == Annot::typeWidget) {
AnnotWidget *annot = static_cast<AnnotWidget *>(annots->getAnnot(i));
scanLinkAction(annot->getAction(),
"Widget Annotation Activated", false);
scanLinkAction(annot->getAdditionalAction(Annot::actionCursorEntering),
"Widget Annotation Cursor Enter");
scanLinkAction(annot->getAdditionalAction(Annot::actionCursorLeaving),
"Widget Annotation Cursor Leave");
scanLinkAction(annot->getAdditionalAction(Annot::actionMousePressed),
"Widget Annotation Mouse Pressed");
scanLinkAction(annot->getAdditionalAction(Annot::actionMouseReleased),
"Widget Annotation Mouse Released");
scanLinkAction(annot->getAdditionalAction(Annot::actionFocusIn),
"Widget Annotation Focus In");
scanLinkAction(annot->getAdditionalAction(Annot::actionFocusOut),
"Widget Annotation Focus Out");
scanLinkAction(annot->getAdditionalAction(Annot::actionPageOpening),
"Widget Annotation Page Open");
scanLinkAction(annot->getAdditionalAction(Annot::actionPageClosing),
"Widget Annotation Page Close");
scanLinkAction(annot->getAdditionalAction(Annot::actionPageVisible),
"Widget Annotation Page Visible");
scanLinkAction(annot->getAdditionalAction(Annot::actionPageInvisible),
"Widget Annotation Page Invisible");
}
}
}
currentPage = lastPage;
}
GBool JSInfo::containsJS() {
return hasJS;
}