Revision 1906

tags/nntpgrab-0.7.1/NNTPGrab.includes (revision 1906)
1
automation
2
base
3
client/gui
4
client/macosx
5
client/web/module
6
glue
7
gui_base
8
indexer
9
nntpgrab_core
10
plugins/decoder
11
plugins/jsonrpc
12
plugins/par2/par2cmdline
13
plugins/par2
14
plugins/unpack/file-roller/copy-n-paste
15
plugins/unpack/file-roller/nautilus
16
plugins/unpack/file-roller/src
17
plugins/unpack
18
server_qt
19
../deps/include
20
../deps/include/gio-unix-2.0
21
../deps/include/gio-unix-2.0/gio
22
../deps/include/glib-2.0
23
../deps/include/glib-2.0/gio
24
../deps/include/glib-2.0/glib
25
../deps/include/glib-2.0/gobject
26
../deps/include/libsoup-2.4
27
../deps/include/libsoup-2.4/libsoup
28
/usr/include
29
/usr/include/libxml2
30
/usr/include/glib-2.0
31
/usr/include/glib-2.0/glib
32
/usr/include/glib-2.0/gobject
33
/usr/include/glib-2.0/gthread
34
/usr/include/cairo
35
/usr/include/pango-1.0
36
/usr/include/pango-1.0/pango
37
/usr/include/gtk-2.0
38
/usr/include/gtk-2.0/gdk
39
/usr/include/gtk-2.0/gdk-pixbuf
40
/usr/include/gtk-2.0/gdk-pixbuf-xlib
41
/usr/include/libgtkhtml-3.14
42
/usr/include/libgtkhtml-3.14/editor
43
/usr/include/libgtkhtml-3.14/gtkhtml
44
/usr/include/libsoup-2.4
45
/usr/include/libsoup-gnome-2.4
46
/usr/include/libnm-glib
47
/usr/include/NetworkManager
48
/usr/include/gnutls
49
/usr/lib64/glib-2.0/include
50
/usr/include/QtSolutions/
tags/nntpgrab-0.7.1/nntpgrab_core/decoder_thread.h (revision 1906)
1
/*
2
    Copyright (C) 2005-2010  Erik van Pienbroek
3

                
4
    This program is free software; you can redistribute it and/or modify
5
    it under the terms of the GNU General Public License as published by
6
    the Free Software Foundation; either version 2 of the License, or
7
    (at your option) any later version.
8

                
9
    This program is distributed in the hope that it will be useful,
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
    GNU General Public License for more details.
13

                
14
    You should have received a copy of the GNU General Public License
15
    along with this program; if not, write to the Free Software
16
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
*/
18

                
19
#ifndef _DECODER_THREAD_H_
20
#define _DECODER_THREAD_H_
21

                
22
#include "collections.h"
23
#include "configuration.h"
24

                
25
typedef struct _decoder_data {
26
    NNTPCollection  *collection;
27
    NNTPFile        *file;
28
    //GThreadPool     *poolPar2verify;
29
    //GThreadPool     *poolPar2repair;
30
    //GThreadPool     *poolUnpack;
31
} DecoderData;
32

                
33
void         decoder_thread_initialize(Configuration *config);
34
void         decoder_thread_destroy(void);
35
gboolean     decoder_thread_start(void);
36
gboolean     decoder_thread_stop(void);
37
void         decoder_thread_push_task(DecoderData *task);
38

                
39
#endif /* _DECODER_THREAD_H_ */
tags/nntpgrab-0.7.1/nntpgrab_core/nntpconnection_backend_iface.h (revision 1906)
1
/*
2
    Copyright (C) 2005-2011  Erik van Pienbroek
3

                
4
    This program is free software; you can redistribute it and/or modify
5
    it under the terms of the GNU General Public License as published by
6
    the Free Software Foundation; either version 2 of the License, or
7
    (at your option) any later version.
8

                
9
    This program is distributed in the hope that it will be useful,
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
    GNU General Public License for more details.
13

                
14
    You should have received a copy of the GNU General Public License
15
    along with this program; if not, write to the Free Software
16
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
*/
18

                
19
#ifndef _NNTPCONNECTION_BACKEND_IFACE_H_
20
#define _NNTPCONNECTION_BACKEND_IFACE_H_
21

                
22
#include 
23
#include 
24

                
25
#ifdef WIN32
26
#include 
27
#else
28
#include 
29
#endif
30

                
31
#include "configuration.h"
32
#include "collections.h"
33

                
34
G_BEGIN_DECLS
35

                
36
typedef enum {
37
    NNTP_JOB_TYPE_NONE,
38
    NNTP_JOB_TYPE_ARTICLE,
39
    NNTP_JOB_TYPE_XOVER
40
} NNTPJobType;
41

                
42
typedef enum {
43
    NNTP_CONNECTION_ERROR_NONE,
44
    NNTP_CONNECTION_ERROR_HOST_NOT_FOUND,
45
    NNTP_CONNECTION_ERROR_SSL_INITIALISE,
46
    NNTP_CONNECTION_ERROR_CONNECTION_REFUSED,
47
    NNTP_CONNECTION_ERROR_CONNECTION_TIMEOUT,
48
    NNTP_CONNECTION_ERROR_READ,
49
    NNTP_CONNECTION_ERROR_WRITE,
50
    NNTP_CONNECTION_ERROR_INVALID_MSG,
51
    NNTP_CONNECTION_ERROR_INVALID_ARGUMENT,
52
    NNTP_CONNECTION_ERROR_LOGIN_FAILURE,
53
    NNTP_CONNECTION_ERROR_TOO_MANY_CONNECTIONS,
54
    NNTP_CONNECTION_ERROR_PART_NOT_AVAILABLE,
55
    NNTP_CONNECTION_ERROR_NO_SUCH_GROUP,
56
    NNTP_CONNECTION_ERROR_UNABLE_TO_SAVE_PART,
57
} NNTPConnectionErrCode;
58

                
59
#define NNTP_TYPE_CONNECTION                (nntpconnection_get_type ())
60
#define NNTP_CONNECTION(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), NNTP_TYPE_CONNECTION, NntpConnection))
61
#define NNTP_IS_CONNECTION(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NNTP_TYPE_CONNECTION))
62

                
63
#define NNTPCONNECTION_TYPE_BACKEND                (nntpconnection_backend_get_type ())
64
#define NNTPCONNECTION_BACKEND(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), NNTPCONNECTION_TYPE_BACKEND, NntpconnectionBackend))
65
#define NNTPCONNECTION_IS_BACKEND(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NNTPCONNECTION_TYPE_BACKEND))
66
#define NNTPCONNECTION_BACKEND_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), NNTPCONNECTION_TYPE_BACKEND, NntpconnectionBackendIface))
67

                
68
typedef struct _NntpConnection NntpConnection;
69
typedef struct _NntpConnectionClass NntpConnectionClass;
70

                
71
typedef struct _NntpconnectionBackend NntpconnectionBackend;    /* dummy interface */
72
typedef struct _NntpconnectionBackendIface NntpconnectionBackendIface;
73

                
74
struct _NntpConnection {
75
    GObject parent;
76

                
77
    int connection_id;
78
    int server_id;
79
    NGConfigServer server_info;
80

                
81
    GPollFD poll_fd;
82

                
83
    void (*active_method) (NntpConnection *conn);
84
    int max_bandwidth;
85

                
86
    gboolean is_idle;
87
    time_t idle_start_stamp;
88
    time_t last_checked_stamp;
89
    time_t last_disconnect_stamp;
90
    time_t last_activity_stamp;
91

                
92
    NNTPJobType job_type;
93

                
94
    NNTPCollection *collection;
95
    NNTPFile *file;
96
    NNTPPart *part;
97

                
98
    char newsgroup[256];
99
    gint64 xover_start_range;
100
    gint64 xover_end_range;
101

                
102
    char article_filename[1024];
103
    int article_fd;
104
    int article_bytes_downloaded;
105
    struct timeval last_article_progress_announce;
106
    char article_write_buffer[50000];              /* Flush the received article data every 50.000 bytes, GObject doesn't support larger objects */
107
    int article_write_buffer_length;
108
};
109

                
110
struct _NntpconnectionBackendIface {
111
    GTypeInterface parent;
112

                
113
    NNTPConnectionErrCode (*connect) (NntpConnection *self, const char *hostname, int port, char **errmsg);
114
    void (*disconnect) (NntpConnection *self);
115

                
116
    gboolean (*prepare_ssl) (NntpConnection *conn, char **errmsg);
117

                
118
    gboolean (*ensure_data_is_ready) (NntpConnection *conn, int timeout);
119

                
120
    gboolean (*read_msg) (NntpConnection *conn, gboolean read_line, int max_length, void *data, int *data_length, gboolean *more_data_ready, gboolean *try_again, char **errmsg);
121
    gboolean (*send_msg) (NntpConnection *conn, void *data, int length, char **errmsg);
122

                
123
    gboolean (*get_has_ssl_support) (NntpConnection *conn);
124
};
125

                
126
GType nntpconnection_get_type (void);
127
GType nntpconnection_backend_get_type (void);
128

                
129
void nntpconnection_backend_init_traffic_monitor(void);
130
void nntpconnection_backend_update_traffic_monitor(int bytes_read);
131
void nntpconnection_backend_perform_shaping(int max_bandwidth, int bytes_read);
132

                
133
/* Wrapper functions */
134
NNTPConnectionErrCode nntpconnection_backend_connect(NntpConnection *conn, const char *hostname, int port, char **errmsg);
135
void nntpconnection_backend_disconnect(NntpConnection *conn);
136
gboolean nntpconnection_backend_prepare_ssl(NntpConnection *conn);
137

                
138
/* Public functions */
139
gboolean nntpconnection_get_has_ssl_support(NntpConnection *conn);
140
NNTPConnectionErrCode nntpconnection_connect_to_server(NntpConnection *conn, char **errmsg);
141
void nntpconnection_disconnect_from_server(NntpConnection *conn, NNTPDisconnectType disconnect_type, const char *reason, const char *cause_file, int cause_lineno);
142

                
143
gboolean nntpconnection_ensure_data_is_ready(NntpConnection *conn, int timeout);
144
gboolean nntpconnection_read_msg(NntpConnection *conn, gboolean read_line, int max_length, void *data, int *data_length, gboolean *more_data_ready);
145
gboolean nntpconnection_send_msg(NntpConnection *conn, void *data, int length);
146
gboolean nntpconnection_get_has_ssl_support(NntpConnection *conn);
147

                
148
void nntpconnection_process_proxy_connect_command(NntpConnection *conn);
149

                
150
G_END_DECLS
151

                
152
#endif /* _NNTPCONNECTION_BACKEND_IFACE_H_ */
tags/nntpgrab-0.7.1/nntpgrab_core/queue_rawfile.h (revision 1906)
1
/*
2
    Copyright (C) 2005-2010  Erik van Pienbroek
3

                
4
    This program is free software; you can redistribute it and/or modify
5
    it under the terms of the GNU General Public License as published by
6
    the Free Software Foundation; either version 2 of the License, or
7
    (at your option) any later version.
8

                
9
    This program is distributed in the hope that it will be useful,
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
    GNU General Public License for more details.
13

                
14
    You should have received a copy of the GNU General Public License
15
    along with this program; if not, write to the Free Software
16
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
*/
18

                
19
#ifndef _QUEUE_RAWFILE_H_
20
#define _QUEUE_RAWFILE_H_
21

                
22
#include "collections.h"
23
#include 
24

                
25
gboolean     queue_rawfile_load(GList **queue_ret, char **errmsg);
26
gboolean     queue_rawfile_save(GList *queue, char **errmsg);
27

                
28
#endif /* _QUEUE_RAWFILE_H_ */
tags/nntpgrab-0.7.1/nntpgrab_core/nntpconnection_backend_gio.c (revision 1906)
1
/*
2
    Copyright (C) 2005-2011  Erik van Pienbroek
3

                
4
    This program is free software; you can redistribute it and/or modify
5
    it under the terms of the GNU General Public License as published by
6
    the Free Software Foundation; either version 2 of the License, or
7
    (at your option) any later version.
8

                
9
    This program is distributed in the hope that it will be useful,
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
    GNU General Public License for more details.
13

                
14
    You should have received a copy of the GNU General Public License
15
    along with this program; if not, write to the Free Software
16
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
*/
18

                
19
#ifdef HAVE_CONFIG_H
20
#include "config.h"
21
#endif
22

                
23
#ifdef HAVE_GIO_SOCKET
24

                
25
#include 
26
#include 
27

                
28
#include "nntpconnection_backend_gio.h"
29
#include "nntpgrab_plugin.h"
30

                
31
struct _NntpconnectionBackendGioPrivate {
32
    GMainLoop *loop;
33
    GSocketConnectable *connectable;
34
    GSocket *socket;
35

                
36
    GIOStream *connection;
37
    GDataInputStream *istream;
38
    GOutputStream *ostream;
39
};
40

                
41
struct _NntpconnectionBackendGioClass {
42
    GObjectClass parent_class;
43
    /* define vtable methods and signals here */
44
};
45

                
46
static void nntpconnection_backend_gio_disconnect(NntpConnection *conn);
47

                
48
static void nntpconnection_backend_gio_iface_init(NntpconnectionBackendIface *iface);
49
static void nntpconnection_backend_gio_init (NntpconnectionBackendGio *self)
50
{
51
    self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NNTPCONNECTION_TYPE_BACKEND_GIO, NntpconnectionBackendGioPrivate);
