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

