Coverage Report

Created: 2025-07-11 06:59

/src/qpdf/libqpdf/QPDFOutlineObjectHelper.cc
Line
Count
Source (jump to first uncovered line)
1
#include <qpdf/QPDFOutlineObjectHelper.hh>
2
3
#include <qpdf/QPDFOutlineDocumentHelper.hh>
4
#include <qpdf/QTC.hh>
5
6
QPDFOutlineObjectHelper::Members::Members(QPDFOutlineDocumentHelper& dh) :
7
3.80k
    dh(dh)
8
3.80k
{
9
3.80k
}
10
11
QPDFOutlineObjectHelper::QPDFOutlineObjectHelper(
12
    QPDFObjectHandle a_oh, QPDFOutlineDocumentHelper& dh, int depth) :
13
3.80k
    QPDFObjectHelper(a_oh),
14
3.80k
    m(new Members(dh))
15
3.80k
{
16
3.80k
    if (depth > 50) {
17
        // Not exercised in test suite, but was tested manually by temporarily changing max depth
18
        // to 1.
19
0
        return;
20
0
    }
21
3.80k
    if (QPDFOutlineDocumentHelper::Accessor::checkSeen(m->dh, a_oh.getObjGen())) {
22
1.44k
        QTC::TC("qpdf", "QPDFOutlineObjectHelper loop");
23
1.44k
        return;
24
1.44k
    }
25
26
2.35k
    QPDFObjGen::set children;
27
2.35k
    QPDFObjectHandle cur = a_oh.getKey("/First");
28
5.26k
    while (!cur.isNull() && cur.isIndirect() && children.add(cur)) {
29
2.90k
        QPDFOutlineObjectHelper new_ooh(cur, dh, 1 + depth);
30
2.90k
        new_ooh.m->parent = std::make_shared<QPDFOutlineObjectHelper>(*this);
31
2.90k
        m->kids.push_back(new_ooh);
32
2.90k
        cur = cur.getKey("/Next");
33
2.90k
    }
34
2.35k
}
35
36
std::shared_ptr<QPDFOutlineObjectHelper>
37
QPDFOutlineObjectHelper::getParent()
38
0
{
39
0
    return m->parent;
40
0
}
41
42
std::vector<QPDFOutlineObjectHelper>
43
QPDFOutlineObjectHelper::getKids()
44
3.60k
{
45
3.60k
    return m->kids;
46
3.60k
}
47
48
QPDFObjectHandle
49
QPDFOutlineObjectHelper::getDest()
50
3.79k
{
51
3.79k
    QPDFObjectHandle dest;
52
3.79k
    QPDFObjectHandle A;
53
3.79k
    if (oh().hasKey("/Dest")) {
54
716
        QTC::TC("qpdf", "QPDFOutlineObjectHelper direct dest");
55
716
        dest = oh().getKey("/Dest");
56
3.08k
    } else if (
57
3.08k
        (A = oh().getKey("/A")).isDictionary() && A.getKey("/S").isName() &&
58
3.08k
        (A.getKey("/S").getName() == "/GoTo") && A.hasKey("/D")) {
59
1.18k
        QTC::TC("qpdf", "QPDFOutlineObjectHelper action dest");
60
1.18k
        dest = A.getKey("/D");
61
1.18k
    }
62
3.79k
    if (!dest) {
63
1.84k
        return QPDFObjectHandle::newNull();
64
1.84k
    }
65
66
1.95k
    if (dest.isName() || dest.isString()) {
67
1.28k
        QTC::TC("qpdf", "QPDFOutlineObjectHelper named dest");
68
1.28k
        dest = m->dh.resolveNamedDest(dest);
69
1.28k
    }
70
71
1.95k
    return dest;
72
3.79k
}
73
74
QPDFObjectHandle
75
QPDFOutlineObjectHelper::getDestPage()
76
3.79k
{
77
3.79k
    QPDFObjectHandle dest = getDest();
78
3.79k
    if ((dest.isArray()) && (dest.getArrayNItems() > 0)) {
79
655
        return dest.getArrayItem(0);
80
655
    }
81
3.14k
    return QPDFObjectHandle::newNull();
82
3.79k
}
83
84
int
85
QPDFOutlineObjectHelper::getCount()
86
0
{
87
0
    int count = 0;
88
0
    if (oh().hasKey("/Count")) {
89
0
        count = oh().getKey("/Count").getIntValueAsInt();
90
0
    }
91
0
    return count;
92
0
}
93
94
std::string
95
QPDFOutlineObjectHelper::getTitle()
96
0
{
97
0
    std::string result;
98
0
    if (oh().hasKey("/Title")) {
99
0
        result = oh().getKey("/Title").getUTF8Value();
100
0
    }
101
0
    return result;
102
0
}