root / trunk / plugins / jsonrpc / plugin_webserver.c @ 1834
History | View | Annotate | Download (15 KB)
| 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  | 
              
| 25 | 
                  #include  | 
              
| 26 | 
                  #include  | 
              
| 27 | 
                  #include "nntpgrab_plugin.h"  | 
              
| 28 | 
                  #include "nntpgrab_utils.h"  | 
              
| 29 | 
                  #include "mongoose.h"  | 
              
| 30 | 
                  #include "json.h"  | 
              
| 31 | 
                  #include "jsonrpc.h"  | 
              
| 32 | 
                  #include "marshalers.h"  | 
              
| 33 | 
                   | 
              
| 34 | 
                  static struct mg_context *ctx = NULL;  | 
              
| 35 | 
                  static NGPlugin *plugin_data_global = NULL;  | 
              
| 36 | 
                  static int current_listen_port = 0;  | 
              
| 37 | 
                  static ngboolean ignore_config_changes = FALSE;
                 | 
              
| 38 | 
                   | 
              
| 39 | 
                  /* Webserver methods */
                 | 
              
| 40 | 
                  static void set_ignore_config_changes(NGPlugin *plugin_data);  | 
              
| 41 | 
                  static ngboolean start_webserver(NGPlugin *plugin_data, int port, char **errmsg);  | 
              
| 42 | 
                  static void stop_webserver(NGPlugin *plugin_data);  | 
              
| 43 | 
                  static void on_config_changed(NGPlugin *plugin_data, gpointer data);  | 
              
| 44 | 
                  static void on_log_message_received(struct mg_connection *conn, const struct mg_request_info *info, void *message);  | 
              
| 45 | 
                  static void process_favicon_request(struct mg_connection *conn, const struct mg_request_info *request_info, void *user_data);  | 
              
| 46 | 
                  static void process_jsonrpc_request(struct mg_connection *conn, const struct mg_request_info *request_info, void *user_data);  | 
              
| 47 | 
                  static void process_upload_request(struct mg_connection *conn, const struct mg_request_info *request_info, void *user_data);  | 
              
| 48 | 
                  void mongoose_hacks_set_plugin_data(NGPlugin *plugin_data);
                 | 
              
| 49 | 
                  ngboolean listen_on_port(struct mg_context *ctx, char *port);  | 
              
| 50 | 
                  void jsonrpc_tcp_force_disconnect(void);  | 
              
| 51 | 
                   | 
              
| 52 | 
                  /* JSON-RPC methods */
                 | 
              
| 53 | 
                  void jsonrpc_methods_register_methods(NGPlugin *plugin_data);
                 | 
              
| 54 | 
                  void jsonrpc_methods_unregister_methods(void);  | 
              
| 55 | 
                   | 
              
| 56 | 
                  /* JSON-RPC events */
                 | 
              
| 57 | 
                  void jsonrpc_connect_signal_handlers(NGPlugin *plugin_data);
                 | 
              
| 58 | 
                  void jsonrpc_disconnect_signal_handlers(NGPlugin *plugin_data);
                 | 
              
| 59 | 
                   | 
              
| 60 | 
                  void
                 | 
              
| 61 | 
                  nntpgrab_plugin_initialize(NGPlugin *plugin_data)  | 
              
