Bug Summary

File:src/camel/providers/pop3/camel-pop3-store.c
Warning:line 526, column 18
File position of the stream might be 'indeterminate' after a failed operation. Can cause undefined behavior

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -O3 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name camel-pop3-store.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=none -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/GNOME/evolution-data-server/_build -fcoverage-compilation-dir=/builds/GNOME/evolution-data-server/_build -resource-dir /usr/bin/../lib/clang/22 -D GLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_68 -D GLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_68 -D G_LOG_DOMAIN="camel-pop3-provider" -D LDAP_DEPRECATED -D SOUP_VERSION_MAX_ALLOWED=SOUP_VERSION_3_2 -D SOUP_VERSION_MIN_REQUIRED=SOUP_VERSION_3_2 -D _LARGEFILE64_SOURCE=1 -D camelpop3_EXPORTS -I /builds/GNOME/evolution-data-server/_build -I /builds/GNOME/evolution-data-server/_build/src -I /builds/GNOME/evolution-data-server/_build/src/camel -I /builds/GNOME/evolution-data-server/src -I /builds/GNOME/evolution-data-server/src/camel -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/nss3 -I /usr/include/nspr4 -D NDEBUG -I /usr/include -D WITH_GZFILEOP -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/nss3 -I /usr/include/nspr4 -internal-isystem /usr/bin/../lib/clang/22/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/16/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-unused-parameter -Wno-sign-compare -Wno-missing-field-initializers -Wno-missing-include-dirs -Wno-deprecated-declarations -Wno-cast-function-type -Wwrite-strings -fconst-strings -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -fdwarf2-cfi-asm -o /builds/GNOME/evolution-data-server/_build/scan-build/2026-08-11-054813-10-1 -x c /builds/GNOME/evolution-data-server/src/camel/providers/pop3/camel-pop3-store.c
1/*
2 * SPDX-FileCopyrightText: (C) 1999-2008 Novell, Inc. (www.novell.com)
3 * SPDX-License-Identifier: LGPL-2.0-or-later
4 * SPDX-FileContributor: Dan Winship <danw@ximian.com>
5 * SPDX-FileContributor: Michael Zucchi <notzed@ximian.com>
6 */
7
8#include "evolution-data-server-config.h"
9
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <unistd.h>
14#include <sys/types.h>
15#include <ctype.h>
16
17#include <glib/gi18n-lib.h>
18#include <glib/gstdio.h>
19
20#include "camel-pop3-folder.h"
21#include "camel-pop3-settings.h"
22#include "camel-pop3-store.h"
23
24#ifdef G_OS_WIN32
25#include <winsock2.h>
26#include <ws2tcpip.h>
27#endif
28
29/* Specified in RFC 1939 */
30#define POP3_PORT110 110
31#define POP3S_PORT995 995
32
33/* defines the length of the server error message we can display in the error dialog */
34#define POP3_ERROR_SIZE_LIMIT60 60
35
36struct _CamelPOP3StorePrivate {
37 GMutex property_lock;
38 CamelDataCache *cache;
39 CamelPOP3Engine *engine;
40};
41
42enum {
43 PROP_0,
44 PROP_CONNECTABLE,
45 PROP_HOST_REACHABLE
46};
47
48extern CamelServiceAuthType camel_pop3_password_authtype;
49extern CamelServiceAuthType camel_pop3_apop_authtype;
50
51/* Forward Declarations */
52static void camel_network_service_init (CamelNetworkServiceInterface *iface);
53
54G_DEFINE_TYPE_WITH_CODE (static void camel_pop3_store_init (CamelPOP3Store *self); static
void camel_pop3_store_class_init (CamelPOP3StoreClass *klass
); static GType camel_pop3_store_get_type_once (void); static
gpointer camel_pop3_store_parent_class = ((void*)0); static gint
CamelPOP3Store_private_offset; static void camel_pop3_store_class_intern_init
(gpointer klass) { camel_pop3_store_parent_class = g_type_class_peek_parent
(klass); if (CamelPOP3Store_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CamelPOP3Store_private_offset); camel_pop3_store_class_init
((CamelPOP3StoreClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer camel_pop3_store_get_instance_private
(CamelPOP3Store *self) { return (((gpointer) ((guint8*) (self
) + (glong) (CamelPOP3Store_private_offset)))); } GType camel_pop3_store_get_type
(void) { static gsize static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) *(&static_g_define_type_id) : ((void*)0));
(!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter (&static_g_define_type_id
)); }))) { GType g_define_type_id = camel_pop3_store_get_type_once
(); (__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&static_g_define_type_id) = (g_define_type_id)
) : (void) 0; g_once_init_leave ((&static_g_define_type_id
), (gsize) (g_define_type_id)); })); } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType camel_pop3_store_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((camel_store_get_type ()), g_intern_static_string ("CamelPOP3Store"
), sizeof (CamelPOP3StoreClass), (GClassInitFunc)(void (*)(void
)) camel_pop3_store_class_intern_init, sizeof (CamelPOP3Store
), (GInstanceInitFunc)(void (*)(void)) camel_pop3_store_init,
(GTypeFlags) 0); { {{ CamelPOP3Store_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CamelPOP3StorePrivate)); } { const
GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) camel_network_service_init, ((void*)0), ((void
*)0) }; g_type_add_interface_static (g_define_type_id, (camel_network_service_get_type
()), &g_implement_interface_info); };} } return g_define_type_id
; }
55 CamelPOP3Store,static void camel_pop3_store_init (CamelPOP3Store *self); static
void camel_pop3_store_class_init (CamelPOP3StoreClass *klass
); static GType camel_pop3_store_get_type_once (void); static
gpointer camel_pop3_store_parent_class = ((void*)0); static gint
CamelPOP3Store_private_offset; static void camel_pop3_store_class_intern_init
(gpointer klass) { camel_pop3_store_parent_class = g_type_class_peek_parent
(klass); if (CamelPOP3Store_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CamelPOP3Store_private_offset); camel_pop3_store_class_init
((CamelPOP3StoreClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer camel_pop3_store_get_instance_private
(CamelPOP3Store *self) { return (((gpointer) ((guint8*) (self
) + (glong) (CamelPOP3Store_private_offset)))); } GType camel_pop3_store_get_type
(void) { static gsize static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) *(&static_g_define_type_id) : ((void*)0));
(!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter (&static_g_define_type_id
)); }))) { GType g_define_type_id = camel_pop3_store_get_type_once
(); (__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&static_g_define_type_id) = (g_define_type_id)
) : (void) 0; g_once_init_leave ((&static_g_define_type_id
), (gsize) (g_define_type_id)); })); } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType camel_pop3_store_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((camel_store_get_type ()), g_intern_static_string ("CamelPOP3Store"
), sizeof (CamelPOP3StoreClass), (GClassInitFunc)(void (*)(void
)) camel_pop3_store_class_intern_init, sizeof (CamelPOP3Store
), (GInstanceInitFunc)(void (*)(void)) camel_pop3_store_init,
(GTypeFlags) 0); { {{ CamelPOP3Store_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CamelPOP3StorePrivate)); } { const
GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) camel_network_service_init, ((void*)0), ((void
*)0) }; g_type_add_interface_static (g_define_type_id, (camel_network_service_get_type
()), &g_implement_interface_info); };} } return g_define_type_id
; }
56 camel_pop3_store,static void camel_pop3_store_init (CamelPOP3Store *self); static
void camel_pop3_store_class_init (CamelPOP3StoreClass *klass
); static GType camel_pop3_store_get_type_once (void); static
gpointer camel_pop3_store_parent_class = ((void*)0); static gint
CamelPOP3Store_private_offset; static void camel_pop3_store_class_intern_init
(gpointer klass) { camel_pop3_store_parent_class = g_type_class_peek_parent
(klass); if (CamelPOP3Store_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CamelPOP3Store_private_offset); camel_pop3_store_class_init
((CamelPOP3StoreClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer camel_pop3_store_get_instance_private
(CamelPOP3Store *self) { return (((gpointer) ((guint8*) (self
) + (glong) (CamelPOP3Store_private_offset)))); } GType camel_pop3_store_get_type
(void) { static gsize static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) *(&static_g_define_type_id) : ((void*)0));
(!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter (&static_g_define_type_id
)); }))) { GType g_define_type_id = camel_pop3_store_get_type_once
(); (__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&static_g_define_type_id) = (g_define_type_id)
) : (void) 0; g_once_init_leave ((&static_g_define_type_id
), (gsize) (g_define_type_id)); })); } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType camel_pop3_store_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((camel_store_get_type ()), g_intern_static_string ("CamelPOP3Store"
), sizeof (CamelPOP3StoreClass), (GClassInitFunc)(void (*)(void
)) camel_pop3_store_class_intern_init, sizeof (CamelPOP3Store
), (GInstanceInitFunc)(void (*)(void)) camel_pop3_store_init,
(GTypeFlags) 0); { {{ CamelPOP3Store_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CamelPOP3StorePrivate)); } { const
GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) camel_network_service_init, ((void*)0), ((void
*)0) }; g_type_add_interface_static (g_define_type_id, (camel_network_service_get_type
()), &g_implement_interface_info); };} } return g_define_type_id
; }
57 CAMEL_TYPE_STORE,static void camel_pop3_store_init (CamelPOP3Store *self); static
void camel_pop3_store_class_init (CamelPOP3StoreClass *klass
); static GType camel_pop3_store_get_type_once (void); static
gpointer camel_pop3_store_parent_class = ((void*)0); static gint
CamelPOP3Store_private_offset; static void camel_pop3_store_class_intern_init
(gpointer klass) { camel_pop3_store_parent_class = g_type_class_peek_parent
(klass); if (CamelPOP3Store_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CamelPOP3Store_private_offset); camel_pop3_store_class_init
((CamelPOP3StoreClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer camel_pop3_store_get_instance_private
(CamelPOP3Store *self) { return (((gpointer) ((guint8*) (self
) + (glong) (CamelPOP3Store_private_offset)))); } GType camel_pop3_store_get_type
(void) { static gsize static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) *(&static_g_define_type_id) : ((void*)0));
(!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter (&static_g_define_type_id
)); }))) { GType g_define_type_id = camel_pop3_store_get_type_once
(); (__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&static_g_define_type_id) = (g_define_type_id)
) : (void) 0; g_once_init_leave ((&static_g_define_type_id
), (gsize) (g_define_type_id)); })); } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType camel_pop3_store_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((camel_store_get_type ()), g_intern_static_string ("CamelPOP3Store"
), sizeof (CamelPOP3StoreClass), (GClassInitFunc)(void (*)(void
)) camel_pop3_store_class_intern_init, sizeof (CamelPOP3Store
), (GInstanceInitFunc)(void (*)(void)) camel_pop3_store_init,
(GTypeFlags) 0); { {{ CamelPOP3Store_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CamelPOP3StorePrivate)); } { const
GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) camel_network_service_init, ((void*)0), ((void
*)0) }; g_type_add_interface_static (g_define_type_id, (camel_network_service_get_type
()), &g_implement_interface_info); };} } return g_define_type_id
; }
58 G_ADD_PRIVATE (CamelPOP3Store)static void camel_pop3_store_init (CamelPOP3Store *self); static
void camel_pop3_store_class_init (CamelPOP3StoreClass *klass
); static GType camel_pop3_store_get_type_once (void); static
gpointer camel_pop3_store_parent_class = ((void*)0); static gint
CamelPOP3Store_private_offset; static void camel_pop3_store_class_intern_init
(gpointer klass) { camel_pop3_store_parent_class = g_type_class_peek_parent
(klass); if (CamelPOP3Store_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CamelPOP3Store_private_offset); camel_pop3_store_class_init
((CamelPOP3StoreClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer camel_pop3_store_get_instance_private
(CamelPOP3Store *self) { return (((gpointer) ((guint8*) (self
) + (glong) (CamelPOP3Store_private_offset)))); } GType camel_pop3_store_get_type
(void) { static gsize static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) *(&static_g_define_type_id) : ((void*)0));
(!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter (&static_g_define_type_id
)); }))) { GType g_define_type_id = camel_pop3_store_get_type_once
(); (__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&static_g_define_type_id) = (g_define_type_id)
) : (void) 0; g_once_init_leave ((&static_g_define_type_id
), (gsize) (g_define_type_id)); })); } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType camel_pop3_store_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((camel_store_get_type ()), g_intern_static_string ("CamelPOP3Store"
), sizeof (CamelPOP3StoreClass), (GClassInitFunc)(void (*)(void
)) camel_pop3_store_class_intern_init, sizeof (CamelPOP3Store
), (GInstanceInitFunc)(void (*)(void)) camel_pop3_store_init,
(GTypeFlags) 0); { {{ CamelPOP3Store_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CamelPOP3StorePrivate)); } { const
GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) camel_network_service_init, ((void*)0), ((void
*)0) }; g_type_add_interface_static (g_define_type_id, (camel_network_service_get_type
()), &g_implement_interface_info); };} } return g_define_type_id
; }
59 G_IMPLEMENT_INTERFACE (static void camel_pop3_store_init (CamelPOP3Store *self); static
void camel_pop3_store_class_init (CamelPOP3StoreClass *klass
); static GType camel_pop3_store_get_type_once (void); static
gpointer camel_pop3_store_parent_class = ((void*)0); static gint
CamelPOP3Store_private_offset; static void camel_pop3_store_class_intern_init
(gpointer klass) { camel_pop3_store_parent_class = g_type_class_peek_parent
(klass); if (CamelPOP3Store_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CamelPOP3Store_private_offset); camel_pop3_store_class_init
((CamelPOP3StoreClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer camel_pop3_store_get_instance_private
(CamelPOP3Store *self) { return (((gpointer) ((guint8*) (self
) + (glong) (CamelPOP3Store_private_offset)))); } GType camel_pop3_store_get_type
(void) { static gsize static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) *(&static_g_define_type_id) : ((void*)0));
(!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter (&static_g_define_type_id
)); }))) { GType g_define_type_id = camel_pop3_store_get_type_once
(); (__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&static_g_define_type_id) = (g_define_type_id)
) : (void) 0; g_once_init_leave ((&static_g_define_type_id
), (gsize) (g_define_type_id)); })); } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType camel_pop3_store_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((camel_store_get_type ()), g_intern_static_string ("CamelPOP3Store"
), sizeof (CamelPOP3StoreClass), (GClassInitFunc)(void (*)(void
)) camel_pop3_store_class_intern_init, sizeof (CamelPOP3Store
), (GInstanceInitFunc)(void (*)(void)) camel_pop3_store_init,
(GTypeFlags) 0); { {{ CamelPOP3Store_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CamelPOP3StorePrivate)); } { const
GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) camel_network_service_init, ((void*)0), ((void
*)0) }; g_type_add_interface_static (g_define_type_id, (camel_network_service_get_type
()), &g_implement_interface_info); };} } return g_define_type_id
; }
60 CAMEL_TYPE_NETWORK_SERVICE,static void camel_pop3_store_init (CamelPOP3Store *self); static
void camel_pop3_store_class_init (CamelPOP3StoreClass *klass
); static GType camel_pop3_store_get_type_once (void); static
gpointer camel_pop3_store_parent_class = ((void*)0); static gint
CamelPOP3Store_private_offset; static void camel_pop3_store_class_intern_init
(gpointer klass) { camel_pop3_store_parent_class = g_type_class_peek_parent
(klass); if (CamelPOP3Store_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CamelPOP3Store_private_offset); camel_pop3_store_class_init
((CamelPOP3StoreClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer camel_pop3_store_get_instance_private
(CamelPOP3Store *self) { return (((gpointer) ((guint8*) (self
) + (glong) (CamelPOP3Store_private_offset)))); } GType camel_pop3_store_get_type
(void) { static gsize static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) *(&static_g_define_type_id) : ((void*)0));
(!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter (&static_g_define_type_id
)); }))) { GType g_define_type_id = camel_pop3_store_get_type_once
(); (__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&static_g_define_type_id) = (g_define_type_id)
) : (void) 0; g_once_init_leave ((&static_g_define_type_id
), (gsize) (g_define_type_id)); })); } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType camel_pop3_store_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((camel_store_get_type ()), g_intern_static_string ("CamelPOP3Store"
), sizeof (CamelPOP3StoreClass), (GClassInitFunc)(void (*)(void
)) camel_pop3_store_class_intern_init, sizeof (CamelPOP3Store
), (GInstanceInitFunc)(void (*)(void)) camel_pop3_store_init,
(GTypeFlags) 0); { {{ CamelPOP3Store_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CamelPOP3StorePrivate)); } { const
GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) camel_network_service_init, ((void*)0), ((void
*)0) }; g_type_add_interface_static (g_define_type_id, (camel_network_service_get_type
()), &g_implement_interface_info); };} } return g_define_type_id
; }
61 camel_network_service_init))static void camel_pop3_store_init (CamelPOP3Store *self); static
void camel_pop3_store_class_init (CamelPOP3StoreClass *klass
); static GType camel_pop3_store_get_type_once (void); static
gpointer camel_pop3_store_parent_class = ((void*)0); static gint
CamelPOP3Store_private_offset; static void camel_pop3_store_class_intern_init
(gpointer klass) { camel_pop3_store_parent_class = g_type_class_peek_parent
(klass); if (CamelPOP3Store_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CamelPOP3Store_private_offset); camel_pop3_store_class_init
((CamelPOP3StoreClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer camel_pop3_store_get_instance_private
(CamelPOP3Store *self) { return (((gpointer) ((guint8*) (self
) + (glong) (CamelPOP3Store_private_offset)))); } GType camel_pop3_store_get_type
(void) { static gsize static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) *(&static_g_define_type_id) : ((void*)0));
(!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter (&static_g_define_type_id
)); }))) { GType g_define_type_id = camel_pop3_store_get_type_once
(); (__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&static_g_define_type_id) = (g_define_type_id)
) : (void) 0; g_once_init_leave ((&static_g_define_type_id
), (gsize) (g_define_type_id)); })); } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType camel_pop3_store_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((camel_store_get_type ()), g_intern_static_string ("CamelPOP3Store"
), sizeof (CamelPOP3StoreClass), (GClassInitFunc)(void (*)(void
)) camel_pop3_store_class_intern_init, sizeof (CamelPOP3Store
), (GInstanceInitFunc)(void (*)(void)) camel_pop3_store_init,
(GTypeFlags) 0); { {{ CamelPOP3Store_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CamelPOP3StorePrivate)); } { const
GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) camel_network_service_init, ((void*)0), ((void
*)0) }; g_type_add_interface_static (g_define_type_id, (camel_network_service_get_type
()), &g_implement_interface_info); };} } return g_define_type_id
; }
62
63/* returns error message with ': ' as prefix */
64static gchar *
65get_valid_utf8_error (const gchar *text)
66{
67 gchar *tmp = camel_utf8_make_valid (text);
68 gchar *ret = NULL((void*)0);
69
70 /*TODO If the error message > size limit log it somewhere */
71 if (!tmp || g_utf8_strlen (tmp, -1) > POP3_ERROR_SIZE_LIMIT60) {
72 g_free (tmp);
73 return NULL((void*)0);
74 }
75
76 /* Translators: This is the separator between an error and an explanation */
77 ret = g_strconcat (_(": ")((char *) g_dgettext ("evolution-data-server", ": ")), tmp, NULL((void*)0));
78
79 g_free (tmp);
80 return ret;
81}
82
83static gboolean
84connect_to_server (CamelService *service,
85 GCancellable *cancellable,
86 GError **error)
87{
88 CamelPOP3Store *store = CAMEL_POP3_STORE (service)((((CamelPOP3Store*) (void *) ((service)))));
89 CamelNetworkSettings *network_settings;
90 CamelNetworkSecurityMethod method;
91 CamelSettings *settings;
92 CamelStream *stream = NULL((void*)0);
93 CamelPOP3Engine *pop3_engine = NULL((void*)0);
94 CamelPOP3Command *pc;
95 GIOStream *base_stream;
96 GIOStream *tls_stream;
97 gboolean disable_extensions;
98 gboolean success = TRUE(!(0));
99 gchar *host;
100 guint32 flags = 0;
101 gint ret;
102 GError *local_error = NULL((void*)0);
103
104 settings = camel_service_ref_settings (service);
105
106 network_settings = CAMEL_NETWORK_SETTINGS (settings)((((CamelNetworkSettings*) (void *) ((settings)))));
107 host = camel_network_settings_dup_host (network_settings);
108 method = camel_network_settings_get_security_method (network_settings);
109
110 disable_extensions = camel_pop3_settings_get_disable_extensions (
111 CAMEL_POP3_SETTINGS (settings)((((CamelPOP3Settings*) (void *) ((settings))))));
112
113 g_object_unref (settings);
114
115 base_stream = camel_network_service_connect_sync (
116 CAMEL_NETWORK_SERVICE (service)((((CamelNetworkService*) (void *) ((service))))), cancellable, error);
117
118 if (base_stream != NULL((void*)0)) {
119 stream = camel_stream_new (base_stream);
120 g_object_unref (base_stream);
121 } else {
122 success = FALSE(0);
123 goto exit;
124 }
125
126 /* parent class connect initialization */
127 if (CAMEL_SERVICE_CLASS (camel_pop3_store_parent_class)((((CamelServiceClass*) (void *) ((camel_pop3_store_parent_class
)))))
->
128 connect_sync (service, cancellable, error) == FALSE(0)) {
129 g_object_unref (stream);
130 success = FALSE(0);
131 goto exit;
132 }
133
134 if (disable_extensions)
135 flags |= CAMEL_POP3_ENGINE_DISABLE_EXTENSIONS;
136
137 if (!(pop3_engine = camel_pop3_engine_new (stream, flags, cancellable, &local_error)) ||
138 local_error != NULL((void*)0)) {
139 if (local_error)
140 g_propagate_error (error, local_error);
141 else
142 g_set_error (
143 error, CAMEL_ERROR(camel_error_quark ()), CAMEL_ERROR_GENERIC,
144 _("Failed to read a valid greeting from POP server %s")((char *) g_dgettext ("evolution-data-server", "Failed to read a valid greeting from POP server %s"
))
,
145 host);
146 g_object_unref (stream);
147 success = FALSE(0);
148 goto exit;
149 }
150
151 if (method != CAMEL_NETWORK_SECURITY_METHOD_STARTTLS_ON_STANDARD_PORT) {
152 g_object_unref (stream);
153 goto exit;
154 }
155
156 if (!(pop3_engine->capa & CAMEL_POP3_CAP_STLS)) {
157 g_set_error (
158 error, CAMEL_ERROR(camel_error_quark ()), CAMEL_ERROR_GENERIC,
159 _("Failed to connect to POP server %s in secure mode: %s")((char *) g_dgettext ("evolution-data-server", "Failed to connect to POP server %s in secure mode: %s"
))
,
160 host, _("STLS not supported by server")((char *) g_dgettext ("evolution-data-server", "STLS not supported by server"
))
);
161 goto stls_exception;
162 }
163
164 pc = camel_pop3_engine_command_new (
165 pop3_engine, 0, NULL((void*)0), NULL((void*)0),
166 cancellable, error, "STLS\r\n");
167 while (camel_pop3_engine_iterate (pop3_engine, NULL((void*)0), cancellable, NULL((void*)0)) > 0)
168 ;
169
170 ret = pc->state == CAMEL_POP3_COMMAND_OK;
171 camel_pop3_engine_command_free (pop3_engine, pc);
172
173 if (ret == FALSE(0)) {
174 gchar *tmp;
175
176 tmp = get_valid_utf8_error ((gchar *) pop3_engine->line);
177 g_set_error (
178 error, CAMEL_ERROR(camel_error_quark ()), CAMEL_ERROR_GENERIC,
179 /* Translators: Last %s is an optional
180 * explanation beginning with ": " separator. */
181 _("Failed to connect to POP server %s in secure mode%s")((char *) g_dgettext ("evolution-data-server", "Failed to connect to POP server %s in secure mode%s"
))
,
182 host, (tmp != NULL((void*)0)) ? tmp : "");
183 g_free (tmp);
184 goto stls_exception;
185 }
186
187 /* Okay, now toggle SSL/TLS mode */
188 base_stream = camel_stream_ref_base_stream (stream);
189 tls_stream = camel_network_service_starttls (
190 CAMEL_NETWORK_SERVICE (service)((((CamelNetworkService*) (void *) ((service))))), base_stream, error);
191 g_object_unref (base_stream);
192
193 if (tls_stream != NULL((void*)0)) {
194 camel_stream_set_base_stream (stream, tls_stream);
195 /* Truncate any left cached input from the insecure part of the session */
196 camel_pop3_stream_discard_cache (pop3_engine->stream);
197 g_object_unref (tls_stream);
198 } else {
199 g_prefix_error (
200 error,
201 _("Failed to connect to POP server %s in secure mode: ")((char *) g_dgettext ("evolution-data-server", "Failed to connect to POP server %s in secure mode: "
))
,
202 host);
203 goto stls_exception;
204 }
205
206 g_clear_object (&stream)do { _Static_assert (sizeof *((&stream)) == sizeof (gpointer
), "Expression evaluates to false"); __typeof__ (((&stream
))) _pp = ((&stream)); __typeof__ (*((&stream))) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr)
; } while (0)
;
207
208 /* rfc2595, section 4 states that after a successful STLS
209 * command, the client MUST discard prior CAPA responses */
210 if (!camel_pop3_engine_reget_capabilities (pop3_engine, cancellable, error))
211 goto exception;
212
213 goto exit;
214
215stls_exception:
216 /* As soon as we send a STLS command, all hope
217 * is lost of a clean QUIT if problems arise. */
218 /* if (clean_quit) {
219 / * try to disconnect cleanly * /
220 pc = camel_pop3_engine_command_new (
221 pop3_engine, 0, NULL, NULL,
222 cancellable, NULL, "QUIT\r\n");
223 while (camel_pop3_engine_iterate (pop3_engine, NULL, cancellable, NULL) > 0)
224 ;
225 camel_pop3_engine_command_free (pop3_engine, pc);
226 }*/
227
228exception:
229 g_clear_object (&stream)do { _Static_assert (sizeof *((&stream)) == sizeof (gpointer
), "Expression evaluates to false"); __typeof__ (((&stream
))) _pp = ((&stream)); __typeof__ (*((&stream))) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr)
; } while (0)
;
230 g_clear_object (&pop3_engine)do { _Static_assert (sizeof *((&pop3_engine)) == sizeof (
gpointer), "Expression evaluates to false"); __typeof__ (((&
pop3_engine))) _pp = ((&pop3_engine)); __typeof__ (*((&
pop3_engine))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref
) (_ptr); } while (0)
;
231
232 success = FALSE(0);
233
234exit:
235 g_free (host);
236
237 g_mutex_lock (&store->priv->property_lock);
238 if (pop3_engine != NULL((void*)0))
239 store->priv->engine = g_object_ref (pop3_engine)((__typeof__ (pop3_engine)) (g_object_ref) (pop3_engine));
240 g_mutex_unlock (&store->priv->property_lock);
241
242 g_clear_object (&pop3_engine)do { _Static_assert (sizeof *((&pop3_engine)) == sizeof (
gpointer), "Expression evaluates to false"); __typeof__ (((&
pop3_engine))) _pp = ((&pop3_engine)); __typeof__ (*((&
pop3_engine))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref
) (_ptr); } while (0)
;
243
244 return success;
245}
246
247static CamelAuthenticationResult
248try_sasl (CamelPOP3Store *store,
249 const gchar *mechanism,
250 GCancellable *cancellable,
251 GError **error)
252{
253 CamelPOP3Engine *pop3_engine;
254 CamelPOP3Stream *pop3_stream;
255 CamelNetworkSettings *network_settings;
256 CamelAuthenticationResult result;
257 CamelSettings *settings;
258 CamelService *service;
259 guchar *line, *resp;
260 CamelSasl *sasl = NULL((void*)0);
261 gchar *string;
262 gchar *host;
263 guint len;
264 gint ret;
265
266 service = CAMEL_SERVICE (store)((((CamelService*) (void *) ((store)))));
267
268 settings = camel_service_ref_settings (service);
269
270 network_settings = CAMEL_NETWORK_SETTINGS (settings)((((CamelNetworkSettings*) (void *) ((settings)))));
271 host = camel_network_settings_dup_host (network_settings);
272
273 g_object_unref (settings);
274
275 pop3_engine = camel_pop3_store_ref_engine (store);
276 if (!pop3_engine) {
277 g_set_error_literal (
278 error, CAMEL_SERVICE_ERROR(camel_service_error_quark ()),
279 CAMEL_SERVICE_ERROR_UNAVAILABLE,
280 _("You must be working online to complete this operation")((char *) g_dgettext ("evolution-data-server", "You must be working online to complete this operation"
))
);
281 result = CAMEL_AUTHENTICATION_ERROR;
282 goto exit;
283 }
284
285 pop3_stream = pop3_engine->stream;
286
287 sasl = camel_sasl_new ("pop", mechanism, service);
288 if (sasl == NULL((void*)0)) {
289 g_set_error (
290 error, CAMEL_SERVICE_ERROR(camel_service_error_quark ()),
291 CAMEL_SERVICE_ERROR_URL_INVALID,
292 _("No support for %s authentication")((char *) g_dgettext ("evolution-data-server", "No support for %s authentication"
))
, mechanism);
293 result = CAMEL_AUTHENTICATION_ERROR;
294 goto exit;
295 }
296
297 string = g_strdup_printf ("AUTH %s\r\n", camel_sasl_is_xoauth2_alias (mechanism) ? "XOAUTH2" : mechanism);
298 ret = camel_stream_write_string (
299 CAMEL_STREAM (pop3_stream)((((CamelStream*) (void *) ((pop3_stream))))), string, cancellable, error);
300 g_free (string);
301
302 if (ret == -1)
303 goto ioerror;
304
305 while (1) {
306 GError *local_error = NULL((void*)0);
307
308 if (camel_pop3_stream_line (pop3_stream, &line, &len, cancellable, error) == -1)
309 goto ioerror;
310
311 if (strncmp ((gchar *) line, "+OK", 3) == 0) {
312 result = CAMEL_AUTHENTICATION_ACCEPTED;
313 break;
314 }
315
316 if (strncmp ((gchar *) line, "-ERR", 4) == 0) {
317 result = CAMEL_AUTHENTICATION_REJECTED;
318 break;
319 }
320
321 /* If we don't get continuation, or the sasl object's run out
322 * of work, or we don't get a challenge, its a protocol error,
323 * so fail, and try reset the server. */
324 if (strncmp ((gchar *) line, "+ ", 2) != 0
325 || camel_sasl_get_authenticated (sasl)
326 || (resp = (guchar *) camel_sasl_challenge_base64_sync (sasl, (const gchar *) line + 2, cancellable, &local_error)) == NULL((void*)0)) {
327 if (camel_stream_write_string (CAMEL_STREAM (pop3_stream)((((CamelStream*) (void *) ((pop3_stream))))), "*\r\n", cancellable, NULL((void*)0))) {
328 /* coverity[unchecked_value] */
329 if (!camel_pop3_stream_line (pop3_stream, &line, &len, cancellable, NULL((void*)0))) {
330 ;
331 }
332 }
333
334 if (local_error) {
335 g_propagate_error (error, local_error);
336 local_error = NULL((void*)0);
337 goto ioerror;
338 }
339
340 g_set_error (
341 error, CAMEL_SERVICE_ERROR(camel_service_error_quark ()),
342 CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
343 _("Cannot login to POP server %s: "((char *) g_dgettext ("evolution-data-server", "Cannot login to POP server %s: "
"SASL Protocol error"))
344 "SASL Protocol error")((char *) g_dgettext ("evolution-data-server", "Cannot login to POP server %s: "
"SASL Protocol error"))
, host);
345 result = CAMEL_AUTHENTICATION_ERROR;
346 goto exit;
347 }
348
349 string = g_strdup_printf ("%s\r\n", resp);
350 ret = camel_stream_write_string (
351 CAMEL_STREAM (pop3_stream)((((CamelStream*) (void *) ((pop3_stream))))), string, cancellable, error);
352 g_free (string);
353
354 g_free (resp);
355
356 if (ret == -1)
357 goto ioerror;
358
359 }
360
361 goto exit;
362
363ioerror:
364 g_prefix_error (
365 error, _("Failed to authenticate on POP server %s: ")((char *) g_dgettext ("evolution-data-server", "Failed to authenticate on POP server %s: "
))
, host);
366 result = CAMEL_AUTHENTICATION_ERROR;
367
368exit:
369 if (sasl != NULL((void*)0))
370 g_object_unref (sasl);
371
372 g_free (host);
373
374 g_clear_object (&pop3_engine)do { _Static_assert (sizeof *((&pop3_engine)) == sizeof (
gpointer), "Expression evaluates to false"); __typeof__ (((&
pop3_engine))) _pp = ((&pop3_engine)); __typeof__ (*((&
pop3_engine))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref
) (_ptr); } while (0)
;
375
376 return result;
377}
378
379static void
380pop3_store_set_property (GObject *object,
381 guint property_id,
382 const GValue *value,
383 GParamSpec *pspec)
384{
385 switch (property_id) {
386 case PROP_CONNECTABLE:
387 camel_network_service_set_connectable (
388 CAMEL_NETWORK_SERVICE (object)((((CamelNetworkService*) (void *) ((object))))),
389 g_value_get_object (value));
390 return;
391 }
392
393 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((property_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "/builds/GNOME/evolution-data-server/src/camel/providers/pop3/camel-pop3-store.c"
, 393, ("property"), _glib__property_id, _glib__pspec->name
, g_type_name ((((((GTypeClass*) (((GTypeInstance*) (_glib__pspec
))->g_class))->g_type)))), (g_type_name ((((((GTypeClass
*) (((GTypeInstance*) (_glib__object))->g_class))->g_type
)))))); } while (0)
;
394}
395
396static void
397pop3_store_get_property (GObject *object,
398 guint property_id,
399 GValue *value,
400 GParamSpec *pspec)
401{
402 switch (property_id) {
403 case PROP_CONNECTABLE:
404 g_value_take_object (
405 value,
406 camel_network_service_ref_connectable (
407 CAMEL_NETWORK_SERVICE (object)((((CamelNetworkService*) (void *) ((object)))))));
408 return;
409
410 case PROP_HOST_REACHABLE:
411 g_value_set_boolean (
412 value,
413 camel_network_service_get_host_reachable (
414 CAMEL_NETWORK_SERVICE (object)((((CamelNetworkService*) (void *) ((object)))))));
415 return;
416 }
417
418 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((property_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "/builds/GNOME/evolution-data-server/src/camel/providers/pop3/camel-pop3-store.c"
, 418, ("property"), _glib__property_id, _glib__pspec->name
, g_type_name ((((((GTypeClass*) (((GTypeInstance*) (_glib__pspec
))->g_class))->g_type)))), (g_type_name ((((((GTypeClass
*) (((GTypeInstance*) (_glib__object))->g_class))->g_type
)))))); } while (0)
;
419}
420
421static void
422pop3_store_dispose (GObject *object)
423{
424 CamelPOP3StorePrivate *priv;
425
426 priv = CAMEL_POP3_STORE (object)((((CamelPOP3Store*) (void *) ((object)))))->priv;
427
428 /* Force disconnect so we don't have it run
429 * later, after we've cleaned up some stuff. */
430 camel_service_disconnect_sync (
431 CAMEL_SERVICE (object)((((CamelService*) (void *) ((object))))), TRUE(!(0)), NULL((void*)0), NULL((void*)0));
432
433 g_clear_object (&priv->cache)do { _Static_assert (sizeof *((&priv->cache)) == sizeof
(gpointer), "Expression evaluates to false"); __typeof__ (((
&priv->cache))) _pp = ((&priv->cache)); __typeof__
(*((&priv->cache))) _ptr = *_pp; *_pp = ((void*)0); if
(_ptr) (g_object_unref) (_ptr); } while (0)
;
434 g_clear_object (&priv->engine)do { _Static_assert (sizeof *((&priv->engine)) == sizeof
(gpointer), "Expression evaluates to false"); __typeof__ (((
&priv->engine))) _pp = ((&priv->engine)); __typeof__
(*((&priv->engine))) _ptr = *_pp; *_pp = ((void*)0); if
(_ptr) (g_object_unref) (_ptr); } while (0)
;
435
436 /* Chain up to parent's dispose() method. */
437 G_OBJECT_CLASS (camel_pop3_store_parent_class)((((GObjectClass*) (void *) ((camel_pop3_store_parent_class))
)))
->dispose (object);
438}
439
440static void
441pop3_store_finalize (GObject *object)
442{
443 CamelPOP3StorePrivate *priv;
444
445 priv = CAMEL_POP3_STORE (object)((((CamelPOP3Store*) (void *) ((object)))))->priv;
446
447 g_mutex_clear (&priv->property_lock);
448
449 /* Chain up to parent's finalize() method. */
450 G_OBJECT_CLASS (camel_pop3_store_parent_class)((((GObjectClass*) (void *) ((camel_pop3_store_parent_class))
)))
->finalize (object);
451}
452
453static gchar *
454pop3_store_get_name (CamelService *service,
455 gboolean brief)
456{
457 CamelNetworkSettings *network_settings;
458 CamelSettings *settings;
459 gchar *host;
460 gchar *user;
461 gchar *name;
462
463 settings = camel_service_ref_settings (service);
464
465 network_settings = CAMEL_NETWORK_SETTINGS (settings)((((CamelNetworkSettings*) (void *) ((settings)))));
466 host = camel_network_settings_dup_host (network_settings);
467 user = camel_network_settings_dup_user (network_settings);
468
469 g_object_unref (settings);
470
471 if (brief)
472 name = g_strdup_printf (
473 _("POP3 server %s")((char *) g_dgettext ("evolution-data-server", "POP3 server %s"
))
, host);
474 else
475 name = g_strdup_printf (
476 _("POP3 server for %s on %s")((char *) g_dgettext ("evolution-data-server", "POP3 server for %s on %s"
))
, user, host);
477
478 g_free (host);
479 g_free (user);
480
481 return name;
482}
483
484/* Called by camel_data_cache_foreach_remove() for each cache file.
485 * Returns TRUE to delete the file, FALSE to keep it. */
486static gboolean
487pop3_migrate_cache_file_cb (CamelDataCache *cdc,
488 const gchar *filename,
489 gpointer user_data)
490{
491 guchar first_byte;
492 FILE *f;
493
494 f = fopen (filename, "rb");
495 if (f
0.1
'f' is not equal to NULL
== NULL((void*)0))
1
Taking false branch
496 return FALSE(0);
497
498 if (fread (&first_byte, 1, 1, f) != 1) {
2
Taking false branch
499 fclose (f);
500 return FALSE(0);
501 }
502
503 fclose (f);
504
505 if (first_byte == '*')
3
Assuming the condition is false
4
Taking false branch
506 return TRUE(!(0)); /* incomplete old download — let foreach_remove delete it */
507
508 if (first_byte == '#') {
5
Assuming the condition is true
6
Taking true branch
509 /* Complete old download: strip the sentinel byte by rewriting via a temp file. */
510 gchar *tmp_path;
511 gint tmp_fd;
512
513 tmp_path = g_strdup_printf ("%s.XXXXXX", filename);
514 tmp_fd = g_mkstemp (tmp_path);
515 if (tmp_fd != -1) {
7
Assuming the condition is true
8
Taking true branch
516 FILE *src, *dst;
517
518 close (tmp_fd);
519 src = fopen (filename, "rb");
520 dst = fopen (tmp_path, "wb");
521 if (src
8.1
'src' is not equal to NULL
!= NULL((void*)0) && dst
8.2
'dst' is not equal to NULL
!= NULL((void*)0)) {
9
Taking true branch
522 guchar buf[4096];
523 gsize nr;
524
525 fseek (src, 1, SEEK_SET0);
526 while ((nr = fread (buf, 1, sizeof (buf), src)) > 0)
10
Assuming this stream operation fails
11
Assuming the condition is true
12
Loop condition is true. Entering loop body
13
File position of the stream might be 'indeterminate' after a failed operation. Can cause undefined behavior
527 fwrite (buf, 1, nr, dst);
528 fclose (src);
529 fclose (dst);
530 g_renamerename (tmp_path, filename);
531 } else {
532 if (src != NULL((void*)0))
533 fclose (src);
534 if (dst != NULL((void*)0)) {
535 fclose (dst);
536 g_unlink (tmp_path);
537 }
538 }
539 }
540
541 g_free (tmp_path);
542 }
543
544 return FALSE(0);
545}
546
547/* One-shot migration of old POP3 cache files that carry a sentinel byte.
548 *
549 * Before the atomic write API, cache files started with either '*' (write
550 * in progress, file is incomplete) or '#' (write finished, message follows
551 * from byte 1). New files contain the raw message from byte 0. This
552 * function rewrites every old '#'-prefixed file in place (stripping the
553 * sentinel) and deletes every '*'-prefixed file. A version marker is
554 * written afterwards so the scan is skipped on future connects. */
555static void
556pop3_store_migrate_cache_format (CamelDataCache *cache)
557{
558 const gchar *base_path;
559 gchar *ver_filename;
560 gchar *ver_content = NULL((void*)0);
561
562 base_path = camel_data_cache_get_path (cache);
563 ver_filename = g_build_filename (base_path, ".cache-format-version", NULL((void*)0));
564
565 if (g_file_get_contents (ver_filename, &ver_content, NULL((void*)0), NULL((void*)0)) &&
566 atoi (ver_content) >= 2) {
567 g_free (ver_content);
568 g_free (ver_filename);
569 return;
570 }
571
572 g_free (ver_content);
573
574 camel_data_cache_foreach_remove (cache, "cache", pop3_migrate_cache_file_cb, NULL((void*)0));
575
576 g_file_set_contents (ver_filename, "2\n", -1, NULL((void*)0));
577 g_free (ver_filename);
578}
579
580static gboolean
581pop3_store_connect_sync (CamelService *service,
582 GCancellable *cancellable,
583 GError **error)
584{
585 CamelPOP3Store *store = (CamelPOP3Store *) service;
586 CamelPOP3Engine *pop3_engine;
587 CamelSettings *settings;
588 CamelSession *session;
589 const gchar *user_data_dir;
590 gboolean success = TRUE(!(0));
591 gchar *mechanism;
592
593 /* Chain up to parent's method. */
594 if (!CAMEL_SERVICE_CLASS (camel_pop3_store_parent_class)((((CamelServiceClass*) (void *) ((camel_pop3_store_parent_class
)))))
->connect_sync (service, cancellable, error))
595 return FALSE(0);
596
597 session = camel_service_ref_session (service);
598 user_data_dir = camel_service_get_user_data_dir (service);
599
600 settings = camel_service_ref_settings (service);
601
602 mechanism = camel_network_settings_dup_auth_mechanism (
603 CAMEL_NETWORK_SETTINGS (settings)((((CamelNetworkSettings*) (void *) ((settings))))));
604
605 g_object_unref (settings);
606
607 if (!session || !camel_session_get_online (session)) {
608 g_set_error (
609 error, CAMEL_SERVICE_ERROR(camel_service_error_quark ()),
610 CAMEL_SERVICE_ERROR_UNAVAILABLE,
611 _("You must be working online to complete this operation")((char *) g_dgettext ("evolution-data-server", "You must be working online to complete this operation"
))
);
612 success = FALSE(0);
613 goto exit;
614 }
615
616 g_mutex_lock (&store->priv->property_lock);
617
618 if (store->priv->cache == NULL((void*)0)) {
619 CamelDataCache *cache;
620
621 cache = camel_data_cache_new (user_data_dir, error);
622 if (cache != NULL((void*)0)) {
623 /* Ensure cache will never expire, otherwise
624 * it causes redownload of messages. */
625 camel_data_cache_set_expire_age (cache, -1);
626 camel_data_cache_set_expire_access (cache, -1);
627
628 store->priv->cache = g_object_ref (cache)((__typeof__ (cache)) (g_object_ref) (cache));
629
630 pop3_store_migrate_cache_format (cache);
631
632 g_object_unref (cache);
633 }
634 }
635
636 g_mutex_unlock (&store->priv->property_lock);
637
638 success = connect_to_server (service, cancellable, error);
639
640 if (!success)
641 goto exit;
642
643 success = camel_session_authenticate_sync (
644 session, service, mechanism, cancellable, error);
645
646 if (!success)
647 goto exit;
648
649 /* Now that we are in the TRANSACTION state,
650 * try regetting the capabilities */
651 pop3_engine = camel_pop3_store_ref_engine (store);
652 if (pop3_engine) {
653 pop3_engine->state = CAMEL_POP3_ENGINE_TRANSACTION;
654 if (!camel_pop3_engine_reget_capabilities (pop3_engine, cancellable, error))
655 success = FALSE(0);
656 g_clear_object (&pop3_engine)do { _Static_assert (sizeof *((&pop3_engine)) == sizeof (
gpointer), "Expression evaluates to false"); __typeof__ (((&
pop3_engine))) _pp = ((&pop3_engine)); __typeof__ (*((&
pop3_engine))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref
) (_ptr); } while (0)
;
657 } else {
658 g_set_error_literal (
659 error, CAMEL_SERVICE_ERROR(camel_service_error_quark ()),
660 CAMEL_SERVICE_ERROR_UNAVAILABLE,
661 _("You must be working online to complete this operation")((char *) g_dgettext ("evolution-data-server", "You must be working online to complete this operation"
))
);
662 success = FALSE(0);
663 }
664
665exit:
666 g_free (mechanism);
667
668 g_object_unref (session);
669
670 if (!success) {
671 /* to not leak possible connection to the server */
672 g_mutex_lock (&store->priv->property_lock);
673 g_clear_object (&store->priv->engine)do { _Static_assert (sizeof *((&store->priv->engine
)) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(((&store->priv->engine))) _pp = ((&store->
priv->engine)); __typeof__ (*((&store->priv->engine
))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref
) (_ptr); } while (0)
;
674 g_mutex_unlock (&store->priv->property_lock);
675 }
676
677 return success;
678}
679
680static gboolean
681pop3_store_disconnect_sync (CamelService *service,
682 gboolean clean,
683 GCancellable *cancellable,
684 GError **error)
685{
686 CamelServiceClass *service_class;
687 CamelPOP3Store *store = CAMEL_POP3_STORE (service)((((CamelPOP3Store*) (void *) ((service)))));
688 gboolean success;
689
690 if (clean) {
691 CamelPOP3Engine *pop3_engine;
692 CamelPOP3Command *pc;
693
694 pop3_engine = camel_pop3_store_ref_engine (store);
695
696 if (pop3_engine) {
697 if (camel_pop3_engine_busy_lock (pop3_engine, cancellable, NULL((void*)0))) {
698 pc = camel_pop3_engine_command_new (
699 pop3_engine, 0, NULL((void*)0), NULL((void*)0),
700 cancellable, error, "QUIT\r\n");
701 while (camel_pop3_engine_iterate (pop3_engine, NULL((void*)0), cancellable, NULL((void*)0)) > 0)
702 ;
703 camel_pop3_engine_command_free (pop3_engine, pc);
704 camel_pop3_engine_busy_unlock (pop3_engine);
705 }
706
707 g_clear_object (&pop3_engine)do { _Static_assert (sizeof *((&pop3_engine)) == sizeof (
gpointer), "Expression evaluates to false"); __typeof__ (((&
pop3_engine))) _pp = ((&pop3_engine)); __typeof__ (*((&
pop3_engine))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref
) (_ptr); } while (0)
;
708 }
709 }
710
711 /* Chain up to parent's disconnect() method. */
712 service_class = CAMEL_SERVICE_CLASS (camel_pop3_store_parent_class)((((CamelServiceClass*) (void *) ((camel_pop3_store_parent_class
)))))
;
713
714 success = service_class->disconnect_sync (service, clean, cancellable, error);
715
716 g_mutex_lock (&store->priv->property_lock);
717 g_clear_object (&store->priv->engine)do { _Static_assert (sizeof *((&store->priv->engine
)) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(((&store->priv->engine))) _pp = ((&store->
priv->engine)); __typeof__ (*((&store->priv->engine
))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref
) (_ptr); } while (0)
;
718 g_mutex_unlock (&store->priv->property_lock);
719
720 return success;
721}
722
723static CamelAuthenticationResult
724pop3_store_authenticate_sync (CamelService *service,
725 const gchar *mechanism,
726 GCancellable *cancellable,
727 GError **error)
728{
729 CamelPOP3Store *store = CAMEL_POP3_STORE (service)((((CamelPOP3Store*) (void *) ((service)))));
730 CamelNetworkSettings *network_settings;
731 CamelAuthenticationResult result;
732 CamelSettings *settings;
733 CamelPOP3Command *pcu = NULL((void*)0);
734 CamelPOP3Command *pcp = NULL((void*)0);
735 CamelPOP3Engine *pop3_engine;
736 const gchar *password;
737 gboolean enable_utf8;
738 gchar *host;
739 gchar *user;
740 gint status;
741
742 password = camel_service_get_password (service);
743
744 settings = camel_service_ref_settings (service);
745 enable_utf8 = camel_pop3_settings_get_enable_utf8 (CAMEL_POP3_SETTINGS (settings)((((CamelPOP3Settings*) (void *) ((settings))))));
746
747 network_settings = CAMEL_NETWORK_SETTINGS (settings)((((CamelNetworkSettings*) (void *) ((settings)))));
748 host = camel_network_settings_dup_host (network_settings);
749 user = camel_network_settings_dup_user (network_settings);
750
751 g_object_unref (settings);
752
753 pop3_engine = camel_pop3_store_ref_engine (store);
754 if (!pop3_engine) {
755 g_set_error_literal (
756 error, CAMEL_SERVICE_ERROR(camel_service_error_quark ()),
757 CAMEL_SERVICE_ERROR_UNAVAILABLE,
758 _("You must be working online to complete this operation")((char *) g_dgettext ("evolution-data-server", "You must be working online to complete this operation"
))
);
759 result = CAMEL_AUTHENTICATION_ERROR;
760 goto exit;
761 }
762
763 if (!camel_pop3_engine_busy_lock (pop3_engine, cancellable, error)) {
764 g_free (host);
765 g_free (user);
766 g_clear_object (&pop3_engine)do { _Static_assert (sizeof *((&pop3_engine)) == sizeof (
gpointer), "Expression evaluates to false"); __typeof__ (((&
pop3_engine))) _pp = ((&pop3_engine)); __typeof__ (*((&
pop3_engine))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref
) (_ptr); } while (0)
;
767
768 return CAMEL_AUTHENTICATION_ERROR;
769 }
770
771 if ((pop3_engine->capa & CAMEL_POP3_CAP_UTF8) != 0 && enable_utf8) {
772 pcu = camel_pop3_engine_command_new (
773 pop3_engine, 0, NULL((void*)0), NULL((void*)0), cancellable, error,
774 "UTF8\r\n");
775 if (error && *error) {
776 g_prefix_error (
777 error,
778 _("Unable to connect to POP server %s.\n"((char *) g_dgettext ("evolution-data-server", "Unable to connect to POP server %s.\n"
"Error enabling UTF-8 mode: "))
779 "Error enabling UTF-8 mode: ")((char *) g_dgettext ("evolution-data-server", "Unable to connect to POP server %s.\n"
"Error enabling UTF-8 mode: "))
, host);
780 result = CAMEL_AUTHENTICATION_ERROR;
781 goto exit;
782 }
783 while (camel_pop3_engine_iterate (pop3_engine, NULL((void*)0), cancellable, NULL((void*)0)) > 0)
784 ;
785 camel_pop3_engine_command_free (pop3_engine, pcu);
786 pcu = NULL((void*)0);
787 }
788
789 if (mechanism == NULL((void*)0)) {
790 if (password == NULL((void*)0)) {
791 g_set_error_literal (
792 error, CAMEL_SERVICE_ERROR(camel_service_error_quark ()),
793 CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
794 _("Authentication password not available")((char *) g_dgettext ("evolution-data-server", "Authentication password not available"
))
);
795 result = CAMEL_AUTHENTICATION_ERROR;
796 goto exit;
797 }
798
799 /* Sanitize user and password to prevent CRLF injection
800 * into POP3 protocol commands */
801 if (strchr (user, '\r') || strchr (user, '\n') ||
802 strchr (password, '\r') || strchr (password, '\n')) {
803 g_set_error_literal (
804 error, CAMEL_SERVICE_ERROR(camel_service_error_quark ()),
805 CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
806 _("Username or password contains invalid characters")((char *) g_dgettext ("evolution-data-server", "Username or password contains invalid characters"
))
);
807 result = CAMEL_AUTHENTICATION_ERROR;
808 goto exit;
809 }
810
811 /* pop engine will take care of pipelining ability */
812 pcu = camel_pop3_engine_command_new (
813 pop3_engine, 0, NULL((void*)0), NULL((void*)0), cancellable, error,
814 "USER %s\r\n", user);
815 if (error && *error) {
816 g_prefix_error (
817 error,
818 _("Unable to connect to POP server %s.\n"((char *) g_dgettext ("evolution-data-server", "Unable to connect to POP server %s.\n"
"Error sending password: "))
819 "Error sending password: ")((char *) g_dgettext ("evolution-data-server", "Unable to connect to POP server %s.\n"
"Error sending password: "))
, host);
820 result = CAMEL_AUTHENTICATION_ERROR;
821 goto exit;
822 }
823
824 pcp = camel_pop3_engine_command_new (
825 pop3_engine, 0, NULL((void*)0), NULL((void*)0), cancellable, error,
826 "PASS %s\r\n", password);
827
828 if (error && *error) {
829 g_prefix_error (
830 error,
831 _("Unable to connect to POP server %s.\n"((char *) g_dgettext ("evolution-data-server", "Unable to connect to POP server %s.\n"
"Error sending password: "))
832 "Error sending password: ")((char *) g_dgettext ("evolution-data-server", "Unable to connect to POP server %s.\n"
"Error sending password: "))
, host);
833 result = CAMEL_AUTHENTICATION_ERROR;
834 goto exit;
835 }
836 } else if (strcmp (mechanism, "+APOP") == 0 && pop3_engine->apop) {
837 GChecksum *checksum;
838 gchar *d;
839
840 if (password == NULL((void*)0)) {
841 g_set_error_literal (
842 error, CAMEL_SERVICE_ERROR(camel_service_error_quark ()),
843 CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
844 _("Authentication password not available")((char *) g_dgettext ("evolution-data-server", "Authentication password not available"
))
);
845 result = CAMEL_AUTHENTICATION_ERROR;
846 goto exit;
847 }
848
849 d = pop3_engine->apop;
850
851 while (*d != '\0') {
852 if (!isascii ((gint) * d)((((gint) * d) & ~0x7f) == 0)) {
853
854 g_set_error (
855 error, CAMEL_SERVICE_ERROR(camel_service_error_quark ()),
856 CAMEL_SERVICE_ERROR_URL_INVALID,
857 /* Translators: Do not translate APOP. */
858 _("Unable to connect to POP server %s: "((char *) g_dgettext ("evolution-data-server", "Unable to connect to POP server %s: "
"Invalid APOP ID received. Impersonation " "attack suspected. Please contact your admin."
))
859 "Invalid APOP ID received. Impersonation "((char *) g_dgettext ("evolution-data-server", "Unable to connect to POP server %s: "
"Invalid APOP ID received. Impersonation " "attack suspected. Please contact your admin."
))
860 "attack suspected. Please contact your admin.")((char *) g_dgettext ("evolution-data-server", "Unable to connect to POP server %s: "
"Invalid APOP ID received. Impersonation " "attack suspected. Please contact your admin."
))
,
861 host);
862
863 result = CAMEL_AUTHENTICATION_ERROR;
864 goto exit;
865 }
866 d++;
867 }
868
869 checksum = g_checksum_new (G_CHECKSUM_MD5);
870 g_checksum_update (checksum, (const guchar *) pop3_engine->apop, strlen (pop3_engine->apop));
871 g_checksum_update (checksum, (const guchar *) (password ? password : ""), strlen (password ? password : ""));
872
873 pcp = camel_pop3_engine_command_new (
874 pop3_engine, 0, NULL((void*)0), NULL((void*)0), cancellable, error,
875 "APOP %s %s\r\n", user, g_checksum_get_string (checksum));
876
877 g_checksum_free (checksum);
878 } else {
879 GList *link;
880 const gchar *test_mechanism = mechanism;
881
882 if (camel_sasl_is_xoauth2_alias (test_mechanism))
883 test_mechanism = "XOAUTH2";
884
885 link = pop3_engine->auth;
886 while (link != NULL((void*)0)) {
887 CamelServiceAuthType *auth = link->data;
888
889 if (g_strcmp0 (auth->authproto, test_mechanism) == 0) {
890 result = try_sasl (
891 store, mechanism,
892 cancellable, error);
893 goto exit;
894 }
895 link = g_list_next (link)((link) ? (((GList *)(link))->next) : ((void*)0));
896 }
897
898 g_set_error (
899 error, CAMEL_SERVICE_ERROR(camel_service_error_quark ()),
900 CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
901 _("No support for %s authentication")((char *) g_dgettext ("evolution-data-server", "No support for %s authentication"
))
, mechanism);
902 result = CAMEL_AUTHENTICATION_ERROR;
903 goto exit;
904 }
905
906 while ((status = camel_pop3_engine_iterate (pop3_engine, pcp, cancellable, error)) > 0)
907 ;
908
909 if (status == -1) {
910 g_prefix_error (
911 error,
912 _("Unable to connect to POP server %s.\n"((char *) g_dgettext ("evolution-data-server", "Unable to connect to POP server %s.\n"
"Error sending password: "))
913 "Error sending password: ")((char *) g_dgettext ("evolution-data-server", "Unable to connect to POP server %s.\n"
"Error sending password: "))
, host);
914 result = CAMEL_AUTHENTICATION_ERROR;
915
916 } else if (pcu && pcu->state != CAMEL_POP3_COMMAND_OK) {
917 gchar *tmp;
918
919 /* Abort authentication if the server rejects the user
920 * name. Reprompting for a password won't do any good. */
921 tmp = get_valid_utf8_error ((gchar *) pop3_engine->line);
922 g_set_error (
923 error, CAMEL_SERVICE_ERROR(camel_service_error_quark ()),
924 CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
925 /* Translators: Last %s is an optional explanation
926 * beginning with ": " separator. */
927 _("Unable to connect to POP server %s.\n"((char *) g_dgettext ("evolution-data-server", "Unable to connect to POP server %s.\n"
"Error sending username%s"))
928 "Error sending username%s")((char *) g_dgettext ("evolution-data-server", "Unable to connect to POP server %s.\n"
"Error sending username%s"))
,
929 host, (tmp != NULL((void*)0)) ? tmp : "");
930 g_free (tmp);
931 result = CAMEL_AUTHENTICATION_ERROR;
932
933 } else if (pcp->state != CAMEL_POP3_COMMAND_OK) {
934 result = CAMEL_AUTHENTICATION_REJECTED;
935 } else {
936 result = CAMEL_AUTHENTICATION_ACCEPTED;
937 }
938
939exit:
940 if (pcp != NULL((void*)0))
941 camel_pop3_engine_command_free (pop3_engine, pcp);
942
943 if (pcu != NULL((void*)0))
944 camel_pop3_engine_command_free (pop3_engine, pcu);
945
946 g_free (host);
947 g_free (user);
948
949 camel_pop3_engine_busy_unlock (pop3_engine);
950 g_clear_object (&pop3_engine)do { _Static_assert (sizeof *((&pop3_engine)) == sizeof (
gpointer), "Expression evaluates to false"); __typeof__ (((&
pop3_engine))) _pp = ((&pop3_engine)); __typeof__ (*((&
pop3_engine))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref
) (_ptr); } while (0)
;
951
952 return result;
953}
954
955static GList *
956pop3_store_query_auth_types_sync (CamelService *service,
957 GCancellable *cancellable,
958 GError **error)
959{
960 CamelServiceClass *service_class;
961 CamelPOP3Store *store = CAMEL_POP3_STORE (service)((((CamelPOP3Store*) (void *) ((service)))));
962 GList *types = NULL((void*)0);
963 GError *local_error = NULL((void*)0);
964
965 /* Chain up to parent's query_auth_types() method. */
966 service_class = CAMEL_SERVICE_CLASS (camel_pop3_store_parent_class)((((CamelServiceClass*) (void *) ((camel_pop3_store_parent_class
)))))
;
967 types = service_class->query_auth_types_sync (
968 service, cancellable, &local_error);
969
970 if (local_error != NULL((void*)0)) {
971 g_propagate_error (error, local_error);
972 return NULL((void*)0);
973 }
974
975 if (connect_to_server (service, cancellable, error)) {
976 CamelPOP3Engine *pop3_engine;
977
978 pop3_engine = camel_pop3_store_ref_engine (store);
979
980 if (pop3_engine) {
981 types = g_list_concat (types, g_list_copy (pop3_engine->auth));
982 pop3_store_disconnect_sync (service, TRUE(!(0)), cancellable, NULL((void*)0));
983
984 g_clear_object (&pop3_engine)do { _Static_assert (sizeof *((&pop3_engine)) == sizeof (
gpointer), "Expression evaluates to false"); __typeof__ (((&
pop3_engine))) _pp = ((&pop3_engine)); __typeof__ (*((&
pop3_engine))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref
) (_ptr); } while (0)
;
985 }
986 }
987
988 return types;
989}
990
991static gboolean
992pop3_store_can_refresh_folder (CamelStore *store,
993 CamelFolderInfo *info,
994 GError **error)
995{
996 /* any pop3 folder can be refreshed */
997 return TRUE(!(0));
998}
999
1000static CamelFolder *
1001pop3_store_get_folder_sync (CamelStore *store,
1002 const gchar *folder_name,
1003 CamelStoreGetFolderFlags flags,
1004 GCancellable *cancellable,
1005 GError **error)
1006{
1007 if (g_ascii_strcasecmp (folder_name, "inbox") != 0) {
1008 g_set_error (
1009 error, CAMEL_FOLDER_ERROR(camel_folder_error_quark ()),
1010 CAMEL_FOLDER_ERROR_INVALID,
1011 _("No such folder “%s”.")((char *) g_dgettext ("evolution-data-server", "No such folder “%s”."
))
, folder_name);
1012 return NULL((void*)0);
1013 }
1014
1015 return camel_pop3_folder_new (store, cancellable, error);
1016}
1017
1018static CamelFolderInfo *
1019pop3_store_get_folder_info_sync (CamelStore *store,
1020 const gchar *top,
1021 CamelStoreGetFolderInfoFlags flags,
1022 GCancellable *cancellable,
1023 GError **error)
1024{
1025 g_set_error (
1026 error, CAMEL_STORE_ERROR(camel_store_error_quark ()),
1027 CAMEL_STORE_ERROR_NO_FOLDER,
1028 _("POP3 stores have no folder hierarchy")((char *) g_dgettext ("evolution-data-server", "POP3 stores have no folder hierarchy"
))
);
1029
1030 return NULL((void*)0);
1031}
1032
1033static CamelFolder *
1034pop3_store_get_trash_folder_sync (CamelStore *store,
1035 GCancellable *cancellable,
1036 GError **error)
1037{
1038 /* no-op */
1039 return NULL((void*)0);
1040}
1041
1042static const gchar *
1043pop3_store_get_service_name (CamelNetworkService *service,
1044 CamelNetworkSecurityMethod method)
1045{
1046 const gchar *service_name;
1047
1048 switch (method) {
1049 case CAMEL_NETWORK_SECURITY_METHOD_SSL_ON_ALTERNATE_PORT:
1050 service_name = "pop3s";
1051 break;
1052
1053 default:
1054 service_name = "pop3";
1055 break;
1056 }
1057
1058 return service_name;
1059}
1060
1061static guint16
1062pop3_store_get_default_port (CamelNetworkService *service,
1063 CamelNetworkSecurityMethod method)
1064{
1065 guint16 default_port;
1066
1067 switch (method) {
1068 case CAMEL_NETWORK_SECURITY_METHOD_SSL_ON_ALTERNATE_PORT:
1069 default_port = POP3S_PORT995;
1070 break;
1071
1072 default:
1073 default_port = POP3_PORT110;
1074 break;
1075 }
1076
1077 return default_port;
1078}
1079
1080static void
1081camel_pop3_store_class_init (CamelPOP3StoreClass *class)
1082{
1083 GObjectClass *object_class;
1084 CamelServiceClass *service_class;
1085 CamelStoreClass *store_class;
1086
1087 object_class = G_OBJECT_CLASS (class)((((GObjectClass*) (void *) ((class)))));
1088 object_class->set_property = pop3_store_set_property;
1089 object_class->get_property = pop3_store_get_property;
1090 object_class->dispose = pop3_store_dispose;
1091 object_class->finalize = pop3_store_finalize;
1092
1093 service_class = CAMEL_SERVICE_CLASS (class)((((CamelServiceClass*) (void *) ((class)))));
1094 service_class->settings_type = CAMEL_TYPE_POP3_SETTINGS(camel_pop3_settings_get_type ());
1095 service_class->get_name = pop3_store_get_name;
1096 service_class->connect_sync = pop3_store_connect_sync;
1097 service_class->disconnect_sync = pop3_store_disconnect_sync;
1098 service_class->authenticate_sync = pop3_store_authenticate_sync;
1099 service_class->query_auth_types_sync = pop3_store_query_auth_types_sync;
1100
1101 store_class = CAMEL_STORE_CLASS (class)((((CamelStoreClass*) (void *) ((class)))));
1102 store_class->can_refresh_folder = pop3_store_can_refresh_folder;
1103 store_class->get_folder_sync = pop3_store_get_folder_sync;
1104 store_class->get_folder_info_sync = pop3_store_get_folder_info_sync;
1105 store_class->get_trash_folder_sync = pop3_store_get_trash_folder_sync;
1106
1107 /* Inherited from CamelNetworkService. */
1108 g_object_class_override_property (
1109 object_class,
1110 PROP_CONNECTABLE,
1111 "connectable");
1112
1113 /* Inherited from CamelNetworkService. */
1114 g_object_class_override_property (
1115 object_class,
1116 PROP_HOST_REACHABLE,
1117 "host-reachable");
1118}
1119
1120static void
1121camel_network_service_init (CamelNetworkServiceInterface *iface)
1122{
1123 iface->get_service_name = pop3_store_get_service_name;
1124 iface->get_default_port = pop3_store_get_default_port;
1125}
1126
1127static void
1128camel_pop3_store_init (CamelPOP3Store *pop3_store)
1129{
1130 pop3_store->priv = camel_pop3_store_get_instance_private (pop3_store);
1131
1132 g_mutex_init (&pop3_store->priv->property_lock);
1133}
1134
1135/**
1136 * camel_pop3_store_ref_cache:
1137 * @store: a #CamelPOP3Store
1138 *
1139 * Returns the #CamelDataCache for @store.
1140 *
1141 * The returned #CamelDataCache is referenced for thread-safety and must be
1142 * unreferenced with g_object_unref() when finished with it.
1143 *
1144 * Returns: a #CamelDataCache
1145 **/
1146CamelDataCache *
1147camel_pop3_store_ref_cache (CamelPOP3Store *store)
1148{
1149 CamelDataCache *cache = NULL((void*)0);
1150
1151 g_return_val_if_fail (CAMEL_IS_POP3_STORE (store), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_21
= 0; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((store)); GType __t = ((camel_pop3_store_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_21
= 1; _g_boolean_var_21; }), 1))) { } else { g_return_if_fail_warning
("camel-pop3-provider", ((const char*) (__func__)), "CAMEL_IS_POP3_STORE (store)"
); return (((void*)0)); } } while (0)
;
1152
1153 g_mutex_lock (&store->priv->property_lock);
1154
1155 if (store->priv->cache != NULL((void*)0))
1156 cache = g_object_ref (store->priv->cache)((__typeof__ (store->priv->cache)) (g_object_ref) (store
->priv->cache))
;
1157
1158 g_mutex_unlock (&store->priv->property_lock);
1159
1160 return cache;
1161}
1162
1163/**
1164 * camel_pop3_store_ref_engine:
1165 * @store: a #CamelPOP3Store
1166 *
1167 * Returns the #CamelPOP3Engine for @store.
1168 *
1169 * The returned #CamelPOP3Engine is referenced for thread-safety and must be
1170 * unreferenced with g_object_unref() when finished with it.
1171 *
1172 * Returns: a #CamelPOP3Store
1173 **/
1174CamelPOP3Engine *
1175camel_pop3_store_ref_engine (CamelPOP3Store *store)
1176{
1177 CamelPOP3Engine *engine = NULL((void*)0);
1178
1179 g_return_val_if_fail (CAMEL_IS_POP3_STORE (store), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_22
= 0; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((store)); GType __t = ((camel_pop3_store_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_22
= 1; _g_boolean_var_22; }), 1))) { } else { g_return_if_fail_warning
("camel-pop3-provider", ((const char*) (__func__)), "CAMEL_IS_POP3_STORE (store)"
); return (((void*)0)); } } while (0)
;
1180
1181 g_mutex_lock (&store->priv->property_lock);
1182
1183 if (store->priv->engine != NULL((void*)0))
1184 engine = g_object_ref (store->priv->engine)((__typeof__ (store->priv->engine)) (g_object_ref) (store
->priv->engine))
;
1185
1186 g_mutex_unlock (&store->priv->property_lock);
1187
1188 return engine;
1189}
1190
1191/**
1192 * camel_pop3_store_expunge:
1193 * @store: a #CamelPOP3Store
1194 * @error: return location for a #GError, or %NULL
1195 * @cancellable: optional #GCancellable object, or %NULL
1196 *
1197 * Expunge messages from the store. This will result in the connection
1198 * being closed, which may cause later commands to fail if they can't
1199 * reconnect.
1200 **/
1201gboolean
1202camel_pop3_store_expunge (CamelPOP3Store *store,
1203 GCancellable *cancellable,
1204 GError **error)
1205{
1206 CamelPOP3Command *pc;
1207 CamelPOP3Engine *pop3_engine;
1208 CamelServiceConnectionStatus status;
1209
1210 status = camel_service_get_connection_status (CAMEL_SERVICE (store)((((CamelService*) (void *) ((store))))));
1211
1212 if (status != CAMEL_SERVICE_CONNECTED) {
1213 g_set_error (
1214 error, CAMEL_SERVICE_ERROR(camel_service_error_quark ()),
1215 CAMEL_SERVICE_ERROR_UNAVAILABLE,
1216 _("You must be working online to complete this operation")((char *) g_dgettext ("evolution-data-server", "You must be working online to complete this operation"
))
);
1217 return FALSE(0);
1218 }
1219
1220 pop3_engine = camel_pop3_store_ref_engine (store);
1221
1222 if (!camel_pop3_engine_busy_lock (pop3_engine, cancellable, error)) {
1223 g_clear_object (&pop3_engine)do { _Static_assert (sizeof *((&pop3_engine)) == sizeof (
gpointer), "Expression evaluates to false"); __typeof__ (((&
pop3_engine))) _pp = ((&pop3_engine)); __typeof__ (*((&
pop3_engine))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref
) (_ptr); } while (0)
;
1224 return FALSE(0);
1225 }
1226
1227 pc = camel_pop3_engine_command_new (
1228 pop3_engine, 0, NULL((void*)0), NULL((void*)0), cancellable, error, "QUIT\r\n");
1229
1230 while (camel_pop3_engine_iterate (pop3_engine, NULL((void*)0), cancellable, NULL((void*)0)) > 0)
1231 ;
1232
1233 camel_pop3_engine_command_free (pop3_engine, pc);
1234
1235 camel_pop3_engine_busy_unlock (pop3_engine);
1236 g_clear_object (&pop3_engine)do { _Static_assert (sizeof *((&pop3_engine)) == sizeof (
gpointer), "Expression evaluates to false"); __typeof__ (((&
pop3_engine))) _pp = ((&pop3_engine)); __typeof__ (*((&
pop3_engine))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref
) (_ptr); } while (0)
;
1237
1238 return TRUE(!(0));
1239}
1240
1241/**
1242 * camel_pop3_store_cache_add:
1243 * @store: a #CamelPOP3Store
1244 * @uid: a message UID
1245 * @out_io_stream: (out) (transfer full): return location for the
1246 * underlying #GIOStream opened for atomic writing
1247 * @error: return location for a #GError, or %NULL
1248 *
1249 * Creates a cache file for @uid in @store and returns a #CamelStream for
1250 * writing to it. On success the underlying atomic #GIOStream is also
1251 * returned in @out_io_stream (transfer full); the caller must pass it to
1252 * camel_data_cache_commit_atomic() on success or
1253 * camel_data_cache_discard_atomic() on failure. If an error occurs the
1254 * function sets @error and returns %NULL.
1255 *
1256 * The returned #CamelStream is referenced for thread-safety and must be
1257 * unreferenced when finished with it.
1258 *
1259 * Returns: a #CamelStream, or %NULL on error
1260 **/
1261CamelStream *
1262camel_pop3_store_cache_add (CamelPOP3Store *store,
1263 const gchar *uid,
1264 GIOStream **out_io_stream,
1265 GError **error)
1266{
1267 CamelDataCache *cache;
1268 GIOStream *base_stream;
1269 CamelStream *stream = NULL((void*)0);
1270
1271 g_return_val_if_fail (CAMEL_IS_POP3_STORE (store), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_23
= 0; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((store)); GType __t = ((camel_pop3_store_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_23
= 1; _g_boolean_var_23; }), 1))) { } else { g_return_if_fail_warning
("camel-pop3-provider", ((const char*) (__func__)), "CAMEL_IS_POP3_STORE (store)"
); return (((void*)0)); } } while (0)
;
1272 g_return_val_if_fail (uid != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_24
= 0; if (uid != ((void*)0)) _g_boolean_var_24 = 1; _g_boolean_var_24
; }), 1))) { } else { g_return_if_fail_warning ("camel-pop3-provider"
, ((const char*) (__func__)), "uid != NULL"); return (((void*
)0)); } } while (0)
;
1273 g_return_val_if_fail (out_io_stream != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_25
= 0; if (out_io_stream != ((void*)0)) _g_boolean_var_25 = 1;
_g_boolean_var_25; }), 1))) { } else { g_return_if_fail_warning
("camel-pop3-provider", ((const char*) (__func__)), "out_io_stream != NULL"
); return (((void*)0)); } } while (0)
;
1274
1275 *out_io_stream = NULL((void*)0);
1276
1277 cache = camel_pop3_store_ref_cache (store);
1278 g_return_val_if_fail (cache != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_26
= 0; if (cache != ((void*)0)) _g_boolean_var_26 = 1; _g_boolean_var_26
; }), 1))) { } else { g_return_if_fail_warning ("camel-pop3-provider"
, ((const char*) (__func__)), "cache != NULL"); return (((void
*)0)); } } while (0)
;
1279
1280 base_stream = camel_data_cache_add_atomic (cache, "cache", uid, error);
1281 if (base_stream != NULL((void*)0)) {
1282 stream = camel_stream_new (base_stream);
1283 *out_io_stream = base_stream;
1284 }
1285
1286 g_object_unref (cache);
1287
1288 return stream;
1289}
1290
1291/**
1292 * camel_pop3_store_cache_get:
1293 * @store: a #CamelPOP3Store
1294 * @uid: a message UID
1295 * @error: return location for a #GError, or %NULL
1296 *
1297 * Opens the cache file for @uid in @store and returns a #CamelStream for it.
1298 * If no matching cache file exists, the function returns %NULL. If an error
1299 * occurs in opening the cache file, the function sets @error and returns
1300 * %NULL.
1301 *
1302 * The returned #CamelStream is referenced for thread-safety and must be
1303 * unreferenced when finished with it.
1304 *
1305 * Returns: (nullable): a #CamelStream, or %NULL
1306 **/
1307CamelStream *
1308camel_pop3_store_cache_get (CamelPOP3Store *store,
1309 const gchar *uid,
1310 GError **error)
1311{
1312 CamelDataCache *cache;
1313 GIOStream *base_stream;
1314 CamelStream *stream = NULL((void*)0);
1315
1316 g_return_val_if_fail (CAMEL_IS_POP3_STORE (store), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_27
= 0; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((store)); GType __t = ((camel_pop3_store_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_27
= 1; _g_boolean_var_27; }), 1))) { } else { g_return_if_fail_warning
("camel-pop3-provider", ((const char*) (__func__)), "CAMEL_IS_POP3_STORE (store)"
); return (((void*)0)); } } while (0)
;
1317 g_return_val_if_fail (uid != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_28
= 0; if (uid != ((void*)0)) _g_boolean_var_28 = 1; _g_boolean_var_28
; }), 1))) { } else { g_return_if_fail_warning ("camel-pop3-provider"
, ((const char*) (__func__)), "uid != NULL"); return (((void*
)0)); } } while (0)
;
1318
1319 cache = camel_pop3_store_ref_cache (store);
1320 g_return_val_if_fail (cache != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_29
= 0; if (cache != ((void*)0)) _g_boolean_var_29 = 1; _g_boolean_var_29
; }), 1))) { } else { g_return_if_fail_warning ("camel-pop3-provider"
, ((const char*) (__func__)), "cache != NULL"); return (((void
*)0)); } } while (0)
;
1321
1322 base_stream = camel_data_cache_get (cache, "cache", uid, error);
1323 if (base_stream != NULL((void*)0)) {
1324 stream = camel_stream_new (base_stream);
1325 g_object_unref (base_stream);
1326 }
1327
1328 g_object_unref (cache);
1329
1330 return stream;
1331}
1332
1333/**
1334 * camel_pop3_store_cache_has:
1335 * @store: a #CamelPOP3Store
1336 * @uid: a message UID
1337 *
1338 * Returns whether @store has a cached message for @uid.
1339 *
1340 * Returns: whether @uid is cached
1341 **/
1342gboolean
1343camel_pop3_store_cache_has (CamelPOP3Store *store,
1344 const gchar *uid)
1345{
1346 CamelStream *stream;
1347 gboolean uid_is_cached;
1348
1349 g_return_val_if_fail (CAMEL_IS_POP3_STORE (store), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_30
= 0; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((store)); GType __t = ((camel_pop3_store_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_30
= 1; _g_boolean_var_30; }), 1))) { } else { g_return_if_fail_warning
("camel-pop3-provider", ((const char*) (__func__)), "CAMEL_IS_POP3_STORE (store)"
); return ((0)); } } while (0)
;
1350 g_return_val_if_fail (uid != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_31
= 0; if (uid != ((void*)0)) _g_boolean_var_31 = 1; _g_boolean_var_31
; }), 1))) { } else { g_return_if_fail_warning ("camel-pop3-provider"
, ((const char*) (__func__)), "uid != NULL"); return ((0)); }
} while (0)
;
1351
1352 stream = camel_pop3_store_cache_get (store, uid, NULL((void*)0));
1353 uid_is_cached = (stream != NULL((void*)0));
1354 g_clear_object (&stream)do { _Static_assert (sizeof *((&stream)) == sizeof (gpointer
), "Expression evaluates to false"); __typeof__ (((&stream
))) _pp = ((&stream)); __typeof__ (*((&stream))) _ptr
= *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr)
; } while (0)
;
1355
1356 return uid_is_cached;
1357}
1358