/src/mupdf/source/fitz/link.c
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (C) 2004-2023 Artifex Software, Inc. |
2 | | // |
3 | | // This file is part of MuPDF. |
4 | | // |
5 | | // MuPDF is free software: you can redistribute it and/or modify it under the |
6 | | // terms of the GNU Affero General Public License as published by the Free |
7 | | // Software Foundation, either version 3 of the License, or (at your option) |
8 | | // any later version. |
9 | | // |
10 | | // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY |
11 | | // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
12 | | // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more |
13 | | // details. |
14 | | // |
15 | | // You should have received a copy of the GNU Affero General Public License |
16 | | // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html> |
17 | | // |
18 | | // Alternative licensing terms are available from the licensor. |
19 | | // For commercial licensing, see <https://www.artifex.com/> or contact |
20 | | // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, |
21 | | // CA 94129, USA, for further information. |
22 | | |
23 | | #include "mupdf/fitz.h" |
24 | | |
25 | | #include <math.h> |
26 | | |
27 | | fz_link * |
28 | | fz_new_link_of_size(fz_context *ctx, int size, fz_rect rect, const char *uri) |
29 | 0 | { |
30 | 0 | fz_link *link = Memento_label(fz_calloc(ctx, 1, size), "fz_link"); |
31 | 0 | link->refs = 1; |
32 | 0 | link->rect = rect; |
33 | |
|
34 | 0 | fz_try(ctx) |
35 | 0 | link->uri = fz_strdup(ctx, uri); |
36 | 0 | fz_catch(ctx) |
37 | 0 | { |
38 | 0 | fz_drop_link(ctx, link); |
39 | 0 | fz_rethrow(ctx); |
40 | 0 | } |
41 | | |
42 | 0 | return link; |
43 | 0 | } |
44 | | |
45 | | fz_link * |
46 | | fz_keep_link(fz_context *ctx, fz_link *link) |
47 | 0 | { |
48 | 0 | return fz_keep_imp(ctx, link, &link->refs); |
49 | 0 | } |
50 | | |
51 | | void |
52 | | fz_drop_link(fz_context *ctx, fz_link *link) |
53 | 14 | { |
54 | 14 | while (fz_drop_imp(ctx, link, &link->refs)) |
55 | 0 | { |
56 | 0 | fz_link *next = link->next; |
57 | |
|
58 | 0 | if (link->drop) |
59 | 0 | link->drop(ctx, link); |
60 | |
|
61 | 0 | fz_free(ctx, link->uri); |
62 | 0 | fz_free(ctx, link); |
63 | 0 | link = next; |
64 | 0 | } |
65 | 14 | } |
66 | | |
67 | | int |
68 | | fz_is_external_link(fz_context *ctx, const char *uri) |
69 | 0 | { |
70 | 0 | const char *mark; |
71 | | /* Basically, this function returns true, if the URI starts with |
72 | | * a valid 'scheme' followed by ':'. */ |
73 | |
|
74 | 0 | if (!uri) |
75 | 0 | return 0; |
76 | | |
77 | | /* All schemes must start with a letter; exit if we don't. */ |
78 | 0 | if ((*uri < 'a' || *uri > 'z') && (*uri < 'A' || *uri > 'Z')) |
79 | 0 | return 0; |
80 | 0 | uri++; |
81 | |
|
82 | 0 | mark = uri; |
83 | | |
84 | | /* Subsequent characters can be letters, digits, +, -, or . */ |
85 | 0 | while ((*uri >= 'a' && *uri <= 'z') || |
86 | 0 | (*uri >= 'A' && *uri <= 'Z') || |
87 | 0 | (*uri >= '0' && *uri <= '9') || |
88 | 0 | (*uri == '+') || |
89 | 0 | (*uri == '-') || |
90 | 0 | (*uri == '.')) |
91 | 0 | ++uri; |
92 | |
|
93 | 0 | return uri[0] == ':' && (uri - mark) > 1; |
94 | 0 | } |
95 | | |
96 | | fz_link_dest fz_make_link_dest_none(void) |
97 | 0 | { |
98 | 0 | fz_link_dest dest = { { -1, -1 }, FZ_LINK_DEST_XYZ, NAN, NAN, NAN, NAN, NAN }; |
99 | 0 | return dest; |
100 | 0 | } |
101 | | |
102 | | fz_link_dest fz_make_link_dest_xyz(int chapter, int page, float x, float y, float z) |
103 | 0 | { |
104 | 0 | fz_link_dest dest = { { chapter, page }, FZ_LINK_DEST_XYZ, x, y, NAN, NAN, z }; |
105 | 0 | return dest; |
106 | 0 | } |