52

                
53
    self->priv->loop = g_main_loop_new(NULL, FALSE);
54
}
55

                
56
static void nntpconnection_backend_gio_class_init (NntpconnectionBackendGioClass *klass)
57
{
58
    g_type_class_add_private (klass, sizeof (NntpconnectionBackendGioPrivate));
59
}
60

                
61
G_DEFINE_TYPE_WITH_CODE (NntpconnectionBackendGio, nntpconnection_backend_gio, NNTP_TYPE_CONNECTION,
62
                         G_IMPLEMENT_INTERFACE(NNTPCONNECTION_TYPE_BACKEND, nntpconnection_backend_gio_iface_init))
63

                
64
NntpConnection *nntpconnection_backend_gio_new (void)
65
{
66
    ng_plugin_emit_log_msg(NULL, NG_LOG_LEVEL_INFO, "Created NNTP connection using backend 'gio'");
67
    return NNTP_CONNECTION(g_object_new(NNTPCONNECTION_TYPE_BACKEND_GIO, NULL));
68
}
69

                
70
static NNTPConnectionErrCode
71
nntpconnection_backend_gio_connect(NntpConnection *conn, const char *hostname, int port, char **errmsg)
72
{
73
    NntpconnectionBackendGioPrivate *conn_priv = NNTPCONNECTION_BACKEND_GIO(conn)->priv;
74
    GError *err = NULL;
75
    GSocketAddressEnumerator *enumerator;
76
    GSocketAddress *address;
77
    GCancellable *cancellable = NULL;
78

                
79
    g_return_val_if_fail(conn != NULL, NNTP_CONNECTION_ERROR_INVALID_ARGUMENT);
80
    g_return_val_if_fail(conn->poll_fd.fd == -1, NNTP_CONNECTION_ERROR_INVALID_ARGUMENT);
81
    g_return_val_if_fail(hostname != NULL, NNTP_CONNECTION_ERROR_INVALID_ARGUMENT);
82
    g_return_val_if_fail(port > 0, NNTP_CONNECTION_ERROR_INVALID_ARGUMENT);
83
    g_return_val_if_fail(conn_priv != NULL, NNTP_CONNECTION_ERROR_INVALID_ARGUMENT);
84
    g_return_val_if_fail(errmsg != NULL, NNTP_CONNECTION_ERROR_INVALID_ARGUMENT);
85
    g_return_val_if_fail(*errmsg == NULL, NNTP_CONNECTION_ERROR_INVALID_ARGUMENT);
86

                
87
    conn_priv->socket = g_socket_new(G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_STREAM, 0, &err);
88
    if (!conn_priv->socket) {
89
        *errmsg = g_strdup_printf("g_socket_new() FAILED: %s", err->message);
90
        g_error_free(err);
91
        return NNTP_CONNECTION_ERROR_INVALID_ARGUMENT;
92
    }
93

                
94
    g_socket_set_timeout(conn_priv->socket, 30);
95

                
96
    conn_priv->connectable = g_network_address_parse(hostname, port, &err);
97
    if (!conn_priv->connectable) {
98
        *errmsg = g_strdup_printf("Unable to parse hostname '%s' and port '%i': %s", hostname, port, err->message);
99
        g_error_free(err);
100
        nntpconnection_backend_gio_disconnect(conn);
101
        return NNTP_CONNECTION_ERROR_HOST_NOT_FOUND;
102
    }
103

                
104
    enumerator = g_socket_connectable_enumerate(conn_priv->connectable);
105
    while (TRUE) {
106
        address = g_socket_address_enumerator_next (enumerator, cancellable, &err);
107
        if (!address) {
108
#if 0
109
            if (err == NULL)
110
                g_printerr ("%s: No more addresses to try\n", argv[0]);
111
            else
112
                g_printerr ("%s: %s\n", argv[0], error->message);
113
#endif
114
            return 1;
115
        }
116

                
117
        if (g_socket_connect(conn_priv->socket, address, cancellable, &err))
118
            break;
119

                
120
        //g_printerr ("%s: Connection to %s failed: %s, trying next\n", argv[0], socket_address_to_string (address), err->message);
121
        g_error_free (err);
122
        err = NULL;
123

                
124
        g_object_unref (address);
125
    }
126

                
127
    g_object_unref (enumerator);
128

                
129
    /* Keep the GSocketConnectable around if we still need to set up SSL later */
130
    if (!conn->server_info.use_ssl) {
131
        g_object_unref(conn_priv->connectable);
132
        conn_priv->connectable = NULL;
133
    }
134

                
135
    conn_priv->connection = G_IO_STREAM (g_socket_connection_factory_create_connection(conn_priv->socket));
136
    conn_priv->istream = g_data_input_stream_new(g_io_stream_get_input_stream(conn_priv->connection));
137
    conn_priv->ostream = g_io_stream_get_output_stream(conn_priv->connection);
138

                
139
    g_socket_set_blocking(conn_priv->socket, FALSE);
140
    g_data_input_stream_set_newline_type(G_DATA_INPUT_STREAM(conn_priv->istream), G_DATA_STREAM_NEWLINE_TYPE_CR_LF);
141

                
142
    conn->poll_fd.fd = g_socket_get_fd(conn_priv->socket);
143

                
144
    return NNTP_CONNECTION_ERROR_NONE;
145
}
146

                
147
static void
148
nntpconnection_backend_gio_disconnect(NntpConnection *conn)
149
{
150
    NntpconnectionBackendGioPrivate *conn_priv = NNTPCONNECTION_BACKEND_GIO(conn)->priv;
151

                
152
    g_return_if_fail(conn != NULL);
153
    g_return_if_fail(conn_priv != NULL);
154

                
155
    if (conn_priv->socket) {
156
        g_object_unref(conn_priv->socket);
157
        conn_priv->socket = NULL;
158
    }
159
}
160

                
161
static gboolean
162
accept_certificate (GTlsClientConnection *conn, GTlsCertificate *cert,
163
                    GTlsCertificateFlags errors, gpointer user_data)