| 62 | 
                  {
                 | 
              
| 63 | 
                      ng_plugin_set_name(plugin_data, "JSON-RPC");
                 | 
              
| 64 | 
                  ng_plugin_set_version(plugin_data, PACKAGE_VERSION);  | 
              
| 65 | 
                      ng_plugin_set_author(plugin_data, "Erik van Pienbroek");
                 | 
              
| 66 | 
                      ng_plugin_set_url(plugin_data, "https://www.nntpgrab.nl");
                 | 
              
| 67 | 
                      ng_plugin_set_description(plugin_data, "Allow NNTPGrab to be remotely controlled using JSON-RPC");
                 | 
              
| 68 | 
                   | 
              
| 69 | 
                  ng_plugin_register_function(plugin_data,  | 
              
| 70 | 
                                                  "webserver_start",
                 | 
              
| 71 | 
                  NG_PLUGIN_FUNCTION(start_webserver),  | 
              
| 72 | 
                  ng_plugin_marshal_BOOLEAN__INT_POINTER,  | 
              
| 73 | 
                  G_TYPE_BOOLEAN,  | 
              
| 74 | 
                                                  2, G_TYPE_INT, G_TYPE_POINTER);
                 | 
              
| 75 | 
                   | 
              
| 76 | 
                  ng_plugin_register_function(plugin_data,  | 
              
| 77 | 
                                                  "webserver_ignore_config_changes",
                 | 
              
| 78 | 
                  NG_PLUGIN_FUNCTION(set_ignore_config_changes),  | 
              
| 79 | 
                  ng_plugin_marshal_VOID__VOID,  | 
              
| 80 | 
                  G_TYPE_NONE,  | 
              
| 81 | 
                                                  0);
                 | 
              
| 82 | 
                   | 
              
| 83 | 
                      ng_plugin_set_required_event(plugin_data, "config_changed");
                 | 
              
| 84 | 
                      ng_plugin_set_required_event(plugin_data, "part_download_start");
                 | 
              
| 85 | 
                      ng_plugin_set_required_event(plugin_data, "part_done");
                 | 
              
| 86 | 
                      ng_plugin_set_required_event(plugin_data, "part_failed");
                 | 
              
| 87 | 
                      ng_plugin_set_required_event(plugin_data, "traffic_monitor_update");
                 | 
              
| 88 | 
                      ng_plugin_set_required_event(plugin_data, "part_progress_update");
                 | 
              
| 89 | 
                      ng_plugin_set_required_event(plugin_data, "collection_added");
                 | 
              
| 90 | 
                      ng_plugin_set_required_event(plugin_data, "collection_removed");
                 | 
              
| 91 | 
                      ng_plugin_set_required_event(plugin_data, "collection_modified");
                 | 
              
| 92 | 
                      ng_plugin_set_required_event(plugin_data, "file_added");
                 | 
              
| 93 | 
                      ng_plugin_set_required_event(plugin_data, "file_removed");
                 | 
              
| 94 | 
                      ng_plugin_set_required_event(plugin_data, "file_download_state_update");
                 | 
              
| 95 | 
                      ng_plugin_set_required_event(plugin_data, "file_state_changed");
                 | 
              
| 96 | 
                      ng_plugin_set_required_event(plugin_data, "connection_connecting");
                 | 
              
| 97 | 
                      ng_plugin_set_required_event(plugin_data, "connection_connected");
                 | 
              
| 98 | 
                      ng_plugin_set_required_event(plugin_data, "connection_disconnect");
                 | 
              
| 99 | 
                      ng_plugin_set_required_event(plugin_data, "schedular_state_changed");
                 | 
              
| 100 | 
                      ng_plugin_set_required_event(plugin_data, "log_message");
                 | 
              
| 101 | 
                      ng_plugin_set_required_event(plugin_data, "task_moved");
                 | 
              
| 102 | 
                      ng_plugin_set_required_event(plugin_data, "collection_moved");
                 | 
              
| 103 | 
                      ng_plugin_set_required_event(plugin_data, "all_downloads_completed");
                 | 
              
| 104 | 
                      ng_plugin_set_required_event(plugin_data, "plugin_loaded");
                 | 
              
| 105 | 
                      ng_plugin_set_required_event(plugin_data, "plugin_unloaded");
                 | 
              
| 106 | 
                      ng_plugin_set_required_event(plugin_data, "plugin_event");
                 | 
              
| 107 | 
                   | 
              
| 108 | 
                  ng_plugin_create_event(plugin_data, "num_active_connections_changed", 1);  | 
              
| 109 | 
                  }  | 
              
| 110 | 
                   | 
              
| 111 | 
                  ngboolean  | 
              
