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 |
|
| 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': |
|
Also available in: Unified diff
NNTPGrab