164
{
165
    g_print ("Certificate would have been rejected ( ");
166
    if (errors & G_TLS_CERTIFICATE_UNKNOWN_CA)
167
        g_print ("unknown-ca ");
168
    if (errors & G_TLS_CERTIFICATE_BAD_IDENTITY)
169
        g_print ("bad-identity ");
170
    if (errors & G_TLS_CERTIFICATE_NOT_ACTIVATED)
171
        g_print ("not-activated ");
172
    if (errors & G_TLS_CERTIFICATE_EXPIRED)
173
        g_print ("expired ");
174
    if (errors & G_TLS_CERTIFICATE_REVOKED)
175
        g_print ("revoked ");
176
    if (errors & G_TLS_CERTIFICATE_INSECURE)
177
        g_print ("insecure ");
178
    g_print (") but accepting anyway.\n");
179

                
180
    return TRUE;
181
}
182

                
183
static gboolean
184
nntpconnection_backend_gio_prepare_ssl (NntpConnection *conn, char **errmsg)
185
{
186
#if GLIB_CHECK_VERSION(2,28,0)
187
    GError *err = NULL;
188
    NntpconnectionBackendGioPrivate *conn_priv;
189
    GIOStream *tls_conn;
190

                
191
    g_return_val_if_fail(conn != NULL, FALSE);
192
    g_return_val_if_fail(conn->server_info.use_ssl == TRUE, FALSE);
193
    g_return_val_if_fail(errmsg != NULL, FALSE);
194
    g_return_val_if_fail(*errmsg == NULL, FALSE);
195

                
196
    conn_priv = NNTPCONNECTION_BACKEND_GIO(conn)->priv;
197
    g_return_val_if_fail(conn_priv != NULL, FALSE);
198
    g_return_val_if_fail(conn_priv->connection != NULL, FALSE);
199
    g_return_val_if_fail(conn_priv->connectable != NULL, FALSE);
200

                
201
    tls_conn = g_tls_client_connection_new (conn_priv->connection, conn_priv->connectable, &err);
202
    if (!tls_conn) {
203
        *errmsg = g_strdup_printf("Could not create TLS connection: %s\n", err->message);
204
        g_error_free(err);
205
        return FALSE;
206
    }
207

                
208
    g_signal_connect (tls_conn, "accept-certificate", G_CALLBACK (accept_certificate), NULL);
209

                
210
    if (!g_tls_connection_handshake (G_TLS_CONNECTION (tls_conn), NULL, &err)) {
211
        *errmsg = g_strdup_printf("Error during TLS handshake: %s\n", err->message);
212
        g_error_free(err);
213
        return FALSE;
214
    }
215

                
216
    /* Replace the already known streams with the TLS based one */
217
    g_object_unref(conn_priv->connection);
218
    g_filter_input_stream_set_close_base_stream(G_FILTER_INPUT_STREAM(conn_priv->istream), FALSE);
219
    g_object_unref(conn_priv->istream);
220
    conn_priv->connection = G_IO_STREAM(tls_conn);
221
    conn_priv->istream = g_data_input_stream_new(g_io_stream_get_input_stream(conn_priv->connection));
222
    conn_priv->ostream = g_io_stream_get_output_stream(conn_priv->connection);
223

                
224
    g_data_input_stream_set_newline_type(G_DATA_INPUT_STREAM(conn_priv->istream), G_DATA_STREAM_NEWLINE_TYPE_CR_LF);
225

                
226
    g_object_unref(conn_priv->connectable);
227
    conn_priv->connectable = NULL;
228

                
229
    return TRUE;
230
#else
231
    *errmsg = g_strdup("This version of GIO doesn't have SSL/TLS support");
232
    return FALSE;
233
#endif
234
}
235

                
236
static gboolean
237
source_ready (GPollableInputStream *stream,
238
              gpointer              data)