| 112 | 
                  nntpgrab_plugin_load(NGPlugin *plugin_data, char **errmsg)
                 | 
              
| 113 | 
                  {
                 | 
              
| 114 | 
                  NGConfigOpts opts;  | 
              
| 115 | 
                   | 
              
| 116 | 
                      g_return_val_if_fail(plugin_data != NULL, FALSE);
                 | 
              
| 117 | 
                      g_return_val_if_fail(errmsg != NULL, FALSE);
                 | 
              
| 118 | 
                      g_return_val_if_fail(ctx == NULL, FALSE);
                 | 
              
| 119 | 
                   | 
              
| 120 | 
                  plugin_data_global = plugin_data;  | 
              
| 121 | 
                   | 
              
| 122 | 
                  jsonrpc_methods_register_methods(plugin_data);  | 
              
| 123 | 
                   | 
              
| 124 | 
                  ng_plugin_connect_event(plugin_data, "config_changed", NG_PLUGIN_FUNCTION(on_config_changed), NULL);  | 
              
| 125 | 
                   | 
              
| 126 | 
                  opts = plugin_data->core_funcs.config_get_opts();  | 
              
| 127 | 
                      if (!opts.enable_webserver) {
                 | 
              
| 128 | 
                          return TRUE;
                 | 
              
| 129 | 
                  }  | 
              
| 130 | 
                   | 
              
| 131 | 
                      return start_webserver(plugin_data, opts.webserver_port, errmsg);
                 | 
              
| 132 | 
                  }  | 
              
| 133 | 
                   | 
              
| 134 | 
                  static void  | 
              
| 135 | 
                  set_ignore_config_changes(NGPlugin *plugin_data)  | 
              
| 136 | 
                  {
                 | 
              
| 137 | 
                  ignore_config_changes = TRUE;  | 
              
| 138 | 
                  }  | 
              
| 139 | 
                   | 
              
| 140 | 
                  static ngboolean
                 | 
              
| 141 | 
                  start_webserver(NGPlugin *plugin_data, int port, char **errmsg)  | 
              
