Bug Summary

File:backend/comics/comics-document.c
Warning:line 966, column 31
The left operand of '*' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name comics-document.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/backend/comics -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I ../.. -I ../.. -I ../../libdocument -D CAFELOCALEDIR="/usr/share/locale" -D LECTOR_COMPILATION -I /usr/include/cairo -I /usr/include/libpng16 -I /usr/include/freetype2 -I /usr/include/pixman-1 -I /usr/include/ctk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/harfbuzz -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -D CDK_MULTIHEAD_SAFE -D CTK_MULTIHEAD_SAFE -D PIC -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/backend/comics -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-02-18-122410-54188-1 -x c comics-document.c
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */
2/*
3 * Copyright (C) 2009-2010 Juanjo Marín <juanj.marin@juntadeandalucia.es>
4 * Copyright (C) 2005, Teemu Tervo <teemu.tervo@gmx.net>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20
21#include <config.h>
22
23#include <unistd.h>
24#include <string.h>
25#include <stdlib.h>
26#include <errno(*__errno_location ()).h>
27
28#include <glib.h>
29#include <glib/gi18n-lib.h>
30#include <glib/gstdio.h>
31#include <gio/gio.h>
32
33#include <sys/wait.h>
34
35#include "comics-document.h"
36#include "ev-document-misc.h"
37#include "ev-document-thumbnails.h"
38#include "ev-file-helpers.h"
39
40#define EV_EOL"\n" "\n"
41
42typedef enum
43{
44 RARLABS,
45 GNAUNRAR,
46 UNZIP,
47 P7ZIP,
48 TAR,
49 UNARCHIVER
50} ComicBookDecompressType;
51
52typedef struct _ComicsDocumentClass ComicsDocumentClass;
53
54struct _ComicsDocumentClass
55{
56 EvDocumentClass parent_class;
57};
58
59struct _ComicsDocument
60{
61 EvDocument parent_instance;
62
63 gchar *archive, *dir;
64 GPtrArray *page_names;
65 gchar *selected_command, *alternative_command;
66 gchar *extract_command, *list_command, *decompress_tmp;
67 gboolean regex_arg;
68 gint offset;
69 ComicBookDecompressType command_usage;
70};
71
72#define OFFSET_7Z53 53
73#define OFFSET_ZIP2 2
74#define NO_OFFSET0 0
75
76/* For perfomance reasons of 7z* we've choosen to decompress on the temporary
77 * directory instead of decompressing on the stdout */
78
79/**
80 * @extract: command line arguments to pass to extract a file from the archive
81 * to stdout.
82 * @list: command line arguments to list the archive contents
83 * @decompress_tmp: command line arguments to pass to extract the archive
84 * into a directory.
85 * @regex_arg: whether the command can accept regex expressions
86 * @offset: the position offset of the filename on each line in the output of
87 * running the @list command
88 */
89typedef struct {
90 char *extract;
91 char *list;
92 char *decompress_tmp;
93 gboolean regex_arg;
94 gint offset;
95} ComicBookDecompressCommand;
96
97static const ComicBookDecompressCommand command_usage_def[] = {
98 /* RARLABS unrar */
99 {"%s p -c- -ierr --", "%s vb -c- -- %s", NULL((void*)0) , FALSE(0), NO_OFFSET0},
100
101 /* GNA! unrar */
102 {NULL((void*)0) , "%s t %s" , "%s -xf %s %s" , FALSE(0), NO_OFFSET0},
103
104 /* unzip */
105 {"%s -p -C --" , "%s %s" , NULL((void*)0) , TRUE(!(0)) , OFFSET_ZIP2},
106
107 /* 7zip */
108 {NULL((void*)0) , "%s l -- %s" , "%s x -y %s -o%s", FALSE(0), OFFSET_7Z53},
109
110 /* tar */
111 {"%s -xOf" , "%s -tf %s" , NULL((void*)0) , FALSE(0), NO_OFFSET0},
112
113 /* UNARCHIVER */
114 {"unar -o -" , "%s %s" , NULL((void*)0) , FALSE(0), NO_OFFSET0}
115};
116
117static void comics_document_document_thumbnails_iface_init (EvDocumentThumbnailsInterface *iface);
118
119static GSList* get_supported_image_extensions (void);
120static void get_page_size_area_prepared_cb (GdkPixbufLoader *loader,
121 gpointer data);
122static void render_pixbuf_size_prepared_cb (GdkPixbufLoader *loader,
123 gint width,
124 gint height,
125 gpointer data);
126static char** extract_argv (EvDocument *document,
127 gint page);
128
129
130EV_BACKEND_REGISTER_WITH_CODE (ComicsDocument, comics_document,static GType g_define_type_id = 0; GType comics_document_get_type
(void) { return g_define_type_id; } static void comics_document_init
(ComicsDocument *self); static void comics_document_class_init
(ComicsDocumentClass *klass); static gpointer comics_document_parent_class
= ((void*)0); static void comics_document_class_intern_init (
gpointer klass) { comics_document_parent_class = g_type_class_peek_parent
(klass); comics_document_class_init ((ComicsDocumentClass *)
klass); } __attribute__((visibility("default"))) GType register_lector_backend
(GTypeModule *module) { const GTypeInfo our_info = { sizeof (
ComicsDocumentClass), ((void*)0), ((void*)0), (GClassInitFunc
) comics_document_class_intern_init, ((void*)0), ((void*)0), sizeof
(ComicsDocument), 0, (GInstanceInitFunc) comics_document_init
}; bindtextdomain ("lector", "/usr/share/locale"); bind_textdomain_codeset
("lector", "UTF-8"); g_define_type_id = g_type_module_register_type
(module, (ev_document_get_type ()), "ComicsDocument", &our_info
, (GTypeFlags)0); { { const GInterfaceInfo g_implement_interface_info
= { (GInterfaceInitFunc) comics_document_document_thumbnails_iface_init
, ((void*)0), ((void*)0) }; g_type_module_add_interface (module
, g_define_type_id, (ev_document_thumbnails_get_type ()), &
g_implement_interface_info); }; } return g_define_type_id; }
131 {static GType g_define_type_id = 0; GType comics_document_get_type
(void) { return g_define_type_id; } static void comics_document_init
(ComicsDocument *self); static void comics_document_class_init
(ComicsDocumentClass *klass); static gpointer comics_document_parent_class
= ((void*)0); static void comics_document_class_intern_init (
gpointer klass) { comics_document_parent_class = g_type_class_peek_parent
(klass); comics_document_class_init ((ComicsDocumentClass *)
klass); } __attribute__((visibility("default"))) GType register_lector_backend
(GTypeModule *module) { const GTypeInfo our_info = { sizeof (
ComicsDocumentClass), ((void*)0), ((void*)0), (GClassInitFunc
) comics_document_class_intern_init, ((void*)0), ((void*)0), sizeof
(ComicsDocument), 0, (GInstanceInitFunc) comics_document_init
}; bindtextdomain ("lector", "/usr/share/locale"); bind_textdomain_codeset
("lector", "UTF-8"); g_define_type_id = g_type_module_register_type
(module, (ev_document_get_type ()), "ComicsDocument", &our_info
, (GTypeFlags)0); { { const GInterfaceInfo g_implement_interface_info
= { (GInterfaceInitFunc) comics_document_document_thumbnails_iface_init
, ((void*)0), ((void*)0) }; g_type_module_add_interface (module
, g_define_type_id, (ev_document_thumbnails_get_type ()), &
g_implement_interface_info); }; } return g_define_type_id; }
132 EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS,static GType g_define_type_id = 0; GType comics_document_get_type
(void) { return g_define_type_id; } static void comics_document_init
(ComicsDocument *self); static void comics_document_class_init
(ComicsDocumentClass *klass); static gpointer comics_document_parent_class
= ((void*)0); static void comics_document_class_intern_init (
gpointer klass) { comics_document_parent_class = g_type_class_peek_parent
(klass); comics_document_class_init ((ComicsDocumentClass *)
klass); } __attribute__((visibility("default"))) GType register_lector_backend
(GTypeModule *module) { const GTypeInfo our_info = { sizeof (
ComicsDocumentClass), ((void*)0), ((void*)0), (GClassInitFunc
) comics_document_class_intern_init, ((void*)0), ((void*)0), sizeof
(ComicsDocument), 0, (GInstanceInitFunc) comics_document_init
}; bindtextdomain ("lector", "/usr/share/locale"); bind_textdomain_codeset
("lector", "UTF-8"); g_define_type_id = g_type_module_register_type
(module, (ev_document_get_type ()), "ComicsDocument", &our_info
, (GTypeFlags)0); { { const GInterfaceInfo g_implement_interface_info
= { (GInterfaceInitFunc) comics_document_document_thumbnails_iface_init
, ((void*)0), ((void*)0) }; g_type_module_add_interface (module
, g_define_type_id, (ev_document_thumbnails_get_type ()), &
g_implement_interface_info); }; } return g_define_type_id; }
133 comics_document_document_thumbnails_iface_init);static GType g_define_type_id = 0; GType comics_document_get_type
(void) { return g_define_type_id; } static void comics_document_init
(ComicsDocument *self); static void comics_document_class_init
(ComicsDocumentClass *klass); static gpointer comics_document_parent_class
= ((void*)0); static void comics_document_class_intern_init (
gpointer klass) { comics_document_parent_class = g_type_class_peek_parent
(klass); comics_document_class_init ((ComicsDocumentClass *)
klass); } __attribute__((visibility("default"))) GType register_lector_backend
(GTypeModule *module) { const GTypeInfo our_info = { sizeof (
ComicsDocumentClass), ((void*)0), ((void*)0), (GClassInitFunc
) comics_document_class_intern_init, ((void*)0), ((void*)0), sizeof
(ComicsDocument), 0, (GInstanceInitFunc) comics_document_init
}; bindtextdomain ("lector", "/usr/share/locale"); bind_textdomain_codeset
("lector", "UTF-8"); g_define_type_id = g_type_module_register_type
(module, (ev_document_get_type ()), "ComicsDocument", &our_info
, (GTypeFlags)0); { { const GInterfaceInfo g_implement_interface_info
= { (GInterfaceInitFunc) comics_document_document_thumbnails_iface_init
, ((void*)0), ((void*)0) }; g_type_module_add_interface (module
, g_define_type_id, (ev_document_thumbnails_get_type ()), &
g_implement_interface_info); }; } return g_define_type_id; }
134 } )static GType g_define_type_id = 0; GType comics_document_get_type
(void) { return g_define_type_id; } static void comics_document_init
(ComicsDocument *self); static void comics_document_class_init
(ComicsDocumentClass *klass); static gpointer comics_document_parent_class
= ((void*)0); static void comics_document_class_intern_init (
gpointer klass) { comics_document_parent_class = g_type_class_peek_parent
(klass); comics_document_class_init ((ComicsDocumentClass *)
klass); } __attribute__((visibility("default"))) GType register_lector_backend
(GTypeModule *module) { const GTypeInfo our_info = { sizeof (
ComicsDocumentClass), ((void*)0), ((void*)0), (GClassInitFunc
) comics_document_class_intern_init, ((void*)0), ((void*)0), sizeof
(ComicsDocument), 0, (GInstanceInitFunc) comics_document_init
}; bindtextdomain ("lector", "/usr/share/locale"); bind_textdomain_codeset
("lector", "UTF-8"); g_define_type_id = g_type_module_register_type
(module, (ev_document_get_type ()), "ComicsDocument", &our_info
, (GTypeFlags)0); { { const GInterfaceInfo g_implement_interface_info
= { (GInterfaceInitFunc) comics_document_document_thumbnails_iface_init
, ((void*)0), ((void*)0) }; g_type_module_add_interface (module
, g_define_type_id, (ev_document_thumbnails_get_type ()), &
g_implement_interface_info); }; } return g_define_type_id; }
;
135
136/**
137 * comics_regex_quote:
138 * @unquoted_string: a literal string
139 *
140 * Quotes a string so unzip will not interpret the regex expressions of
141 * @unquoted_string. Basically, this functions uses [] to disable regex
142 * expressions. The return value must be freed with * g_free()
143 *
144 * Return value: quoted and disabled-regex string
145 **/
146static gchar *
147comics_regex_quote (const gchar *unquoted_string)
148{
149 const gchar *p;
150 GString *dest;
151
152 dest = g_string_new ("'");
153
154 p = unquoted_string;
155
156 while (*p) {
157 switch (*p) {
158 /* * matches a sequence of 0 or more characters */
159 case ('*'):
160 /* ? matches exactly 1 charactere */
161 case ('?'):
162 /* [...] matches any single character found inside
163 * the brackets. Disabling the first bracket is enough.
164 */
165 case ('['):
166 g_string_append (dest, "[")(__builtin_constant_p ("[") ? __extension__ ({ const char * const
__val = ("["); g_string_append_len_inline (dest, __val, (__val
!= ((void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize
) -1); }) : g_string_append_len_inline (dest, "[", (gssize) -
1))
;
167 g_string_append_c (dest, *p)g_string_append_c_inline (dest, *p);
168 g_string_append (dest, "]")(__builtin_constant_p ("]") ? __extension__ ({ const char * const
__val = ("]"); g_string_append_len_inline (dest, __val, (__val
!= ((void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize
) -1); }) : g_string_append_len_inline (dest, "]", (gssize) -
1))
;
169 break;
170 /* Because \ escapes regex expressions that we are
171 * disabling for unzip, we need to disable \ too */
172 case ('\\'):
173 g_string_append (dest, "[\\\\]")(__builtin_constant_p ("[\\\\]") ? __extension__ ({ const char
* const __val = ("[\\\\]"); g_string_append_len_inline (dest
, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !
(__val))) : (gssize) -1); }) : g_string_append_len_inline (dest
, "[\\\\]", (gssize) -1))
;
174 break;
175 /* Escape single quote inside the string */
176 case ('\''):
177 g_string_append (dest, "'\\''")(__builtin_constant_p ("'\\''") ? __extension__ ({ const char
* const __val = ("'\\''"); g_string_append_len_inline (dest,
__val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !
(__val))) : (gssize) -1); }) : g_string_append_len_inline (dest
, "'\\''", (gssize) -1))
;
178 break;
179 default:
180 g_string_append_c (dest, *p)g_string_append_c_inline (dest, *p);
181 break;
182 }
183 ++p;
184 }
185 g_string_append_c (dest, '\'')g_string_append_c_inline (dest, '\'');
186 return g_string_free (dest, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((dest
), ((0))) : g_string_free_and_steal (dest)) : (g_string_free)
((dest), ((0))))
;
187}
188
189
190/* This function manages the command for decompressing a comic book */
191static gboolean
192comics_decompress_temp_dir (const gchar *command_decompress_tmp,
193 const gchar *command,
194 GError **error)
195{
196 gboolean success;
197 gchar *std_out, *basename;
198 GError *err = NULL((void*)0);
199 gint retval;
200
201 success = g_spawn_command_line_sync (command_decompress_tmp, &std_out,
202 NULL((void*)0), &retval, &err);
203 basename = g_path_get_basename (command);
204 if (!success) {
205 g_set_error (error,
206 EV_DOCUMENT_ERRORev_document_error_quark (),
207 EV_DOCUMENT_ERROR_INVALID,
208 _("Error launching the command “%s” in order to "((char *) g_dgettext ("lector", "Error launching the command “%s” in order to "
"decompress the comic book: %s"))
209 "decompress the comic book: %s")((char *) g_dgettext ("lector", "Error launching the command “%s” in order to "
"decompress the comic book: %s"))
,
210 basename,
211 err->message);
212 g_error_free (err);
213 } else if (WIFEXITED (retval)(((retval) & 0x7f) == 0)) {
214 if (WEXITSTATUS (retval)(((retval) & 0xff00) >> 8) == EXIT_SUCCESS0) {
215 g_free (std_out);
216 g_free (basename);
217 return TRUE(!(0));
218 } else {
219 g_set_error (error,
220 EV_DOCUMENT_ERRORev_document_error_quark (),
221 EV_DOCUMENT_ERROR_INVALID,
222 _("The command “%s” failed at "((char *) g_dgettext ("lector", "The command “%s” failed at "
"decompressing the comic book."))
223 "decompressing the comic book.")((char *) g_dgettext ("lector", "The command “%s” failed at "
"decompressing the comic book."))
,
224 basename);
225 g_free (std_out);
226 }
227 } else {
228 g_set_error (error,
229 EV_DOCUMENT_ERRORev_document_error_quark (),
230 EV_DOCUMENT_ERROR_INVALID,
231 _("The command “%s” did not end normally.")((char *) g_dgettext ("lector", "The command “%s” did not end normally."
))
,
232 basename);
233 g_free (std_out);
234 }
235 g_free (basename);
236 return FALSE(0);
237}
238
239/* This function shows how to use the choosen command for decompressing a
240 * comic book file. It modifies fields of the ComicsDocument struct with
241 * this information */
242static gboolean
243comics_generate_command_lines (ComicsDocument *comics_document,
244 GError **error)
245{
246 gchar *quoted_file, *quoted_file_aux;
247 gchar *quoted_command;
248 ComicBookDecompressType type;
249
250 type = comics_document->command_usage;
251 comics_document->regex_arg = command_usage_def[type].regex_arg;
252 quoted_command = g_shell_quote (comics_document->selected_command);
253 if (comics_document->regex_arg) {
254 quoted_file = comics_regex_quote (comics_document->archive);
255 quoted_file_aux = g_shell_quote (comics_document->archive);
256 comics_document->list_command =
257 g_strdup_printf (command_usage_def[type].list,
258 comics_document->alternative_command,
259 quoted_file_aux);
260 g_free (quoted_file_aux);
261 } else {
262 quoted_file = g_shell_quote (comics_document->archive);
263 comics_document->list_command =
264 g_strdup_printf (command_usage_def[type].list,
265 quoted_command, quoted_file);
266 }
267 comics_document->extract_command =
268 g_strdup_printf (command_usage_def[type].extract,
269 quoted_command);
270 comics_document->offset = command_usage_def[type].offset;
271 if (command_usage_def[type].decompress_tmp) {
272 comics_document->dir = ev_mkdtemp ("lector-comics-XXXXXX", error);
273 if (comics_document->dir == NULL((void*)0))
274 return FALSE(0);
275
276 /* unrar-free can't create directories, but ev_mkdtemp already created the dir */
277
278 comics_document->decompress_tmp =
279 g_strdup_printf (command_usage_def[type].decompress_tmp,
280 quoted_command, quoted_file,
281 comics_document->dir);
282 g_free (quoted_file);
283 g_free (quoted_command);
284
285 if (!comics_decompress_temp_dir (comics_document->decompress_tmp,
286 comics_document->selected_command, error))
287 return FALSE(0);
288 else
289 return TRUE(!(0));
290 } else {
291 g_free (quoted_file);
292 g_free (quoted_command);
293 return TRUE(!(0));
294 }
295
296}
297
298/* This function chooses an external command for decompressing a comic
299 * book based on its mime tipe. */
300static gboolean
301comics_check_decompress_command (gchar *mime_type,
302 ComicsDocument *comics_document,
303 GError **error)
304{
305 gboolean success;
306 gchar *std_out, *std_err;
307 gint retval;
308 GError *err = NULL((void*)0);
309
310 /* FIXME, use proper cbr/cbz mime types once they're
311 * included in shared-mime-info */
312
313 if (g_content_type_is_a (mime_type, "application/x-cbr") ||
314 g_content_type_is_a (mime_type, "application/x-rar")) {
315 /* The RARLAB provides a no-charge proprietary (freeware)
316 * decompress-only client for Linux called unrar. Another
317 * option is a GPLv2-licensed command-line tool developed by
318 * the Gna! project. Confusingly enough, the free software RAR
319 * decoder is also named unrar. For this reason we need to add
320 * some lines for disambiguation. Sorry for the added the
321 * complexity but it's life :)
322 * Finally, some distributions, like Debian, rename this free
323 * option as unrar-free.
324 * */
325 comics_document->selected_command =
326 g_find_program_in_path ("unrar");
327 if (comics_document->selected_command) {
328 /* We only use std_err to avoid printing useless error
329 * messages on the terminal */
330 success =
331 g_spawn_command_line_sync (
332 comics_document->selected_command,
333 &std_out, &std_err,
334 &retval, &err);
335 if (!success) {
336 g_propagate_error (error, err);
337 g_error_free (err);
338 return FALSE(0);
339 /* I don't check retval status because RARLAB unrar
340 * doesn't have a way to return 0 without involving an
341 * operation with a file*/
342 } else if (WIFEXITED (retval)(((retval) & 0x7f) == 0)) {
343 if (g_strrstr (std_out,"freeware") != NULL((void*)0))
344 /* The RARLAB freeware client */
345 comics_document->command_usage = RARLABS;
346 else
347 /* The Gna! free software client */
348 comics_document->command_usage = GNAUNRAR;
349
350 g_free (std_out);
351 g_free (std_err);
352 return TRUE(!(0));
353 }
354 }
355 /* The Gna! free software client with Debian naming convention */
356 comics_document->selected_command =
357 g_find_program_in_path ("unrar-free");
358 if (comics_document->selected_command) {
359 comics_document->command_usage = GNAUNRAR;
360 return TRUE(!(0));
361 }
362 comics_document->selected_command =
363 g_find_program_in_path ("lsar");
364 if (comics_document->selected_command) {
365 comics_document->command_usage = UNARCHIVER;
366 return TRUE(!(0));
367 }
368 comics_document->selected_command =
369 g_find_program_in_path ("bsdtar");
370 if (comics_document->selected_command) {
371 comics_document->command_usage = TAR;
372 return TRUE(!(0));
373 }
374
375 } else if (g_content_type_is_a (mime_type, "application/x-cbz") ||
376 g_content_type_is_a (mime_type, "application/zip")) {
377 /* InfoZIP's unzip program */
378 comics_document->selected_command =
379 g_find_program_in_path ("unzip");
380 comics_document->alternative_command =
381 g_find_program_in_path ("zipnote");
382 if (comics_document->selected_command &&
383 comics_document->alternative_command) {
384 comics_document->command_usage = UNZIP;
385 return TRUE(!(0));
386 }
387 comics_document->selected_command =
388 g_find_program_in_path ("bsdtar");
389 if (comics_document->selected_command) {
390 comics_document->command_usage = TAR;
391 return TRUE(!(0));
392 }
393 comics_document->selected_command =
394 g_find_program_in_path ("lsar");
395 if (comics_document->selected_command) {
396 comics_document->command_usage = UNARCHIVER;
397 return TRUE(!(0));
398 }
399
400 } else if (g_content_type_is_a (mime_type, "application/x-cb7") ||
401 g_content_type_is_a (mime_type, "application/x-7z-compressed")) {
402 /* 7zr, 7za and 7z are the commands from the p7zip project able
403 * to decompress .7z files */
404 comics_document->selected_command =
405 g_find_program_in_path ("7zr");
406 if (comics_document->selected_command) {
407 comics_document->command_usage = P7ZIP;
408 return TRUE(!(0));
409 }
410 comics_document->selected_command =
411 g_find_program_in_path ("7za");
412 if (comics_document->selected_command) {
413 comics_document->command_usage = P7ZIP;
414 return TRUE(!(0));
415 }
416 comics_document->selected_command =
417 g_find_program_in_path ("7z");
418 if (comics_document->selected_command) {
419 comics_document->command_usage = P7ZIP;
420 return TRUE(!(0));
421 }
422 comics_document->selected_command =
423 g_find_program_in_path ("bsdtar");
424 if (comics_document->selected_command) {
425 comics_document->command_usage = TAR;
426 return TRUE(!(0));
427 }
428 comics_document->selected_command =
429 g_find_program_in_path ("lsar");
430 if (comics_document->selected_command) {
431 comics_document->command_usage = UNARCHIVER;
432 return TRUE(!(0));
433 }
434 } else if (g_content_type_is_a (mime_type, "application/x-cbt") ||
435 g_content_type_is_a (mime_type, "application/x-tar")) {
436 /* tar utility (Tape ARchive) */
437 comics_document->selected_command =
438 g_find_program_in_path ("tar");
439 if (comics_document->selected_command) {
440 comics_document->command_usage = TAR;
441 return TRUE(!(0));
442 }
443 comics_document->selected_command =
444 g_find_program_in_path ("bsdtar");
445 if (comics_document->selected_command) {
446 comics_document->command_usage = TAR;
447 return TRUE(!(0));
448 }
449 comics_document->selected_command =
450 g_find_program_in_path ("lsar");
451 if (comics_document->selected_command) {
452 comics_document->command_usage = UNARCHIVER;
453 return TRUE(!(0));
454 }
455 } else {
456 g_set_error (error,
457 EV_DOCUMENT_ERRORev_document_error_quark (),
458 EV_DOCUMENT_ERROR_INVALID,
459 _("Not a comic book MIME type: %s")((char *) g_dgettext ("lector", "Not a comic book MIME type: %s"
))
,
460 mime_type);
461 return FALSE(0);
462 }
463 g_set_error_literal (error,
464 EV_DOCUMENT_ERRORev_document_error_quark (),
465 EV_DOCUMENT_ERROR_INVALID,
466 _("Can't find an appropriate command to "((char *) g_dgettext ("lector", "Can't find an appropriate command to "
"decompress this type of comic book"))
467 "decompress this type of comic book")((char *) g_dgettext ("lector", "Can't find an appropriate command to "
"decompress this type of comic book"))
);
468 return FALSE(0);
469}
470
471static int
472sort_page_names (gconstpointer a,
473 gconstpointer b)
474{
475 const char *name_1, *name_2;
476 gchar *key_1, *key_2;
477 gboolean sort_last_1, sort_last_2;
478 int compare;
479
480 name_1 = * (const char **) a;
481 name_2 = * (const char **) b;
482
483 #define SORT_LAST_CHAR1 '.'
484 #define SORT_LAST_CHAR2 '#'
485
486 sort_last_1 = name_1[0] == SORT_LAST_CHAR1 || name_1[0] == SORT_LAST_CHAR2;
487 sort_last_2 = name_2[0] == SORT_LAST_CHAR1 || name_2[0] == SORT_LAST_CHAR2;
488
489 #undef SORT_LAST_CHAR1
490 #undef SORT_LAST_CHAR2
491
492 if (sort_last_1 && !sort_last_2)
493 {
494 compare = +1;
495 }
496 else if (!sort_last_1 && sort_last_2)
497 {
498 compare = -1;
499 }
500 else
501 {
502 key_1 = g_utf8_collate_key_for_filename (name_1, -1);
503 key_2 = g_utf8_collate_key_for_filename (name_2, -1);
504
505 compare = strcmp (key_1, key_2);
506
507 g_free (key_1);
508 g_free (key_2);
509 }
510
511 return compare;
512}
513
514static gboolean
515comics_document_load (EvDocument *document,
516 const char *uri,
517 GError **error)
518{
519 ComicsDocument *comics_document = COMICS_DOCUMENT (document)((((ComicsDocument*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((document)), ((comics_document_get_type ()))))))
;
520 GSList *supported_extensions;
521 gchar *std_out;
522 gchar *mime_type;
523 gchar **cb_files, *cb_file;
524 gboolean success;
525 int i, retval;
526 GError *err = NULL((void*)0);
527
528 comics_document->archive = g_filename_from_uri (uri, NULL((void*)0), error);
529 if (!comics_document->archive)
530 return FALSE(0);
531
532 mime_type = ev_file_get_mime_type (uri, FALSE(0), &err);
533 if (!mime_type) {
534 if (err) {
535 g_propagate_error (error, err);
536 } else {
537 g_set_error_literal (error,
538 EV_DOCUMENT_ERRORev_document_error_quark (),
539 EV_DOCUMENT_ERROR_INVALID,
540 _("Unknown MIME Type")((char *) g_dgettext ("lector", "Unknown MIME Type")));
541 }
542
543 return FALSE(0);
544 }
545
546 if (!comics_check_decompress_command (mime_type, comics_document,
547 error)) {
548 g_free (mime_type);
549 return FALSE(0);
550 } else if (!comics_generate_command_lines (comics_document, error)) {
551 g_free (mime_type);
552 return FALSE(0);
553 }
554
555 g_free (mime_type);
556
557 /* Get list of files in archive */
558 success = g_spawn_command_line_sync (comics_document->list_command,
559 &std_out, NULL((void*)0), &retval, error);
560
561 if (!success) {
562 return FALSE(0);
563 } else if (!WIFEXITED(retval)(((retval) & 0x7f) == 0) || WEXITSTATUS(retval)(((retval) & 0xff00) >> 8) != EXIT_SUCCESS0) {
564 g_set_error_literal (error,
565 EV_DOCUMENT_ERRORev_document_error_quark (),
566 EV_DOCUMENT_ERROR_INVALID,
567 _("File corrupted")((char *) g_dgettext ("lector", "File corrupted")));
568 return FALSE(0);
569 }
570
571 /* FIXME: is this safe against filenames containing \n in the archive ? */
572 cb_files = g_strsplit (std_out, EV_EOL"\n", 0);
573
574 g_free (std_out);
575
576 if (!cb_files) {
577 g_set_error_literal (error,
578 EV_DOCUMENT_ERRORev_document_error_quark (),
579 EV_DOCUMENT_ERROR_INVALID,
580 _("No files in archive")((char *) g_dgettext ("lector", "No files in archive")));
581 return FALSE(0);
582 }
583
584 comics_document->page_names = g_ptr_array_sized_new (64);
585
586 supported_extensions = get_supported_image_extensions ();
587 for (i = 0; cb_files[i] != NULL((void*)0); i++) {
588 if (comics_document->offset != NO_OFFSET0) {
589 if (g_utf8_strlen (cb_files[i],-1) >
590 comics_document->offset) {
591 cb_file =
592 g_utf8_offset_to_pointer (cb_files[i],
593 comics_document->offset);
594 } else {
595 continue;
596 }
597 } else {
598 cb_file = cb_files[i];
599 }
600 gchar *suffix = g_strrstr (cb_file, ".");
601 if (!suffix)
602 continue;
603 suffix = g_ascii_strdown (suffix + 1, -1);
604 if (g_slist_find_custom (supported_extensions, suffix,
605 (GCompareFunc) strcmp) != NULL((void*)0)) {
606 g_ptr_array_add (comics_document->page_names,
607 g_strstrip (g_strdup (cb_file))g_strchomp (g_strchug (g_strdup_inline (cb_file))));
608 }
609 g_free (suffix);
610 }
611 g_strfreev (cb_files);
612 g_slist_foreach (supported_extensions, (GFunc) g_free, NULL((void*)0));
613 g_slist_free (supported_extensions);
614
615 if (comics_document->page_names->len == 0) {
616 g_set_error (error,
617 EV_DOCUMENT_ERRORev_document_error_quark (),
618 EV_DOCUMENT_ERROR_INVALID,
619 _("No images found in archive %s")((char *) g_dgettext ("lector", "No images found in archive %s"
))
,
620 uri);
621 return FALSE(0);
622 }
623
624 /* Now sort the pages */
625 g_ptr_array_sort (comics_document->page_names, sort_page_names);
626
627 return TRUE(!(0));
628}
629
630
631static gboolean
632comics_document_save (EvDocument *document,
633 const char *uri,
634 GError **error)
635{
636 ComicsDocument *comics_document = COMICS_DOCUMENT (document)((((ComicsDocument*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((document)), ((comics_document_get_type ()))))))
;
637
638 return ev_xfer_uri_simple (comics_document->archive, uri, error);
639}
640
641static int
642comics_document_get_n_pages (EvDocument *document)
643{
644 ComicsDocument *comics_document = COMICS_DOCUMENT (document)((((ComicsDocument*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((document)), ((comics_document_get_type ()))))))
;
645
646 if (comics_document->page_names == NULL((void*)0))
647 return 0;
648
649 return comics_document->page_names->len;
650}
651
652static void
653comics_document_get_page_size (EvDocument *document,
654 EvPage *page,
655 double *width,
656 double *height)
657{
658 GdkPixbufLoader *loader;
659 char **argv;
660 guchar buf[1024];
661 gboolean success, got_size = FALSE(0);
662 gint outpipe = -1;
663 GPid child_pid;
664 gssize bytes;
665 GdkPixbuf *pixbuf;
666 gchar *filename;
667 ComicsDocument *comics_document = COMICS_DOCUMENT (document)((((ComicsDocument*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((document)), ((comics_document_get_type ()))))))
;
668
669 if (!comics_document->decompress_tmp) {
3
Assuming field 'decompress_tmp' is non-null
4
Taking false branch
670 argv = extract_argv (document, page->index);
671 success = g_spawn_async_with_pipes (NULL((void*)0), argv, NULL((void*)0),
672 G_SPAWN_SEARCH_PATH |
673 G_SPAWN_STDERR_TO_DEV_NULL,
674 NULL((void*)0), NULL((void*)0),
675 &child_pid,
676 NULL((void*)0), &outpipe, NULL((void*)0), NULL((void*)0));
677 g_strfreev (argv);
678 g_return_if_fail (success == TRUE)do { if ((success == (!(0)))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "success == TRUE"
); return; } } while (0)
;
679
680 loader = gdk_pixbuf_loader_new ();
681 g_signal_connect (loader, "area-prepared",g_signal_connect_data ((loader), ("area-prepared"), (((GCallback
) (get_page_size_area_prepared_cb))), (&got_size), ((void
*)0), (GConnectFlags) 0)
682 G_CALLBACK (get_page_size_area_prepared_cb),g_signal_connect_data ((loader), ("area-prepared"), (((GCallback
) (get_page_size_area_prepared_cb))), (&got_size), ((void
*)0), (GConnectFlags) 0)
683 &got_size)g_signal_connect_data ((loader), ("area-prepared"), (((GCallback
) (get_page_size_area_prepared_cb))), (&got_size), ((void
*)0), (GConnectFlags) 0)
;
684
685 while (outpipe >= 0) {
686 bytes = read (outpipe, buf, 1024);
687
688 if (bytes > 0)
689 gdk_pixbuf_loader_write (loader, buf, bytes, NULL((void*)0));
690 if (bytes <= 0 || got_size) {
691 close (outpipe);
692 outpipe = -1;
693 gdk_pixbuf_loader_close (loader, NULL((void*)0));
694 }
695 }
696 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
697 if (pixbuf) {
698 if (width)
699 *width = gdk_pixbuf_get_width (pixbuf);
700 if (height)
701 *height = gdk_pixbuf_get_height (pixbuf);
702 }
703 g_spawn_close_pid (child_pid);
704 g_object_unref (loader);
705 } else {
706 filename = g_build_filename (comics_document->dir,
707 (char *) comics_document->page_names->pdata[page->index],
708 NULL((void*)0));
709 pixbuf = gdk_pixbuf_new_from_file (filename, NULL((void*)0));
710 if (pixbuf) {
5
Assuming 'pixbuf' is null
6
Taking false branch
711 if (width)
712 *width = gdk_pixbuf_get_width (pixbuf);
713 if (height)
714 *height = gdk_pixbuf_get_height (pixbuf);
715 g_object_unref (pixbuf);
716 }
717 g_free (filename);
718 }
719}
7
Returning without writing to '*width'
720
721static void
722get_page_size_area_prepared_cb (GdkPixbufLoader *loader,
723 gpointer data)
724{
725 gboolean *got_size = data;
726 *got_size = TRUE(!(0));
727}
728
729static GdkPixbuf *
730comics_document_render_pixbuf (EvDocument *document,
731 EvRenderContext *rc)
732{
733 GdkPixbufLoader *loader;
734 GdkPixbuf *rotated_pixbuf, *tmp_pixbuf;
735 char **argv;
736 guchar buf[4096];
737 gboolean success;
738 gint outpipe = -1;
739 GPid child_pid;
740 gssize bytes;
741 gint width, height;
742 gchar *filename;
743 ComicsDocument *comics_document = COMICS_DOCUMENT (document)((((ComicsDocument*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((document)), ((comics_document_get_type ()))))))
;
744
745 if (!comics_document->decompress_tmp) {
746 argv = extract_argv (document, rc->page->index);
747 success = g_spawn_async_with_pipes (NULL((void*)0), argv, NULL((void*)0),
748 G_SPAWN_SEARCH_PATH |
749 G_SPAWN_STDERR_TO_DEV_NULL,
750 NULL((void*)0), NULL((void*)0),
751 &child_pid,
752 NULL((void*)0), &outpipe, NULL((void*)0), NULL((void*)0));
753 g_strfreev (argv);
754 g_return_val_if_fail (success == TRUE, NULL)do { if ((success == (!(0)))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "success == TRUE"
); return (((void*)0)); } } while (0)
;
755
756 loader = gdk_pixbuf_loader_new ();
757 g_signal_connect (loader, "size-prepared",g_signal_connect_data ((loader), ("size-prepared"), (((GCallback
) (render_pixbuf_size_prepared_cb))), (&rc->scale), ((
void*)0), (GConnectFlags) 0)
758 G_CALLBACK (render_pixbuf_size_prepared_cb),g_signal_connect_data ((loader), ("size-prepared"), (((GCallback
) (render_pixbuf_size_prepared_cb))), (&rc->scale), ((
void*)0), (GConnectFlags) 0)
759 &rc->scale)g_signal_connect_data ((loader), ("size-prepared"), (((GCallback
) (render_pixbuf_size_prepared_cb))), (&rc->scale), ((
void*)0), (GConnectFlags) 0)
;
760
761 while (outpipe >= 0) {
762 bytes = read (outpipe, buf, 4096);
763
764 if (bytes > 0) {
765 gdk_pixbuf_loader_write (loader, buf, bytes,
766 NULL((void*)0));
767 } else if (bytes <= 0) {
768 close (outpipe);
769 gdk_pixbuf_loader_close (loader, NULL((void*)0));
770 outpipe = -1;
771 }
772 }
773 tmp_pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
774 rotated_pixbuf =
775 gdk_pixbuf_rotate_simple (tmp_pixbuf,
776 360 - rc->rotation);
777 g_spawn_close_pid (child_pid);
778 g_object_unref (loader);
779 } else {
780 filename =
781 g_build_filename (comics_document->dir,
782 (char *) comics_document->page_names->pdata[rc->page->index],
783 NULL((void*)0));
784
785 gdk_pixbuf_get_file_info (filename, &width, &height);
786
787 tmp_pixbuf =
788 gdk_pixbuf_new_from_file_at_size (
789 filename, width * (rc->scale) + 0.5,
790 height * (rc->scale) + 0.5, NULL((void*)0));
791 rotated_pixbuf =
792 gdk_pixbuf_rotate_simple (tmp_pixbuf,
793 360 - rc->rotation);
794 g_free (filename);
795 g_object_unref (tmp_pixbuf);
796 }
797 return rotated_pixbuf;
798}
799
800static cairo_surface_t *
801comics_document_render (EvDocument *document,
802 EvRenderContext *rc)
803{
804 GdkPixbuf *pixbuf;
805 cairo_surface_t *surface;
806
807 pixbuf = comics_document_render_pixbuf (document, rc);
808 surface = ev_document_misc_surface_from_pixbuf (pixbuf);
809 g_object_unref (pixbuf);
810
811 return surface;
812}
813
814static void
815render_pixbuf_size_prepared_cb (GdkPixbufLoader *loader,
816 gint width,
817 gint height,
818 gpointer data)
819{
820 double *scale = data;
821 int w = (width * (*scale) + 0.5);
822 int h = (height * (*scale) + 0.5);
823
824 gdk_pixbuf_loader_set_size (loader, w, h);
825}
826
827/**
828 * comics_remove_dir: Removes a directory recursively.
829 * Returns:
830 * 0 if it was successfully deleted,
831 * -1 if an error occurred
832 */
833static int
834comics_remove_dir (gchar *path_name)
835{
836 GDir *content_dir;
837 const gchar *filename;
838 gchar *filename_with_path;
839
840 if (g_file_test (path_name, G_FILE_TEST_IS_DIR)) {
841 content_dir = g_dir_open (path_name, 0, NULL((void*)0));
842 filename = g_dir_read_name (content_dir);
843 while (filename) {
844 filename_with_path =
845 g_build_filename (path_name,
846 filename, NULL((void*)0));
847 comics_remove_dir (filename_with_path);
848 g_free (filename_with_path);
849 filename = g_dir_read_name (content_dir);
850 }
851 g_dir_close (content_dir);
852 }
853 /* Note from g_remove() documentation: on Windows, it is in general not
854 * possible to remove a file that is open to some process, or mapped
855 * into memory.*/
856 return (g_removeremove (path_name));
857}
858
859static void
860comics_document_finalize (GObject *object)
861{
862 ComicsDocument *comics_document = COMICS_DOCUMENT (object)((((ComicsDocument*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((comics_document_get_type ()))))))
;
863
864 if (comics_document->decompress_tmp) {
865 if (comics_remove_dir (comics_document->dir) == -1)
866 g_warning (_("There was an error deleting “%s”.")((char *) g_dgettext ("lector", "There was an error deleting “%s”."
))
,
867 comics_document->dir);
868 g_free (comics_document->dir);
869 }
870
871 if (comics_document->page_names) {
872 g_ptr_array_foreach (comics_document->page_names, (GFunc) g_free, NULL((void*)0));
873 g_ptr_array_free (comics_document->page_names, TRUE(!(0)));
874 }
875
876 g_free (comics_document->archive);
877 g_free (comics_document->selected_command);
878 g_free (comics_document->alternative_command);
879 g_free (comics_document->extract_command);
880 g_free (comics_document->list_command);
881
882 G_OBJECT_CLASS (comics_document_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((comics_document_parent_class)), (((GType) ((20) <<
(2))))))))
->finalize (object);
883}
884
885static void
886comics_document_class_init (ComicsDocumentClass *klass)
887{
888 GObjectClass *gobject_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((klass)), (((GType) ((20) << (2))))))))
;
889 EvDocumentClass *ev_document_class = EV_DOCUMENT_CLASS (klass)((((EvDocumentClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((klass)), ((ev_document_get_type ()))))))
;
890
891 gobject_class->finalize = comics_document_finalize;
892
893 ev_document_class->load = comics_document_load;
894 ev_document_class->save = comics_document_save;
895 ev_document_class->get_n_pages = comics_document_get_n_pages;
896 ev_document_class->get_page_size = comics_document_get_page_size;
897 ev_document_class->render = comics_document_render;
898}
899
900static void
901comics_document_init (ComicsDocument *comics_document)
902{
903 comics_document->archive = NULL((void*)0);
904 comics_document->page_names = NULL((void*)0);
905 comics_document->extract_command = NULL((void*)0);
906}
907
908/* Returns a list of file extensions supported by gdk-pixbuf */
909static GSList*
910get_supported_image_extensions(void)
911{
912 GSList *extensions = NULL((void*)0);
913 GSList *formats = gdk_pixbuf_get_formats ();
914 GSList *l;
915
916 for (l = formats; l != NULL((void*)0); l = l->next) {
917 int i;
918 gchar **ext = gdk_pixbuf_format_get_extensions (l->data);
919
920 for (i = 0; ext[i] != NULL((void*)0); i++) {
921 extensions = g_slist_append (extensions,
922 g_strdup (ext[i])g_strdup_inline (ext[i]));
923 }
924
925 g_strfreev (ext);
926 }
927
928 g_slist_free (formats);
929 return extensions;
930}
931
932static GdkPixbuf *
933comics_document_thumbnails_get_thumbnail (EvDocumentThumbnails *document,
934 EvRenderContext *rc,
935 gboolean border)
936{
937 GdkPixbuf *thumbnail;
938
939 thumbnail = comics_document_render_pixbuf (EV_DOCUMENT (document)((((EvDocument*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((document)), ((ev_document_get_type ()))))))
, rc);
940
941 if (border) {
942 GdkPixbuf *tmp_pixbuf = thumbnail;
943
944 thumbnail = ev_document_misc_get_thumbnail_frame (-1, -1, tmp_pixbuf);
945 g_object_unref (tmp_pixbuf);
946 }
947
948 return thumbnail;
949}
950
951static void
952comics_document_thumbnails_get_dimensions (EvDocumentThumbnails *document,
953 EvRenderContext *rc,
954 gint *width,
955 gint *height)
956{
957 gdouble page_width, page_height;
1
'page_width' declared without an initial value
958
959 comics_document_get_page_size (EV_DOCUMENT (document)((((EvDocument*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((document)), ((ev_document_get_type ()))))))
, rc->page,
2
Calling 'comics_document_get_page_size'
8
Returning from 'comics_document_get_page_size'
960 &page_width, &page_height);
961
962 if (rc->rotation == 90 || rc->rotation == 270) {
9
Assuming field 'rotation' is not equal to 90
10
Assuming field 'rotation' is not equal to 270
11
Taking false branch
963 *width = (gint) (page_height * rc->scale);
964 *height = (gint) (page_width * rc->scale);
965 } else {
966 *width = (gint) (page_width * rc->scale);
12
The left operand of '*' is a garbage value
967 *height = (gint) (page_height * rc->scale);
968 }
969}
970
971static void
972comics_document_document_thumbnails_iface_init (EvDocumentThumbnailsInterface *iface)
973{
974 iface->get_thumbnail = comics_document_thumbnails_get_thumbnail;
975 iface->get_dimensions = comics_document_thumbnails_get_dimensions;
976}
977
978static char**
979extract_argv (EvDocument *document, gint page)
980{
981 ComicsDocument *comics_document = COMICS_DOCUMENT (document)((((ComicsDocument*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((document)), ((comics_document_get_type ()))))))
;
982 char **argv;
983 char *command_line, *quoted_archive, *quoted_filename;
984 GError *err = NULL((void*)0);
985
986 if (g_strrstr (comics_document->page_names->pdata[page], "--checkpoint-action="))
987 {
988 g_warning ("File unsupported\n");
989 g_application_quit (g_application_get_default ());
990 }
991
992 if (page >= comics_document->page_names->len)
993 return NULL((void*)0);
994
995 if (comics_document->regex_arg) {
996 quoted_archive = g_shell_quote (comics_document->archive);
997 quoted_filename =
998 comics_regex_quote (comics_document->page_names->pdata[page]);
999 } else {
1000 quoted_archive = g_shell_quote (comics_document->archive);
1001 quoted_filename = g_shell_quote (comics_document->page_names->pdata[page]);
1002 }
1003
1004 command_line = g_strdup_printf ("%s %s %s",
1005 comics_document->extract_command,
1006 quoted_archive,
1007 quoted_filename);
1008 g_free (quoted_archive);
1009 g_free (quoted_filename);
1010
1011 g_shell_parse_argv (command_line, NULL((void*)0), &argv, &err);
1012 g_free (command_line);
1013
1014 if (err) {
1015 g_warning (_("Error %s")((char *) g_dgettext ("lector", "Error %s")), err->message);
1016 g_error_free (err);
1017 return NULL((void*)0);
1018 }
1019
1020 return argv;
1021}