239
{
240
    NntpconnectionBackendGioPrivate *conn_priv = (NntpconnectionBackendGioPrivate*) data;
241

                
242
    g_main_loop_quit (conn_priv->loop);
243

                
244
    return FALSE;
245
}
246

                
247
static void
248
ensure_connection_condition (NntpConnection *conn,
249
                             GIOCondition    condition,
250
                             GCancellable   *cancellable)
251
{
252
    NntpconnectionBackendGioPrivate *conn_priv = NNTPCONNECTION_BACKEND_GIO(conn)->priv;
253
    GSource *source;
254

                
255
    if (condition & G_IO_IN)
256
        source = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM (g_io_stream_get_input_stream (conn_priv->connection)), cancellable);
257
    else
258
        source = g_pollable_output_stream_create_source (G_POLLABLE_OUTPUT_STREAM (g_io_stream_get_output_stream (conn_priv->connection)), cancellable);
259

                
260
    g_source_set_callback (source, (GSourceFunc) source_ready, conn_priv, NULL);
261
    g_source_attach (source, NULL);
262
    g_source_unref (source);
263
    g_main_loop_run (conn_priv->loop);
264
}
265

                
266
struct _cancel_data {
267
    GCancellable *cancellable;
268
    int timeout;
269
};
270

                
271
static gpointer
272
cancel_thread (gpointer data)
273
{
274
    struct _cancel_data *cancel_data = (struct _cancel_data*) data;
275

                
276
    g_usleep(cancel_data->timeout);
277
    g_print("Cancelling\n");
278
    g_cancellable_cancel(cancel_data->cancellable);
279

                
280
    g_slice_free1(sizeof(struct _cancel_data), cancel_data);
281

                
282
    return NULL;
283
}
284

                
285
static gboolean
286
nntpconnection_backend_gio_ensure_data_is_ready(NntpConnection *conn, int timeout)
287
{
288
    GCancellable *cancellable = NULL;
289
    gboolean ret;
290

                
291
    if (timeout > 0) {
292
        static GCancellable *cancellable_cached = NULL;
293
        struct _cancel_data *cancel_data = g_slice_alloc(sizeof(struct _cancel_data));
294

                
295
        if (!cancellable_cached) {
296
            cancellable_cached = g_cancellable_new();
297
        }
298

                
299
        cancellable = cancellable_cached;
300
        cancel_data->cancellable = cancellable_cached;
301
        cancel_data->timeout = timeout;
302

                
303
        g_thread_create(cancel_thread, cancel_data, FALSE, NULL);
304
    }
305

                
306
    ensure_connection_condition (conn, G_IO_IN, cancellable);
307

                
308
    ret = !(g_cancellable_is_cancelled(cancellable));
309
    g_cancellable_reset(cancellable);
310

                
311
    return ret;
312
}
313

                
314
static gboolean
315
nntpconnection_backend_gio_read_msg(NntpConnection *conn, gboolean read_line, int max_length, void *data, int *data_length, gboolean *more_data_ready, gboolean *try_again, char **errmsg)
316
{
317
    NntpconnectionBackendGioPrivate *conn_priv;
318
    GError *err = NULL;
319
    gsize len;
320
    char *line;
321

                
322
    g_return_val_if_fail(conn != NULL, FALSE);
323
    g_return_val_if_fail(max_length > 0, FALSE);
324
    g_return_val_if_fail(data != NULL, FALSE);
325
    g_return_val_if_fail(data_length != NULL, FALSE);
326
    g_return_val_if_fail(*data_length == 0, FALSE);
327
    /* more_data_ready can be NULL */
328
    g_return_val_if_fail(try_again != NULL, FALSE);
329
    g_return_val_if_fail(errmsg != NULL, FALSE);
330
    g_return_val_if_fail(*errmsg == NULL, FALSE);
331

                
332
    conn_priv = NNTPCONNECTION_BACKEND_GIO(conn)->priv;
333
    g_return_val_if_fail(conn_priv != NULL, FALSE);
334

                
335
    *try_again = FALSE;
336

                
337
    if (read_line) {
338
        line = g_data_input_stream_read_line(G_DATA_INPUT_STREAM(conn_priv->istream), &len, NULL, &err);
339
    } else {
340
        line = g_data_input_stream_read_upto(G_DATA_INPUT_STREAM(conn_priv->istream), "\n", -1, &len, NULL, &err);
341
        if (line) {
342
            /* Also read the \n character itself */
343
            g_return_val_if_fail(g_data_input_stream_read_byte(G_DATA_INPUT_STREAM(conn_priv->istream), NULL, NULL) == '\n', FALSE);
344
        }
345
    }
346

                
347
    if (line) {
348
        /* NOTE: len will include the newline characters when read_line == FALSE, otherwise len will be 0 when an empty line was received */
349

                
350
        if (len > max_length) {
351
            ng_plugin_emit_log_msg(NULL, NG_LOG_LEVEL_INFO, "nntpconnection_backend_gio_read_msg: Very long line received from server. Ignoring\nLine = %s", line);
352
            g_free(line);
353
            return FALSE;
354
        }
355

                
356
        memcpy(data, line, len);
357

                
358
        /* g_data_input_stream_read_upto doesn't put the \n character in the buffer. Manually add this when read_line == FALSE */
359
        if (!read_line && len + 1 < max_length) {
360
            char *data_ptr = (char*) data;
361
            data_ptr[len] = '\n';
362
            data_ptr[len + 1] = '\0';
363
            len += 1;
364
        }
365

                
366
        g_free(line);
367
    } else {
368
        len = -1;
369
    }
370

                
371
    if (len == -1) {
372
        g_return_val_if_fail(err != NULL, FALSE);
373

                
374
        if (err->code == G_IO_ERROR_WOULD_BLOCK) {
375
            *try_again = TRUE;
376
        }
377
        *errmsg = g_strdup(err->message);
378
        g_error_free(err);
379
        return FALSE;
380
    } else {
381
        *data_length = len;
382

                
383
        nntpconnection_backend_perform_shaping(conn->max_bandwidth, len);
384
        nntpconnection_backend_update_traffic_monitor(len);
385
    }
386

                
387
    if (more_data_ready) {
388
        *more_data_ready = (g_buffered_input_stream_get_available(G_BUFFERED_INPUT_STREAM(conn_priv->istream)) > 0);
389
    }
390

                
391
    return TRUE;
392
}
393

                
394
static gboolean
395
nntpconnection_backend_gio_send_msg(NntpConnection *conn, void *data, int length, char **errmsg)
396
{
397
    NntpconnectionBackendGioPrivate *conn_priv;
398
    GError *err = NULL;
399
    gboolean ret;
400

                
401
    g_return_val_if_fail(conn != NULL, FALSE);
402

                
403
    conn_priv = NNTPCONNECTION_BACKEND_GIO(conn)->priv;
404
    g_return_val_if_fail(conn_priv != NULL, FALSE);
405

                
406
    ret = g_output_stream_write_all(G_OUTPUT_STREAM(conn_priv->ostream), data, length, NULL, NULL, &err);
407
    if (!ret) {
408
        *errmsg = g_strdup(err->message);
409
        g_error_free(err);
410
        return FALSE;
411
    }
412

                
413
    return TRUE;
414
}
415

                
416
static gboolean
417
nntpconnection_backend_gio_get_has_ssl_support(NntpConnection *conn)
418
{
419
#if GLIB_CHECK_VERSION(2,28,0)
420
    return g_tls_backend_supports_tls(g_tls_backend_get_default());
421
#else
422
    return FALSE;
423
#endif
424
}
425

                
426
static void nntpconnection_backend_gio_iface_init(NntpconnectionBackendIface *iface)
427
{
428
    iface->connect = nntpconnection_backend_gio_connect;
429
    iface->disconnect = nntpconnection_backend_gio_disconnect;
430
    iface->prepare_ssl = nntpconnection_backend_gio_prepare_ssl;
431
    iface->ensure_data_is_ready = nntpconnection_backend_gio_ensure_data_is_ready;
432
    iface->read_msg = nntpconnection_backend_gio_read_msg;
433
    iface->send_msg = nntpconnection_backend_gio_send_msg;
434
    iface->get_has_ssl_support = nntpconnection_backend_gio_get_has_ssl_support;
435
}
436

                
437
#endif
tags/nntpgrab-0.7.1/nntpgrab_core/collection_alloc.c (revision 1906)
1
/*
2
    Copyright (C) 2005-2010  Erik van Pienbroek
3

                
4
    This program is free software; you can redistribute it and/or modify
5
    it under the terms of the GNU General Public License as published by
6
    the Free Software Foundation; either version 2 of the License, or
7
    (at your option) any later version.
8

                
9
    This program is distributed in the hope that it will be useful,
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
    GNU General Public License for more details.
13

                
14
    You should have received a copy of the GNU General Public License
15
    along with this program; if not, write to the Free Software
16
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
*/
18

                
19
#ifdef HAVE_CONFIG_H
20
#include "config.h"
21
#endif
22

                
23
#include 
24
#include "nntpgrab_types.h"
25
#include "collections.h"
26
#include "collection_alloc.h"
27

                
28
NNTPFile *
29
file_new(void)
30
{
31
    NNTPFile *file = g_slice_new0(NNTPFile);
32
    file_ref(file);
33
    return file;
34
}
35

                
36
void
37
file_ref(NNTPFile *file)
38
{
39
    g_atomic_int_inc(&file->refcount);
40
//    g_print("file_ref: refcount = %i for subject %s\n", file->refcount, file->subject);
41
}
42

                
43
void
44
file_unref(NNTPFile *file)
45
{
46
    GList *groups;
47
    GList *parts;
48

                
49
    if (!g_atomic_int_dec_and_test(&file->refcount)) {
50
//        g_print("file_unref: refcount = %i for subject %s\n", file->refcount, file->subject);
51
        return;
52
    }
53

                
54
//    g_print("file_unref: refcount = %i for subject %s\n", file->refcount, file->subject);
55
//    g_print("releasing file\n");
56

                
57
    groups = file->groups;
58
    while (groups) {
59
        g_free(groups->data);
60
        groups = g_list_next(groups);
61
    }
62

                
63
    g_list_free(file->groups);
64

                
65
    parts = file->parts;
66
    while (parts) {
67
        g_slice_free(NNTPPart, parts->data);
68
        parts = g_list_next(parts);
69
    }
70

                
71
    g_list_free(file->parts);
72

                
73
    g_slice_free(NNTPFile, file);
74
}
75

                
76
NNTPCollection *
77
collection_new(void)
78
{
79
    NNTPCollection *collection = g_slice_new0(NNTPCollection);
80
    g_static_mutex_init(&collection->mutex);
81
    collection_ref(collection);
82
    return collection;
83
}
84

                
85
void
86
collection_ref(NNTPCollection *collection)
87
{
88
    g_atomic_int_inc(&collection->refcount);
89
//    g_print("collection_ref: refcount = %i for collection %s\n", collection->refcount, collection->collection_name);
90
}
91

                
92
void
93
collection_unref(NNTPCollection *collection)
94
{
95
    GList *files;
96

                
97
    if (!g_atomic_int_dec_and_test(&collection->refcount)) {
98
//        g_print("collection_unref: refcount = %i for collection %s\n", collection->refcount, collection->collection_name);
99
        return;
100
    }
101

                
102
//    g_print("collection_unref: refcount = %i for collection %s\n", collection->refcount, collection->collection_name);
103
//    g_print("releasing collection\n");
104

                
105
    files = collection->files;
106
    while (files) {
107
        NNTPFile *file = (NNTPFile *) files->data;
108

                
109
        file_unref(file);
110

                
111
        files = g_list_next(files);
112
    }
113

                
114
    g_list_free(collection->files);
115
    g_list_free(collection->files_to_download);
116

                
117
    g_slice_free(NNTPCollection, collection);
118
}
tags/nntpgrab-0.7.1/nntpgrab_core/throttle.c (revision 1906)
1
/*
2
    Copyright (C) 2005-2010  Erik van Pienbroek
3

                
4
    This program is free software; you can redistribute it and/or modify
5
    it under the terms of the GNU General Public License as published by
6
    the Free Software Foundation; either version 2 of the License, or
7
    (at your option) any later version.
8

                
9
    This program is distributed in the hope that it will be useful,
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
    GNU General Public License for more details.
13

                
14
    You should have received a copy of the GNU General Public License
15
    along with this program; if not, write to the Free Software
16
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
*/
18

                
19
/* Parts of this file are taken from ProFTP's throttle.c */
20

                
21
#include 
22
#include 
23
#include 
24
#include 
25
#include 
26
#ifdef WIN32
27
#include 
28
#endif
29
#include "nntpgrab.h"
30
#include "nntpgrab_plugin.h"
31

                
32
/* This allows a throttling process to be killed by the admin */
33
#ifndef WIN32
34
static void
35
xfer_rate_sigmask(int block)
36
{
37
    static sigset_t sig_set;
38

                
39
    if (block) {
40
        sigemptyset(&sig_set);
41

                
42
        sigaddset(&sig_set, SIGCHLD);
43
        sigaddset(&sig_set, SIGUSR1);
44
        sigaddset(&sig_set, SIGINT);
45
        sigaddset(&sig_set, SIGQUIT);
46
#ifdef SIGIO
47
        sigaddset(&sig_set, SIGIO);
48
#endif /* SIGIO */
49
#ifdef SIGBUS
50
        sigaddset(&sig_set, SIGBUS);
51
#endif /* SIGBUS */
52
        sigaddset(&sig_set, SIGHUP);
53

                
54
        while (sigprocmask(SIG_BLOCK, &sig_set, NULL) < 0) {
55
            if (errno == EINTR) {
56
                continue;
57
            }
58

                
59
            break;
60
        }
61
    } else {
62
        while (sigprocmask(SIG_UNBLOCK, &sig_set, NULL) < 0) {
63
            if (errno == EINTR) {
64
                continue;
65
            }
66

                
67
            break;
68
        }
69
    }
70
}
71
#endif
72

                
73
/* Returns the difference, in milliseconds, between the given timeval and now */
74
static long
75
xfer_rate_since(struct timeval *then)
76
{
77
    struct timeval now;
78
    gettimeofday(&now, NULL);
79

                
80
    return (((now.tv_sec - then->tv_sec) * 1000L) + ((now.tv_usec - then->tv_usec) / 1000L));
81
}
82

                
83
void
84
throttle_pause(struct timeval start_time, off_t xferlen, int max_bandwidth)
85
{
86
    long double xfer_rate_bps;
87
    long ideal = 0, elapsed = 0;
88

                
89
    /* Calculate the time interval since the transfer of data started. */
90
    elapsed = xfer_rate_since(&start_time);
91
    xfer_rate_bps = max_bandwidth * 1024.0;
92

                
93
    ideal = (xferlen * 1000L) / xfer_rate_bps;
94

                
95
    if (ideal > elapsed) {
96
        struct timeval tv;
97

                
98
        /* Setup for the select.  We use select() instead of usleep() because it
99
         * seems to be far more portable across platforms.
100
         *
101
         * ideal and elapsed are in milleconds, but tv_usec will be microseconds,
102
         * so be sure to convert properly.
103
         */
104
        tv.tv_usec = (ideal - elapsed) * 1000;
105
        tv.tv_sec = tv.tv_usec / 1000000L;
106
        tv.tv_usec = tv.tv_usec % 1000000L;
107

                
108
#if 0
109
        ng_plugin_emit_log_msg(NULL, NG_LOG_LEVEL_DEBUG, "transferring too fast, delaying %ld sec%s, %ld usecs",
110
            (long int) tv.tv_sec, tv.tv_sec == 1 ? "" : "s", (long int) tv.tv_usec);
111
#endif
112

                
113
#ifdef WIN32
114
        /* Stupid Win32 doesn't support the select() function with no sockets attached.. */
115
        Sleep(ideal - elapsed);
116
#else
117
        /* No interruptions, please... */
118
        xfer_rate_sigmask(TRUE);
119

                
120
        if (select(0, NULL, NULL, NULL, &tv) < 0) {
121
            ng_plugin_emit_log_msg(NULL, NG_LOG_LEVEL_WARNING, "warning: unable to throttle bandwidth: %s", strerror(errno));
122
        }
123

                
124
        xfer_rate_sigmask(FALSE);
125
#endif
126
    }
127

                
128
    return;
129
}
tags/nntpgrab-0.7.1/nntpgrab_core/strptime.c (revision 1906)
1
/* Convert a string representation of time to a time value.
2
   Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
3
   This file is part of the GNU C Library.
4
   Contributed by Ulrich Drepper , 1996.
5

                
6
   The GNU C Library is free software; you can redistribute it and/or
7
   modify it under the terms of the GNU Library General Public License as
8
   published by the Free Software Foundation; either version 2 of the
9
   License, or (at your option) any later version.
10

                
11
   The GNU C Library 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 GNU
14
   Library General Public License for more details.
15

                
16
   You should have received a copy of the GNU Library General Public
17
   License along with the GNU C Library; see the file COPYING.LIB.  If not,
18
   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19
   Boston, MA 02111-1307, USA.  */