| 142 | 
                  {
                 | 
              
| 143 | 
                      char *path;
                 | 
              
| 144 | 
                  char port_str[16];  | 
              
| 145 | 
                  char opt[128];  | 
              
| 146 | 
                   | 
              
| 147 | 
                      g_return_val_if_fail(plugin_data != NULL, FALSE);
                 | 
              
| 148 | 
                      g_return_val_if_fail(errmsg != NULL, FALSE);
                 | 
              
| 149 | 
                   | 
              
| 150 | 
                      if (ctx) {
                 | 
              
| 151 | 
                          if (current_listen_port == port) {
                 | 
              
| 152 | 
                              return TRUE;
                 | 
              
| 153 | 
                  }  | 
              
| 154 | 
                   | 
              
| 155 | 
                  stop_webserver(plugin_data);  | 
              
| 156 | 
                  }  | 
              
| 157 | 
                   | 
              
| 158 | 
                  memset(&port_str, 0, sizeof(port_str));  | 
              
| 159 | 
                  snprintf(port_str, sizeof(port_str) - 1, "%i", port);  | 
              
| 160 | 
                   | 
              
| 161 | 
                  if ((ctx = mg_start()) == NULL) {  | 
              
| 162 | 
                          *errmsg = g_strdup(_("Unable to start embedded webserver"));
                 | 
              
| 163 | 
                          return FALSE;
                 | 
              
| 164 | 
                  }  | 
              
| 165 | 
                   | 
              
| 166 | 
                  mg_set_log_callback(ctx, on_log_message_received);  | 
              
| 167 | 
                   | 
              
| 168 | 
                  listen_on_port(ctx, port_str);  | 
              
| 169 | 
                   | 
              
| 170 | 
                  mg_set_option(ctx, "idle_time", "3");  | 
              
| 171 | 
                  mg_set_option(ctx, "dir_list", "0");  | 
              
| 172 | 
                  if (g_getenv("NNTPGRAB_WWWDIR")) {  | 
              
| 173 | 
                  path = (char*) g_getenv("NNTPGRAB_WWWDIR");  | 
              
| 174 | 
                      } else {
                 | 
              
| 175 | 
                  path = WWW_DIR;  | 
              
| 176 | 
                  }  | 
              
| 177 | 
                      mg_set_option(ctx, "root", path);
                 | 
              
| 178 | 
                  mg_set_option(ctx, "auth_realm", "NNTPGrab embedded webserver");  | 
              
| 179 | 
                   | 
              
| 180 | 
                  if (g_getenv("NNTPGRAB_CONFIG_DIR")) {  | 
              
| 181 | 
                  path = g_build_filename(g_getenv("NNTPGRAB_CONFIG_DIR"), "NNTPGrab", "htpasswd", NULL);  | 
              
| 182 | 
                      } else {
                 | 
              
| 183 | 
                  path = g_build_filename(g_get_user_config_dir(), "NNTPGrab", "htpasswd", NULL);  | 
              
| 184 | 
                  }  | 
              
| 185 | 
                      if (!g_file_test(path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
                 | 
              
| 186 | 
                          /* Password file doesn't exist yet, generate a default one */
                 | 
              
| 187 | 
                  mg_modify_passwords_file(ctx, path, "admin", "admin");  | 
              
| 188 | 
                  }  | 
              
| 189 | 
                  memset(&opt, 0, sizeof(opt));  | 
              
| 190 | 
                  snprintf(opt, sizeof(opt) - 1, "/jsonrpc=%s", path);  | 
              
| 191 | 
                      mg_set_option(ctx, "protect", opt);
                 | 
              
| 192 | 
                  g_free(path);  | 
              
| 193 | 
                   | 
              
| 194 | 
                      //mg_set_uri_callback(ctx, "/", &process_index_request, NULL);
                 | 
              
| 195 | 
                  mg_set_uri_callback(ctx, "/favicon.ico", &process_favicon_request, NULL);  | 
              
| 196 | 
                  mg_set_uri_callback(ctx, "/jsonrpc", &process_jsonrpc_request, NULL);  | 
              
| 197 | 
                      mg_set_uri_callback(ctx, "/upload", &process_upload_request, plugin_data);
                 | 
              
| 198 | 
                   | 
              
| 199 | 
                  mongoose_hacks_set_plugin_data(plugin_data);  | 
              
| 200 | 
                  jsonrpc_connect_signal_handlers(plugin_data);  | 
              
| 201 | 
                   | 
              
| 202 | 
                  current_listen_port = port;  | 
              
| 203 | 
                   | 
              
| 204 | 
                      return TRUE;
                 | 
              
| 205 | 
                  }  | 
              
| 206 | 
                   | 
              
| 207 | 
                  ngboolean  | 
              
| 208 | 
                  nntpgrab_plugin_can_unload(NGPlugin *plugin_data, char **reason)
                 | 
              
| 209 | 
                  {
                 | 
              
| 210 | 
                      return TRUE;
                 | 
              
| 211 | 
                  }  | 
              
| 212 | 
                   | 
              
| 213 | 
                  void
                 | 
              
| 214 | 
                  nntpgrab_plugin_unload(NGPlugin *plugin_data)  | 
              
| 215 | 
                  {
                 | 
              
| 216 | 
                  NGConfigOpts opts = plugin_data->core_funcs.config_get_opts();  | 
              
| 217 | 
                   | 
              
| 218 | 
                      g_return_if_fail(plugin_data != NULL);
                 | 
              
| 219 | 
                   | 
              
| 220 | 
                      if (opts.enable_webserver) {
                 | 
              
| 221 | 
                          g_return_if_fail(ctx != NULL);
                 | 
              
| 222 | 
                   | 
              
| 223 | 
                  stop_webserver(plugin_data);  | 
              
| 224 | 
                  }  | 
              
| 225 | 
                   | 
              
| 226 | 
                      mongoose_hacks_set_plugin_data(NULL);
                 | 
              
| 227 | 
                      plugin_data_global = NULL;
                 | 
              
| 228 | 
                   | 
              
| 229 | 
                      /* Free the buffer containing the most recent JSON-RPC events */
                 | 
              
| 230 | 
                      jsonrpc_set_event_list_size(0);
                 | 
              
| 231 | 
                  }  | 
              
| 232 | 
                   | 
              
| 233 | 
                  static void  | 
              
| 234 | 
                  stop_webserver(NGPlugin *plugin_data)  | 
              
| 235 | 
                  {
                 | 
              
| 236 | 
                      g_return_if_fail(plugin_data != NULL);
                 | 
              
| 237 | 
                      g_return_if_fail(ctx != NULL);
                 | 
              
| 238 | 
                   | 
              
| 239 | 
                  jsonrpc_tcp_force_disconnect();  | 
              
| 240 | 
                   | 
              
| 241 | 
                  mg_stop(ctx);  | 
              
| 242 | 
                      ctx = NULL;
                 | 
              
| 243 | 
                      current_listen_port = 0;
                 | 
              
| 244 | 
                   | 
              
| 245 | 
                  jsonrpc_disconnect_signal_handlers(plugin_data);  | 
              
| 246 | 
                  }  | 
              
| 247 | 
                   | 
              
| 248 | 
                  void
                 | 
              
| 249 | 
                  nntpgrab_plugin_destroy(NGPlugin *plugin_data)  | 
              
| 250 | 
                  {
                 | 
              
| 251 | 
                  jsonrpc_methods_unregister_methods();  | 
              
| 252 | 
                  }  | 
              
| 253 | 
                   | 
              
| 254 | 
                  int
                 | 
              
| 255 | 
                  nntpgrab_plugin_get_version(void)
                 | 
              
| 256 | 
                  {
                 | 
              
| 257 | 
                      return NNTPGRAB_PLUGIN_API_VERSION;
                 | 
              
| 258 | 
                  }  | 
              
| 259 | 
                   | 
              
| 260 | 
                  static void  | 
              
| 261 | 
                  on_config_changed(NGPlugin *plugin_data, gpointer data)  | 
              
| 262 | 
                  {
                 | 
              
| 263 | 
                  NGConfigOpts opts = plugin_data->core_funcs.config_get_opts();  | 
              
| 264 | 
                  char *errmsg = NULL;  | 
              
| 265 | 
                   | 
              
| 266 | 
                      if (ignore_config_changes) {
                 | 
              
| 267 | 
                          return;
                 | 
              
| 268 | 
                  }  | 
              
| 269 | 
                   | 
              
| 270 | 
                      /* Do we need to stop the embedded webserver? */
                 | 
              
| 271 | 
                  if (!opts.enable_webserver && ctx != NULL) {  | 
              
| 272 | 
                  stop_webserver(plugin_data);  | 
              
| 273 | 
                          return;
                 | 
              
| 274 | 
                  }  | 
              
| 275 | 
                   | 
              
| 276 | 
                      /* Do we need to start the embedded webserver? */
                 | 
              
| 277 | 
                  if (opts.enable_webserver && ctx == NULL) {  | 
              
| 278 | 
                          if (!start_webserver(plugin_data, opts.webserver_port, &errmsg)) {
                 | 
              
| 279 | 
                              ng_plugin_emit_log_msg(plugin_data, NG_LOG_LEVEL_WARNING, _("Unable to start the embedded webserver: %s"), errmsg);
                 | 
              
| 280 | 
                  g_free(errmsg);  | 
              
| 281 | 
                  }  | 
              
| 282 | 
                  }  | 
              
| 283 | 
                   | 
              
| 284 | 
                      /* Did the webserver port change? */
                 | 
              
| 285 | 
                      if (opts.enable_webserver && opts.webserver_port != current_listen_port) {
                 | 
              
| 286 | 
                  stop_webserver(plugin_data);  | 
              
| 287 | 
                          if (!start_webserver(plugin_data, opts.webserver_port, &errmsg)) {
                 | 
              
| 288 | 
                              ng_plugin_emit_log_msg(plugin_data, NG_LOG_LEVEL_WARNING, _("Unable to re-start the embedded webserver: %s"), errmsg);
                 | 
              
| 289 | 
                  g_free(errmsg);  | 
              
| 290 | 
                  }  | 
              
| 291 | 
                  }  | 
              
| 292 | 
                  }  | 
              
| 293 | 
                   | 
              
| 294 | 
                  static void  | 
              
| 295 | 
                  process_favicon_request(struct mg_connection *conn, const struct mg_request_info *request_info, void *user_data)  | 
              
| 296 | 
                  {
                 | 
              
| 297 | 
                  mg_printf(conn, "%s", "HTTP/1.1 404 File not found\r\n\r\n");  | 
              
| 298 | 
                  }  | 
              
| 299 | 
                   | 
              
| 300 | 
                  static void  | 
              
| 301 | 
                  process_jsonrpc_request(struct mg_connection *conn, const struct mg_request_info *request_info, void *user_data)  | 
              
| 302 | 
                  {
                 | 
              
| 303 | 
                      char *response;
                 | 
              
| 304 | 
                  char post_data[1024];  | 
              
| 305 | 
                  int response_length = 0;  | 
              
| 306 | 
                   | 
              
| 307 | 
                  mg_printf(conn, "%s", "HTTP/1.1 200 OK\r\n");  | 
              
| 308 | 
                  mg_printf(conn, "%s", "Content-Type: text/plain\r\n");  | 
              
| 309 | 
                   | 
              
| 310 | 
                  if (strcmp(request_info->request_method, "POST") ||  | 
              
| 311 | 
                          request_info->post_data_len == 0) {
                 | 
              
| 312 | 
                   | 
              
| 313 | 
                  mg_printf(conn, "\r\n%s", "This URI should only be used for JSON-RPC requests\r\n");  | 
              
| 314 | 
                          return;
                 | 
              
| 315 | 
                  }  | 
              
| 316 | 
                   | 
              
| 317 | 
                      /* We need to duplicate the post_data here as it isn't NULL-terminated.. */
                 | 
              
| 318 | 
                  if (request_info->post_data_len > sizeof(post_data) - 1) {  | 
              
| 319 | 
                          /* Refuse to handle such a large request */
                 | 
              
| 320 | 
                  mg_printf(conn, "\r\n%s", "Request is too large to process\r\n");  | 
              
| 321 | 
                          return;
                 | 
              
| 322 | 
                  }  | 
              
| 323 | 
                  memset(&post_data, 0, sizeof(post_data));  | 
              
| 324 | 
                  strncpy(post_data, request_info->post_data, request_info->post_data_len);  | 
              
| 325 | 
                  response = jsonrpc_process(post_data, conn);  | 
              
| 326 | 
                   | 
              
| 327 | 
                      g_print("post_data = %s\n", post_data);
                 | 
              
| 328 | 
                      g_print("post_data_len = %i\n", request_info->post_data_len);
                 | 
              
| 329 | 
                      g_print("response = %s\n", response);
                 | 
              
| 330 | 
                   | 
              
| 331 | 
                      g_return_if_fail(response != NULL);
                 | 
              
| 332 | 
                   | 
              
| 333 | 
                  response_length = strlen(response);  | 
              
| 334 | 
                   | 
              
| 335 | 
                      mg_printf(conn, "Content-Length: %d\r\n\r\n", response_length);
                 | 
              
| 336 | 
                  mg_write(conn, response, response_length);  | 
              
| 337 | 
                   | 
              
| 338 | 
                  free(response);  | 
              
| 339 | 
                  }  | 
              
| 340 | 
                   | 
              
| 341 | 
                  static void  | 
              
| 342 | 
                  process_upload_request(struct mg_connection *conn, const struct mg_request_info *request_info, void *user_data)  | 
              
| 343 | 
                  {
                 | 
              
| 344 | 
                  NGPlugin *plugin_data = (NGPlugin*) user_data;  | 
              
| 345 | 
                  NNTPGrabNZB *nzb;  | 
              
| 346 | 
                  NGList *list;  | 
              
| 347 | 
                  char *errmsg = NULL;  | 
              
| 348 | 
                  char *warnings = NULL;  | 
              
| 349 | 
                      char *nzb_data;
                 | 
              
| 350 | 
                      char *collection_name;
                 | 
              
| 351 | 
                   | 
              
| 352 | 
                      g_return_if_fail(plugin_data != NULL);
                 | 
              
| 353 | 
                   | 
              
| 354 | 
                  if (strcmp(request_info->request_method, "POST") ||  | 
              
| 355 | 
                          request_info->post_data_len == 0) {
                 | 
              
| 356 | 
                   | 
              
| 357 | 
                  mg_printf(conn, "%s", "HTTP/1.1 400 Bad request\r\n");  | 
              
| 358 | 
                  mg_printf(conn, "%s", "Content-Type: text/plain\r\n\r\n");  | 
              
| 359 | 
                   | 
              
| 360 | 
                  mg_printf(conn, "%s", "This URI should only be used for NZB upload requests\r\n");  | 
              
| 361 | 
                          return;
                 | 
              
| 362 | 
                  }  | 
              
| 363 | 
                   | 
              
| 364 | 
                      collection_name = mg_get_var(conn, "collection_name");
                 | 
              
| 365 | 
                      if (!collection_name) {
                 | 
              
| 366 | 
                  mg_printf(conn, "%s", "HTTP/1.1 400 Bad request\r\n");  | 
              
| 367 | 
                  mg_printf(conn, "%s", "Content-Type: text/plain\r\n\r\n");  | 
              
| 368 | 
                   | 
              
| 369 | 
                  mg_printf(conn, "%s", "The argument collection_name is missing\r\n");  | 
              
| 370 | 
                          return;
                 | 
              
| 371 | 
                  }  | 
              
| 372 | 
                   | 
              
| 373 | 
                      nzb_data = mg_get_var(conn, "nzb_data");
                 | 
              
| 374 | 
                      if (!nzb_data) {
                 | 
              
| 375 | 
                  mg_printf(conn, "%s", "HTTP/1.1 400 Bad request\r\n");  | 
              
| 376 | 
                  mg_printf(conn, "%s", "Content-Type: text/plain\r\n\r\n");  | 
              
| 377 | 
                   | 
              
| 378 | 
                  mg_printf(conn, "%s", "The argument nzb_data is missing\r\n");  | 
              
| 379 | 
                          return;
                 | 
              
| 380 | 
                  }  | 
              
| 381 | 
                   | 
              
| 382 | 
                      g_print("collection_name = %s\n", collection_name);
                 | 
              
| 383 | 
                      g_print("nzb_data = %s\n", nzb_data);
                 | 
              
| 384 | 
                      g_print("post_data_len = %i\n", request_info->post_data_len);
                 | 
              
| 385 | 
                   | 
              
| 386 | 
                  mg_printf(conn, "%s", "HTTP/1.1 200 OK\r\n");  | 
              
| 387 | 
                  mg_printf(conn, "%s", "Content-Type: text/plain\r\n\r\n");  | 
              
| 388 | 
                   | 
              
| 389 | 
                      /* Try to parse the NZB file */
                 | 
              
| 390 | 
                      if (!(nzb = nntpgrab_utils_parse_nzb_file(nzb_data, &errmsg))) {
                 | 
              
| 391 | 
                          mg_printf(conn, "ERROR: Unable to parse NZB file: %s\r\n", errmsg);
                 | 
              
| 392 | 
                  ng_free(errmsg);  | 
              
| 393 | 
                          goto out;
                 | 
              
| 394 | 
                  }  | 
              
| 395 | 
                   | 
              
| 396 | 
                      /* Add all the files to the download queue */
                 | 
              
| 397 | 
                  list = nzb->files;  | 
              
| 398 | 
                      while (list) {
                 | 
              
| 399 | 
                  NNTPGrabNZBFile *file = list->data;  | 
              
| 400 | 
                   | 
              
| 401 | 
                          if (!plugin_data->core_funcs.schedular_add_file_to_queue(collection_name, file->subject, file->poster, file->stamp, file->filesize, file->groups, file->segments, &errmsg)) {
                 | 
              
| 402 | 
                              if (warnings) {
                 | 
              
| 403 | 
                  char *tmp = g_strdup_printf("%s\n%s", warnings, errmsg);  | 
              
| 404 | 
                  g_free(warnings);  | 
              
| 405 | 
                  warnings = tmp;  | 
              
| 406 | 
                              } else {
                 | 
              
| 407 | 
                                  warnings = g_strdup_printf(_("File could not be added to the download queue:\r\n%s"), errmsg);
                 | 
              
| 408 | 
                  }  | 
              
| 409 | 
                  g_free(errmsg);  | 
              
| 410 | 
                              errmsg = NULL;
                 | 
              
| 411 | 
                  }  | 
              
| 412 | 
                   | 
              
| 413 | 
                  list = ng_list_next(list);  | 
              
| 414 | 
                  }  | 
              
| 415 | 
                   | 
              
| 416 | 
                      /* Save the download queue */
                 | 
              
| 417 | 
                      if (!plugin_data->core_funcs.schedular_save_queue(&errmsg)) {
                 | 
              
| 418 | 
                          char *msg;
                 | 
              
| 419 | 
                          if (errmsg) {
                 | 
              
| 420 | 
                              msg = g_strdup_printf(_("Download queue could not be saved:\r\n%s"), errmsg);
                 | 
              
| 421 | 
                  g_free(errmsg);  | 
              
| 422 | 
                          } else {
                 | 
              
| 423 | 
                              msg = g_strdup_printf(_("Download queue could not be saved"));
                 | 
              
| 424 | 
                  }  | 
              
| 425 | 
                   | 
              
| 426 | 
                          mg_printf(conn, "ERROR: %s\r\n", msg);
                 | 
              
| 427 | 
                  g_free(msg);  | 
              
| 428 | 
                          goto out;
                 | 
              
| 429 | 
                  }  | 
              
| 430 | 
                   | 
              
| 431 | 
                      g_print("warnings = %s\n", warnings);
                 | 
              
| 432 | 
                   | 
              
| 433 | 
                      if (!warnings) {
                 | 
              
| 434 | 
                          mg_printf(conn, "OK: NZB file imported successfully\r\n");
                 | 
              
| 435 | 
                      } else {
                 | 
              
| 436 | 
                          mg_printf(conn, "WARN: %s\r\n", warnings);
                 | 
              
| 437 | 
                  g_free(warnings);  | 
              
| 438 | 
                  }  | 
              
| 439 | 
                   | 
              
| 440 | 
                  out:
                 | 
              
| 441 | 
                  free(collection_name);  | 
              
| 442 | 
                  free(nzb_data);  | 
              
| 443 | 
                      return;
                 | 
              
| 444 | 
                  }  | 
              
| 445 | 
                   | 
              
| 446 | 
                  static void  | 
              
| 447 | 
                  on_log_message_received(struct mg_connection *conn, const struct mg_request_info *info, void *message)  | 
              
| 448 | 
                  {
                 | 
              
| 449 | 
                      g_return_if_fail(plugin_data_global != NULL);
                 | 
              
| 450 | 
                   | 
              
| 451 | 
                  ng_plugin_emit_log_msg(plugin_data_global, NG_LOG_LEVEL_INFO, "%s", (char*) message);  | 
              
| 452 | 
                  }  | 
              
NNTPGrab