20

                
21
/* XXX This version of the implementation is not really complete.
22
   Some of the fields cannot add information alone.  But if seeing
23
   some of them in the same format (such as year, week and weekday)
24
   this is enough information for determining the date.  */
25

                
26
#ifdef HAVE_CONFIG_H
27
# include "config.h"
28
#endif
29

                
30
#ifdef WIN32
31
#define strncasecmp            strnicmp
32
#endif
33

                
34
#include 
35
#include 
36
#include 
37
#include 
38

                
39
#ifdef _LIBC
40
# include "../locale/localeinfo.h"
41
#endif
42

                
43
#include "strptime.h"
44

                
45
#ifndef __P
46
# if defined (__GNUC__) || (defined (__STDC__) && __STDC__)
47
#  define __P(args) args
48
# else
49
#  define __P(args) ()
50
# endif  /* GCC.  */
51
#endif  /* Not __P.  */
52

                
53
#if ! HAVE_LOCALTIME_R && ! defined localtime_r
54
# ifdef _LIBC
55
#  define localtime_r __localtime_r
56
# else
57
/* Approximate localtime_r as best we can in its absence.  */
58
#  define localtime_r my_localtime_r
59
static struct tm *localtime_r __P ((const time_t *, struct tm *));
60
static struct tm *
61
localtime_r (t, tp)
62
     const time_t *t;
63
     struct tm *tp;
64
{
65
  struct tm *l = localtime (t);
66
  if (! l)
67
    return 0;
68
  *tp = *l;
69
  return tp;
70
}
71
# endif /* ! _LIBC */
72
#endif /* ! HAVE_LOCALTIME_R && ! defined (localtime_r) */
73

                
74

                
75
#define match_char(ch1, ch2) if (ch1 != ch2) return NULL
76
#if defined __GNUC__ && __GNUC__ >= 2
77
# define match_string(cs1, s2) \
78
  ({ size_t len = strlen (cs1);                                                      \
79
     int result = strncasecmp ((cs1), (s2), len) == 0;                       \
80
     if (result) (s2) += len;                                                \
81
     result; })
82
#else
83
/* Oh come on.  Get a reasonable compiler.  */
84
# define match_string(cs1, s2) \
85
  (strncasecmp ((cs1), (s2), strlen (cs1)) ? 0 : ((s2) += strlen (cs1), 1))
86
#endif
87
/* We intentionally do not use isdigit() for testing because this will
88
   lead to problems with the wide character version.  */
89
#define get_number(from, to, n) \
90
  do {                                                                       \
91
    int __n = n;                                                             \
92
    val = 0;                                                                 \
93
    while (*rp == ' ')                                                       \
94
      ++rp;                                                                  \
95
    if (*rp < '0' || *rp > '9')                                                \
96
      return NULL;                                                           \
97
    do {                                                                     \
98
      val *= 10;                                                             \
99
      val += *rp++ - '0';                                                    \
100
    } while (--__n > 0 && val * 10 <= to && *rp >= '0' && *rp <= '9');           \
101
    if (val < from || val > to)                                                \
102
      return NULL;                                                           \
103
  } while (0)
104
#ifdef _NL_CURRENT
105
# define get_alt_number(from, to, n) \
106
  ({                                                                         \
107
    __label__ do_normal;                                                     \
108
    if (*decided != raw)                                                     \
109
      {                                                                              \
110
        const char *alts = _NL_CURRENT (LC_TIME, ALT_DIGITS);                \
111
        int __n = n;                                                         \
112
        int any = 0;                                                         \
113
        while (*rp == ' ')                                                   \
114
          ++rp;                                                                      \
115
        val = 0;                                                             \
116
        do {                                                                 \
117
          val *= 10;                                                         \
118
          while (*alts != '\0')                                                      \
119
            {                                                                \
120
              size_t len = strlen (alts);                                    \
121
              if (strncasecmp (alts, rp, len) == 0)                          \
122
                break;                                                       \
123
              alts += len + 1;                                               \
124
              ++val;                                                         \
125
            }                                                                \
126
          if (*alts == '\0')                                                 \
127
            {                                                                \
128
              if (*decided == not && ! any)                                  \
129
                goto do_normal;                                                      \
130
              /* If we haven't read anything it's an error.  */                      \
131
              if (! any)                                                     \
132
                return NULL;                                                 \
133
              /* Correct the premature multiplication.  */                   \
134
              val /= 10;                                                     \
135
              break;                                                         \
136
            }                                                                \
137
          else                                                               \
138
            *decided = loc;                                                  \
139
        } while (--__n > 0 && val * 10 <= to);                                 \
140
        if (val < from || val > to)                                            \
141
          return NULL;                                                       \
142
      }                                                                              \
143
    else                                                                     \
144
      {                                                                              \
145
       do_normal:                                                            \
146
        get_number (from, to, n);                                            \
147
      }                                                                              \
148
    0;                                                                       \
149
  })
150
#else
151
# define get_alt_number(from, to, n) \
152
  /* We don't have the alternate representation.  */                         \
153
  get_number(from, to, n)
154
#endif
155
#define recursive(new_fmt) \
156
  (*(new_fmt) != '\0'                                                        \
157
   && (rp = strptime_internal (rp, (new_fmt), tm, decided, era_cnt)) != NULL)
158

                
159

                
160
#ifdef _LIBC
161
/* This is defined in locale/C-time.c in the GNU libc.  */
162
extern const struct locale_data _nl_C_LC_TIME;
163
extern const unsigned short int __mon_yday[2][13];
164

                
165
# define weekday_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (DAY_1)].string)
166
# define ab_weekday_name \
167
  (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABDAY_1)].string)
168
# define month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (MON_1)].string)
169
# define ab_month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABMON_1)].string)
170
# define HERE_D_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_T_FMT)].string)
171
# define HERE_D_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_FMT)].string)
172
# define HERE_AM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (AM_STR)].string)
173
# define HERE_PM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (PM_STR)].string)
174
# define HERE_T_FMT_AMPM \
175
  (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT_AMPM)].string)
176
# define HERE_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT)].string)
177

                
178
# define strncasecmp(s1, s2, n) __strncasecmp (s1, s2, n)
179
#else
180
static char const weekday_name[][10] =
181
  {
182
    "Sunday", "Monday", "Tuesday", "Wednesday",
183
    "Thursday", "Friday", "Saturday"
184
  };
185
static char const ab_weekday_name[][4] =
186
  {
187
    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
188
  };
189
static char const month_name[][10] =
190
  {
191
    "January", "February", "March", "April", "May", "June",
192
    "July", "August", "September", "October", "November", "December"
193
  };
194
static char const ab_month_name[][4] =
195
  {
196
    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
197
    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
198
  };
199
# define HERE_D_T_FMT "%a %b %e %H:%M:%S %Y"
200
# define HERE_D_FMT "%m/%d/%y"
201
# define HERE_AM_STR "AM"
202
# define HERE_PM_STR "PM"
203
# define HERE_T_FMT_AMPM "%I:%M:%S %p"
204
# define HERE_T_FMT "%H:%M:%S"
205

                
206
const unsigned short int __mon_yday[2][13] =
207
  {
208
    /* Normal years.  */
209
    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
210
    /* Leap years.  */
211
    { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
212
  };
213
#endif
214

                
215
/* Status of lookup: do we use the locale data or the raw data?  */
216
enum locale_status { not, loc, raw };
217

                
218

                
219
#ifndef __isleap
220
/* Nonzero if YEAR is a leap year (every 4 years,
221
   except every 100th isn't, and every 400th is).  */
222
# define __isleap(year)        \
223
  ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
224
#endif
225

                
226
/* Compute the day of the week.  */
227
static void
228
day_of_the_week (struct tm *tm)
229
{
230
  /* We know that January 1st 1970 was a Thursday (= 4).  Compute the
231
     the difference between this data in the one on TM and so determine
232
     the weekday.  */
233
  int corr_year = 1900 + tm->tm_year - (tm->tm_mon < 2);
234
  int wday = (-473
235
              + (365 * (tm->tm_year - 70))
236
              + (corr_year / 4)
237
              - ((corr_year / 4) / 25) + ((corr_year / 4) % 25 < 0)
238
              + (((corr_year / 4) / 25) / 4)
239
              + __mon_yday[0][tm->tm_mon]
240
              + tm->tm_mday - 1);
241
  tm->tm_wday = ((wday % 7) + 7) % 7;
242
}
243

                
244
/* Compute the day of the year.  */
245
static void
246
day_of_the_year (struct tm *tm)
247
{
248
  tm->tm_yday = (__mon_yday[__isleap (1900 + tm->tm_year)][tm->tm_mon]
249
                 + (tm->tm_mday - 1));
250
}
251

                
252
static char *
253
#ifdef _LIBC
254
internal_function
255
#endif
256
strptime_internal __P ((const char *rp, const char *fmt, struct tm *tm,
257
                        enum locale_status *decided, int era_cnt));
258

                
259
static char *
260
#ifdef _LIBC
261
internal_function
262
#endif
263
strptime_internal (rp, fmt, tm, decided, era_cnt)
264
     const char *rp;
265
     const char *fmt;
266
     struct tm *tm;
267
     enum locale_status *decided;
268
     int era_cnt;
269
{
270
  int cnt;
271
  size_t val;
272
  int have_I, is_pm;
273
  int century, want_century;
274
  int want_era;
275
  int have_wday, want_xday;
276
  int have_yday;
277
  int have_mon, have_mday;
278
#ifdef _NL_CURRENT
279
  const char *rp_backup;
280
  size_t num_eras;
281
  struct era_entry *era;
282
#endif
283

                
284
  have_I = is_pm = 0;
285
  century = -1;
286
  want_century = 0;
287
  want_era = 0;
288
#ifdef _NL_CURRENT
289
  era = NULL;
290
#endif
291

                
292
  have_wday = want_xday = have_yday = have_mon = have_mday = 0;
293

                
294
  while (*fmt != '\0')
295
    {
296
      /* A white space in the format string matches 0 more or white
297
         space in the input string.  */
298
      if (isspace (*fmt))
299
        {
300
          while (isspace (*rp))
301
            ++rp;
302
          ++fmt;
303
          continue;
304
        }
305

                
306
      /* Any character but `%' must be matched by the same character
307
         in the iput string.  */
308
      if (*fmt != '%')
309
        {
310
          match_char (*fmt++, *rp++);
311
          continue;
312
        }
313

                
314
      ++fmt;
315
#ifndef _NL_CURRENT
316
      /* We need this for handling the `E' modifier.  */
317
    start_over:
318
#endif
319

                
320
#ifdef _NL_CURRENT
321
      /* Make back up of current processing pointer.  */
322
      rp_backup = rp;
323
#endif
324

                
325
      switch (*fmt++)
326
        {
327
        case '%':
328
          /* Match the `%' character itself.  */
329
          match_char ('%', *rp++);
330
          break;
331
        case 'a':
332
        case 'A':
333
          /* Match day of week.  */
334
          for (cnt = 0; cnt < 7; ++cnt)
335
            {
336
#ifdef _NL_CURRENT
337
              if (*decided !=raw)
338
                {
339
                  if (match_string (_NL_CURRENT (LC_TIME, DAY_1 + cnt), rp))
340
                    {
341
                      if (*decided == not
342
                          && strcmp (_NL_CURRENT (LC_TIME, DAY_1 + cnt),
343
                                     weekday_name[cnt]))
344
                        *decided = loc;
345
                      break;
346
                    }
347
                  if (match_string (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt), rp))
348
                    {
349
                      if (*decided == not
350
                          && strcmp (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt),
351
                                     ab_weekday_name[cnt]))
352
                        *decided = loc;
353
                      break;
354
                    }
355
                }
356
#endif
357
              if (*decided != loc
358
                  && (match_string (weekday_name[cnt], rp)
359
                      || match_string (ab_weekday_name[cnt], rp)))
360
                {
361
                  *decided = raw;
362
                  break;
363
                }
364
            }
365
          if (cnt == 7)
366
            /* Does not match a weekday name.  */
367
            return NULL;
368
          tm->tm_wday = cnt;
369
          have_wday = 1;
370
          break;
371
        case 'b':
372
        case 'B':
373
        case 'h':
374
          /* Match month name.  */
375
          for (cnt = 0; cnt < 12; ++cnt)
376
            {
377
#ifdef _NL_CURRENT
378
              if (*decided !=raw)
379
                {
380
                  if (match_string (_NL_CURRENT (LC_TIME, MON_1 + cnt), rp))
381
                    {
382
                      if (*decided == not
383
                          && strcmp (_NL_CURRENT (LC_TIME, MON_1 + cnt),
384
                                     month_name[cnt]))
385
                        *decided = loc;
386
                      break;
387
                    }
388
                  if (match_string (_NL_CURRENT (LC_TIME, ABMON_1 + cnt), rp))
389
                    {
390
                      if (*decided == not
391
                          && strcmp (_NL_CURRENT (LC_TIME, ABMON_1 + cnt),
392
                                     ab_month_name[cnt]))
393
                        *decided = loc;
394
                      break;
395
                    }
396
                }
397
#endif
398
              if (match_string (month_name[cnt], rp)
399
                  || match_string (ab_month_name[cnt], rp))
400
                {
401
                  *decided = raw;
402
                  break;
403
                }
404
            }
405
          if (cnt == 12)
406
            /* Does not match a month name.  */
407
            return NULL;
408
          tm->tm_mon = cnt;
409
          want_xday = 1;
410
          break;
411
        case 'c':
412
          /* Match locale's date and time format.  */
413
#ifdef _NL_CURRENT
414
          if (*decided != raw)
415
            {
416
              if (!recursive (_NL_CURRENT (LC_TIME, D_T_FMT)))
417
                {
418
                  if (*decided == loc)
419
                    return NULL;
420
                  else
421
                    rp = rp_backup;
422
                }
423
              else
424
                {
425
                  if (*decided == not &&
426
                      strcmp (_NL_CURRENT (LC_TIME, D_T_FMT), HERE_D_T_FMT))
427
                    *decided = loc;
428
                  want_xday = 1;
429
                  break;
430
                }
431
              *decided = raw;
432
            }
433
#endif
434
          if (!recursive (HERE_D_T_FMT))
435
            return NULL;
436
          want_xday = 1;
437
          break;
438
        case 'C':
439
          /* Match century number.  */
440
#ifdef _NL_CURRENT
441
        match_century:
442
#endif
443
          get_number (0, 99, 2);
444
          century = val;
445
          want_xday = 1;
446
          break;
447
        case 'd':
448
        case 'e':
449
          /* Match day of month.  */
450
          get_number (1, 31, 2);
451
          tm->tm_mday = val;
452
          have_mday = 1;
453
          want_xday = 1;
454
          break;
455
        case 'F':
456
          if (!recursive ("%Y-%m-%d"))
457
            return NULL;
458
          want_xday = 1;
459
          break;
460
        case 'x':
461
#ifdef _NL_CURRENT
462
          if (*decided != raw)
463
            {
464
              if (!recursive (_NL_CURRENT (LC_TIME, D_FMT)))
465
                {
466
                  if (*decided == loc)
467
                    return NULL;
468
                  else
469
                    rp = rp_backup;
470
                }
471
              else
472
                {
473
                  if (*decided == not
474
                      && strcmp (_NL_CURRENT (LC_TIME, D_FMT), HERE_D_FMT))
475
                    *decided = loc;
476
                  want_xday = 1;
477
                  break;
478
                }
479
              *decided = raw;
480
            }
481
#endif
482
          /* Fall through.  */
483
        case 'D':
484
          /* Match standard day format.  */
485
          if (!recursive (HERE_D_FMT))
486
            return NULL;
487
          want_xday = 1;
488
          break;
489
        case 'k':
490
        case 'H':
491
          /* Match hour in 24-hour clock.  */
492
          get_number (0, 23, 2);
493
          tm->tm_hour = val;
494
          have_I = 0;
495
          break;
496
        case 'I':
497
          /* Match hour in 12-hour clock.  */
498
          get_number (1, 12, 2);
499
          tm->tm_hour = val % 12;
500
          have_I = 1;
501
          break;
502
        case 'j':
503
          /* Match day number of year.  */
504
          get_number (1, 366, 3);
505
          tm->tm_yday = val - 1;
506
          have_yday = 1;
507
          break;
508
        case 'm':
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff