Esempio n. 1
0
static void cache_manager_render_start_cb(GenericDialog *fd, gpointer data)
{
	CleanData *cd = data;
	gchar *path;

	if (cd->list || !gtk_widget_get_sensitive(cd->button_start)) return;

	path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(cd->entry))));
	parse_out_relatives(path);

	if (!isdir(path))
		{
		warning_dialog(_("Invalid folder"),
				_("The specified folder can not be found."),
			       GTK_STOCK_DIALOG_WARNING, cd->gd->dialog);
		}
	else
		{
		FileData *dir_fd;
		gtk_widget_set_sensitive(cd->group, FALSE);
		gtk_widget_set_sensitive(cd->button_start, FALSE);
		gtk_widget_set_sensitive(cd->button_stop, TRUE);
		gtk_widget_set_sensitive(cd->button_close, FALSE);

		spinner_set_interval(cd->spinner, SPINNER_SPEED);

		dir_fd = file_data_new_dir(path);
		cache_manager_render_folder(cd, dir_fd);
		file_data_unref(dir_fd);
		while (cache_manager_render_file(cd));
		}

	g_free(path);
}
Esempio n. 2
0
int main(int argc, char *argv[])
{
  TALLOC_CTX *main_ctx=NULL;

  TR_INSTANCE *tr = NULL;
  struct cmdline_args opts;
  struct event_base *ev_base;
  struct tr_socket_event tids_ev;
  struct event *cfgwatch_ev;

  configure_signals();

  /* we're going to be multithreaded, so disable null context tracking */
  talloc_set_abort_fn(tr_abort);
  talloc_disable_null_tracking();
#if TALLOC_DEBUG_ENABLE
  talloc_set_log_fn(tr_talloc_log);
#endif /* TALLOC_DEBUG_ENABLE */
  main_ctx=talloc_new(NULL);

  /* Use standalone logging */
  tr_log_open();

  /***** parse command-line arguments *****/
  /* set defaults */
  opts.config_dir=".";

  /* parse the command line*/
  argp_parse(&argp, argc, argv, 0, 0, &opts);

  /* process options */
  remove_trailing_slash(opts.config_dir);

  /***** create a Trust Router instance *****/
  if (NULL == (tr = tr_create(main_ctx))) {
    tr_crit("Unable to create Trust Router instance, exiting.");
    return 1;
  }

  /***** initialize the trust path query server instance *****/
  if (NULL == (tr->tids = tids_create (tr))) {
    tr_crit("Error initializing Trust Path Query Server instance.");
    return 1;
  }

  /***** initialize the trust router protocol server instance *****/
  if (NULL == (tr->trps = trps_new(tr))) {
    tr_crit("Error initializing Trust Router Protocol Server instance.");
    return 1;
  }

  /***** process configuration *****/
  tr->cfgwatch=tr_cfgwatch_create(tr);
  if (tr->cfgwatch == NULL) {
    tr_crit("Unable to create configuration watcher object, exiting.");
    return 1;
  }
  tr->cfgwatch->config_dir=opts.config_dir;
  tr->cfgwatch->cfg_mgr=tr->cfg_mgr;
  tr->cfgwatch->update_cb=tr_config_changed; /* handle configuration changes */
  tr->cfgwatch->update_cookie=(void *)tr;
  if (0 != tr_read_and_apply_config(tr->cfgwatch)) {
    tr_crit("Error reading configuration, exiting.");
    return 1;
  }

  /***** Set up the event loop *****/
  ev_base=tr_event_loop_init(); /* Set up the event loop */
  if (ev_base==NULL) {
    tr_crit("Error initializing event loop.");
    return 1;
  }

  /* already set config_dir, fstat_list and n_files earlier */
  if (0 != tr_cfgwatch_event_init(ev_base, tr->cfgwatch, &cfgwatch_ev)) {
    tr_crit("Error initializing configuration file watcher.");
    return 1;
  }

  /*tr_status_event_init();*/ /* install status reporting events */

  /* install TID server events */
  if (0 != tr_tids_event_init(ev_base,
                              tr->tids,
                              tr->cfg_mgr,
                              tr->trps,
                             &tids_ev)) {
    tr_crit("Error initializing Trust Path Query Server instance.");
    return 1;
  }

  /* install TRP handler events */
  if (TRP_SUCCESS != tr_trps_event_init(ev_base, tr)) {
    tr_crit("Error initializing Trust Path Query Server instance.");
    return 1;
  }

  tr_event_loop_run(ev_base); /* does not return until we are done */

  tr_destroy(tr); /* thanks to talloc, should destroy everything */

  talloc_free(main_ctx);
  return 0;
}
Esempio n. 3
0
static int mod_http_resource(calipso_request_t *request)
{
    int fd;
    struct stat sb;
	char date[32];
	
    calipso_reply_t *reply = calipso_request_get_reply(request);
    calipso_resource_t *resource = calipso_reply_get_resource(reply);
    const char *filename = calipso_resource_get_path(resource);
	int http_status  = calipso_reply_get_status(reply);
	
	/* Set the default handler */
    calipso_request_set_handler(request, mod_http_reply);

	if (calipso_http_status_is_error(http_status)) {
		TRACE(" http error %d\n", http_status);
		return (0);
	}
	//XXX: IsHandler AddHandelr ...
	if ( is_file_of(filename, ".php") ) {
		return (0);
	}

	/* check method */
    if (strcasecmp(request->method, "GET")  != 0 &&
            strcasecmp(request->method, "HEAD") != 0) {
        calipso_reply_set_status(reply, HTTP_NOT_IMPLEMENTED);
        return (NOK);
    }
	/* stat the resource for other modules to know what type it is */
#ifdef _WIN32
	remove_trailing_slash(filename);
#endif
	if (stat(filename, &sb) < 0) {
	
        //TRACE("ERROR: %s %s\n", strerror(errno), filename);

        switch (errno) {
        case ENOTDIR:
        case ENOENT:
            calipso_reply_set_status(reply, HTTP_NOT_FOUND);
            break;
        case EACCES:
            calipso_reply_set_status(reply, HTTP_FORBIDDEN);
            break;
        case ENAMETOOLONG:
            calipso_reply_set_status(reply, HTTP_REQUEST_URI_TOO_LARGE);
            break;
        default:
            calipso_reply_set_status(reply, HTTP_INTERNAL_SERVER_ERROR);
        }

        return CPO_OK;
    }

    calipso_resource_set_stat(resource, &sb);

	cpo_http_time(date, &sb.st_mtime);
	
	/* modified_since */
	if(USE_HEADER_MODFIED_SINCE && 
		CPO_OK == mod_http_set_if_modified_since(request, date))
		return OK;
	
    if (! calipso_resource_is_file(resource)) {

        /* default state mod_directory override */
		if(!calipso_http_status_is_error(http_status)) {
        	calipso_reply_set_status(reply, HTTP_FORBIDDEN);
		}
        return CPO_OK;
    }

	/*XXX: fcache needed */
	fd = cpo_file_open(filename, 0);

	if(fd < 0 ){
		calipso_reply_set_status(reply, HTTP_INTERNAL_SERVER_ERROR);
		return CPO_ERR;
	}

	calipso_reply_set_header_value(reply, "Accept-Ranges", "bytes");

	if (!calipso_reply_get_header_value(reply, "content-range"))
		reply->content_length = calipso_resource_get_size(resource);
    	//calipso_reply_set_header_value(reply, "Content-Length", "%llu",
        //                               calipso_resource_get_size(resource));

	calipso_reply_set_header_value(reply, "Last-Modified", date);

    calipso_resource_set_file_descriptor(resource, fd);

	mod_http_partial_content(request, fd);

    return CPO_OK;
}
Esempio n. 4
0
static void config_window_apply(void)
{
	const gchar *buf;
	gchar *l_conf;
	gint new_style;
	gint i;
	gint refresh = FALSE;

	for(i = 0; i < GQVIEW_EDITOR_SLOTS; i++)
		{
		g_free(editor_name[i]);
		editor_name[i] = NULL;
		buf = gtk_entry_get_text(GTK_ENTRY(editor_name_entry[i]));
		if (buf && strlen(buf) > 0) editor_name[i] = g_strdup(buf);

		g_free(editor_command[i]);
		editor_command[i] = NULL;
		buf = gtk_entry_get_text(GTK_ENTRY(editor_command_entry[i]));
		if (buf && strlen(buf) > 0) editor_command[i] = g_strdup(buf);
		}
	layout_edit_update_all();

	g_free(startup_path);
	startup_path = NULL;
	buf = gtk_entry_get_text(GTK_ENTRY(startup_path_entry));
	if (buf && strlen(buf) > 0) startup_path = remove_trailing_slash(buf);

	g_free(safe_delete_path);
	safe_delete_path = NULL;
	buf = gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry));
	if (buf && strlen(buf) > 0) safe_delete_path = remove_trailing_slash(buf);

	if (show_dot_files != show_dot_files_c) refresh = TRUE;
	if (file_sort_case_sensitive != file_sort_case_sensitive_c) refresh = TRUE;
	if (file_filter_disable != file_filter_disable_c) refresh = TRUE;

	startup_path_enable = startup_path_enable_c;
	confirm_delete = confirm_delete_c;
	enable_delete_key = enable_delete_key_c;
	safe_delete_enable = safe_delete_enable_c;
	safe_delete_size = safe_delete_size_c;
	restore_tool = restore_tool_c;
	save_window_positions = save_window_positions_c;
	zoom_mode = zoom_mode_c;
	two_pass_zoom = two_pass_zoom_c;
	fit_window = fit_window_c;
	limit_window_size = limit_window_size_c;
	zoom_to_fit_expands = zoom_to_fit_expands_c;
	max_window_size = max_window_size_c;
	progressive_key_scrolling = progressive_key_scrolling_c;
	thumb_max_width = thumb_max_width_c;
	thumb_max_height = thumb_max_height_c;
	enable_thumb_caching = enable_thumb_caching_c;
	enable_thumb_dirs = enable_thumb_dirs_c;
	thumbnail_fast = thumbnail_fast_c;
#if 0
	use_xvpics_thumbnails = use_xvpics_thumbnails_c;
#endif
	thumbnail_spec_standard = thumbnail_spec_standard_c;
	enable_metadata_dirs = enable_metadata_dirs_c;
	show_dot_files = show_dot_files_c;
	file_sort_case_sensitive = file_sort_case_sensitive_c;
	file_filter_disable = file_filter_disable_c;

	slideshow_random = slideshow_random_c;
	slideshow_repeat = slideshow_repeat_c;
	slideshow_delay = slideshow_delay_c;

	mousewheel_scrolls = mousewheel_scrolls_c;

	enable_in_place_rename = enable_in_place_rename_c;

	collection_rectangular_selection = collection_rectangular_selection_c;

	tile_cache_max = tile_cache_max_c;

	thumbnail_quality = thumbnail_quality_c;
	zoom_quality = zoom_quality_c;

	zoom_increment = zoom_increment_c;

	enable_read_ahead = enable_read_ahead_c;

	if (black_window_background != black_window_background_c)
		{
		black_window_background = black_window_background_c;

		layout_colors_update();
		view_window_colors_update();
		}

	fullscreen_screen = fullscreen_screen_c;
	fullscreen_clean_flip = fullscreen_clean_flip_c;
	fullscreen_disable_saver = fullscreen_disable_saver_c;
	fullscreen_above = fullscreen_above_c;

	update_on_time_change = update_on_time_change_c;
	exif_rotate_enable = exif_rotate_enable_c;

	dupe_custom_threshold = dupe_custom_threshold_c;

	tree_descend_subdirs = tree_descend_subdirs_c;

#ifdef HAVE_LCMS
	for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
		{
		g_free(color_profile_input_name[i]);
		color_profile_input_name[i] = NULL;
		buf = gtk_entry_get_text(GTK_ENTRY(color_profile_input_name_entry[i]));
		if (buf && strlen(buf) > 0) color_profile_input_name[i] = g_strdup(buf);

		g_free(color_profile_input_file[i]);
		color_profile_input_file[i] = NULL;
		buf = gtk_entry_get_text(GTK_ENTRY(color_profile_input_file_entry[i]));
		if (buf && strlen(buf) > 0) color_profile_input_file[i] = g_strdup(buf);
		}
	g_free(color_profile_screen_file);
	color_profile_screen_file = NULL;
	buf = gtk_entry_get_text(GTK_ENTRY(color_profile_screen_file_entry));
	if (buf && strlen(buf) > 0) color_profile_screen_file = g_strdup(buf);
#endif

	l_conf = layout_config_get(layout_widget, &new_style);

	if (new_style != layout_style ||
	    (l_conf == NULL) != (layout_order == NULL) ||
	    !layout_order ||
	    strcmp(buf, layout_order) != 0)
		{
		if (refresh) filter_rebuild();
		refresh = FALSE;

		g_free(layout_order);
		layout_order = l_conf;
		l_conf = NULL;

		layout_style = new_style;

		layout_styles_update();
		}

	g_free(l_conf);

	image_options_sync();

	if (refresh)
		{
		filter_rebuild();
		layout_refresh(NULL);
		}
}
Esempio n. 5
0
/*!
 * \internal
 * \brief ARI HTTP handler.
 *
 * This handler takes the HTTP request and turns it into the appropriate
 * RESTful request (conversion to JSON, routing, etc.)
 *
 * \param ser TCP session.
 * \param urih URI handler.
 * \param uri URI requested.
 * \param method HTTP method.
 * \param get_params HTTP \c GET params.
 * \param headers HTTP headers.
 */
static int ast_ari_callback(struct ast_tcptls_session_instance *ser,
                            const struct ast_http_uri *urih,
                            const char *uri,
                            enum ast_http_method method,
                            struct ast_variable *get_params,
                            struct ast_variable *headers)
{
    RAII_VAR(struct ast_ari_conf *, conf, NULL, ao2_cleanup);
    RAII_VAR(struct ast_str *, response_body, ast_str_create(256), ast_free);
    RAII_VAR(struct ast_ari_conf_user *, user, NULL, ao2_cleanup);
    struct ast_ari_response response = {};
    RAII_VAR(struct ast_variable *, post_vars, NULL, ast_variables_destroy);

    if (!response_body) {
        ast_http_request_close_on_completion(ser);
        ast_http_error(ser, 500, "Server Error", "Out of memory");
        return 0;
    }

    response.headers = ast_str_create(40);
    if (!response.headers) {
        ast_http_request_close_on_completion(ser);
        ast_http_error(ser, 500, "Server Error", "Out of memory");
        return 0;
    }

    conf = ast_ari_config_get();
    if (!conf || !conf->general) {
        ast_free(response.headers);
        ast_http_request_close_on_completion(ser);
        ast_http_error(ser, 500, "Server Error", "URI handler config missing");
        return 0;
    }

    process_cors_request(headers, &response);

    /* Process form data from a POST. It could be mixed with query
     * parameters, which seems a bit odd. But it's allowed, so that's okay
     * with us.
     */
    post_vars = ast_http_get_post_vars(ser, headers);
    if (!post_vars) {
        switch (errno) {
        case EFBIG:
            ast_ari_response_error(&response, 413,
                                   "Request Entity Too Large",
                                   "Request body too large");
            goto request_failed;
        case ENOMEM:
            ast_http_request_close_on_completion(ser);
            ast_ari_response_error(&response, 500,
                                   "Internal Server Error",
                                   "Out of memory");
            goto request_failed;
        case EIO:
            ast_ari_response_error(&response, 400,
                                   "Bad Request", "Error parsing request body");
            goto request_failed;
        }
    }
    if (get_params == NULL) {
        get_params = post_vars;
    } else if (get_params && post_vars) {
        /* Has both post_vars and get_params */
        struct ast_variable *last_var = post_vars;
        while (last_var->next) {
            last_var = last_var->next;
        }
        /* The duped get_params will get freed when post_vars gets
         * ast_variables_destroyed.
         */
        last_var->next = ast_variables_dup(get_params);
        get_params = post_vars;
    }

    user = authenticate_user(get_params, headers);
    if (response.response_code > 0) {
        /* POST parameter processing error. Do nothing. */
    } else if (!user) {
        /* Per RFC 2617, section 1.2: The 401 (Unauthorized) response
         * message is used by an origin server to challenge the
         * authorization of a user agent. This response MUST include a
         * WWW-Authenticate header field containing at least one
         * challenge applicable to the requested resource.
         */
        ast_ari_response_error(&response, 401, "Unauthorized", "Authentication required");

        /* Section 1.2:
         *   realm       = "realm" "=" realm-value
         *   realm-value = quoted-string
         * Section 2:
         *   challenge   = "Basic" realm
         */
        ast_str_append(&response.headers, 0,
                       "WWW-Authenticate: Basic realm=\"%s\"\r\n",
                       conf->general->auth_realm);
    } else if (!ast_fully_booted) {
        ast_http_request_close_on_completion(ser);
        ast_ari_response_error(&response, 503, "Service Unavailable", "Asterisk not booted");
    } else if (user->read_only && method != AST_HTTP_GET && method != AST_HTTP_OPTIONS) {
        ast_ari_response_error(&response, 403, "Forbidden", "Write access denied");
    } else if (ast_ends_with(uri, "/")) {
        remove_trailing_slash(uri, &response);
    } else if (ast_begins_with(uri, "api-docs/")) {
        /* Serving up API docs */
        if (method != AST_HTTP_GET) {
            ast_ari_response_error(&response, 405, "Method Not Allowed", "Unsupported method");
        } else {
            /* Skip the api-docs prefix */
            ast_ari_get_docs(strchr(uri, '/') + 1, headers, &response);
        }
    } else {
        /* Other RESTful resources */
        ast_ari_invoke(ser, uri, method, get_params, headers,
                       &response);
    }

    if (response.no_response) {
        /* The handler indicates no further response is necessary.
         * Probably because it already handled it */
        ast_free(response.headers);
        return 0;
    }

request_failed:
    /* If you explicitly want to have no content, set message to
     * ast_json_null().
     */
    ast_assert(response.message != NULL);
    ast_assert(response.response_code > 0);

    /* response.message could be NULL, in which case the empty response_body
     * is correct
     */
    if (response.message && !ast_json_is_null(response.message)) {
        ast_str_append(&response.headers, 0,
                       "Content-type: application/json\r\n");
        if (ast_json_dump_str_format(response.message, &response_body,
                                     conf->general->format) != 0) {
            /* Error encoding response */
            response.response_code = 500;
            response.response_text = "Internal Server Error";
            ast_str_set(&response_body, 0, "%s", "");
            ast_str_set(&response.headers, 0, "%s", "");
        }
    }

    ast_debug(3, "Examining ARI response:\n%d %s\n%s\n%s\n", response.response_code,
              response.response_text, ast_str_buffer(response.headers), ast_str_buffer(response_body));
    ast_http_send(ser, method, response.response_code,
                  response.response_text, response.headers, response_body,
                  0, 0);
    /* ast_http_send takes ownership, so we don't have to free them */
    response_body = NULL;

    ast_json_unref(response.message);
    return 0;
}
Esempio n. 6
0
static void file_dialog_entry_cb(GtkWidget *widget, gpointer data)
{
	FileDialog *fdlg = data;
	g_free(fdlg->dest_path);
	fdlg->dest_path = remove_trailing_slash(gtk_entry_get_text(GTK_ENTRY(fdlg->entry)));
}
Esempio n. 7
0
static void set_default(max_hosts)
{
	int i, j;
	int default_section;
	char *string_default;
	int integer_default;
	bool boolean_default;

	default_section = cfgSectionNameToNumber("default");
	if (default_section == -1) {
		fprintf(stderr, _("Section `default' is required.\n"));
		exit(1);
	}
	for (i = 0; i < max_hosts; i++) {
		for (j = 0; config_table[j].type != CFG_END; j++) {
			switch (config_table[j].type) {
			case CFG_STRING:
				if (*(*(char ***) (config_table[j].value) + i) == NULL) {	/* The section doesn't have the parameter. */
					if (*(*(char ***) (config_table[j].value) + default_section) == NULL) {	/* Section `default' doesn't have the parameter. */
						string_default = get_string_internal_default(config_table[j].parameterName, i);
						if (string_default != NULL) {	/* If weex has internal default value, use it. */
							*(*(char ***) (config_table[j].value) + i) = string_default;
						}
					} else {	/* Section `default' has the parameter. */
						if (strcmp(config_table[j].parameterName, "CacheFile") == 0) { /* Add section name to the value, if parameter is `CacheFile'. */
							*(*(char ***) (config_table[j].value) + i) = str_concat(*(*(char ***) (config_table[j].value) + default_section), ".", cfgSectionNumberToName(i), NULL);
						} else {
							*(*(char ***) (config_table[j].value) + i) = str_dup(*(*(char ***) (config_table[j].value) + default_section));
						}
					}
				}
				break;
			case CFG_INT:
				if (*(*(int **) (config_table[j].value) + i) == -1) {	/* The section doesn't have the parameter. */
					if (*(*(int **) (config_table[j].value) + default_section) == -1) {	/* Section `default' doesn't have the parameter. */
						integer_default = get_integer_internal_default(config_table[j].parameterName);
						if (integer_default != -1) {	/* If weex has internal default value, use it. */
							*(*(int **) (config_table[j].value) + i) = integer_default;
						}
					} else {	/* Section `default' has the parameter. */
						*(*(int **) (config_table[j].value) + i) = *(*(int **) (config_table[j].value) + default_section);
					}
				}
				break;
			case CFG_BOOL:
				if (*(*(bool **) (config_table[j].value) + i) == -1) {	/* The section doesn't have the parameter. */
					if (*(*(bool **) (config_table[j].value) + default_section) == -1) {	/* Section `default' doesn't have the parameter. */
						boolean_default = get_boolean_internal_default(config_table[j].parameterName);
						if (boolean_default != -1) {	/* If weex has internal default value, use it. */
							*(*(bool **) (config_table[j].value) + i) = boolean_default;
						}
					} else {	/* Section `default' has the parameter. */
						*(*(bool **) (config_table[j].value) + i) = *(*(bool **) (config_table[j].value) + default_section);
					}
				}
				break;
			case CFG_STRING_LIST:
				if (*(*(cfgList ***) (config_table[j].value) + i) == NULL) {	/* The section doesn't have the parameter. */
					if (*(*(cfgList ***) (config_table[j].value) + default_section) != NULL) {	/* Section `default' have the parameter. */
						*(*(cfgList ***) (config_table[j].value) + i) = copy_cfg_list(*(*(cfgList ***) (config_table[j].value) + default_section));
					}
				}
				break;
			default:
				internal_error(__FILE__, __LINE__);
			}
			remove_trailing_slash(j, i);
			absolutize_path(j, i);
		}
	}
}
Esempio n. 8
0
/*!
 * \internal
 * \brief ARI HTTP handler.
 *
 * This handler takes the HTTP request and turns it into the appropriate
 * RESTful request (conversion to JSON, routing, etc.)
 *
 * \param ser TCP session.
 * \param urih URI handler.
 * \param uri URI requested.
 * \param method HTTP method.
 * \param get_params HTTP \c GET params.
 * \param headers HTTP headers.
 */
static int ast_ari_callback(struct ast_tcptls_session_instance *ser,
				const struct ast_http_uri *urih,
				const char *uri,
				enum ast_http_method method,
				struct ast_variable *get_params,
				struct ast_variable *headers)
{
	RAII_VAR(struct ast_ari_conf *, conf, NULL, ao2_cleanup);
	RAII_VAR(struct ast_str *, response_headers, ast_str_create(40), ast_free);
	RAII_VAR(struct ast_str *, response_body, ast_str_create(256), ast_free);
	RAII_VAR(struct ast_ari_conf_user *, user, NULL, ao2_cleanup);
	struct ast_ari_response response = {};
	int ret = 0;

	if (!response_headers || !response_body) {
		return -1;
	}

	response.headers = ast_str_create(40);
	if (!response.headers) {
		return -1;
	}

	conf = ast_ari_config_get();
	if (!conf || !conf->general) {
		return -1;
	}

	process_cors_request(headers, &response);

	user = authenticate_user(get_params, headers);
	if (!user) {
		/* Per RFC 2617, section 1.2: The 401 (Unauthorized) response
		 * message is used by an origin server to challenge the
		 * authorization of a user agent. This response MUST include a
		 * WWW-Authenticate header field containing at least one
		 * challenge applicable to the requested resource.
		 */
		response.response_code = 401;
		response.response_text = "Unauthorized";

		/* Section 1.2:
		 *   realm       = "realm" "=" realm-value
		 *   realm-value = quoted-string
		 * Section 2:
		 *   challenge   = "Basic" realm
		 */
		ast_str_append(&response.headers, 0,
			"WWW-Authenticate: Basic realm=\"%s\"\r\n",
			conf->general->auth_realm);
		response.message = ast_json_pack("{s: s}",
			"error", "Authentication required");
	} else if (!ast_fully_booted) {
		response.response_code = 503;
		response.response_text = "Service Unavailable";
		response.message = ast_json_pack("{s: s}",
			"error", "Asterisk not booted");
	} else if (user->read_only && method != AST_HTTP_GET && method != AST_HTTP_OPTIONS) {
		response.message = ast_json_pack("{s: s}",
			"error", "Write access denied");
		response.response_code = 403;
		response.response_text = "Forbidden";
	} else if (ast_ends_with(uri, "/")) {
		remove_trailing_slash(uri, &response);
	} else if (ast_begins_with(uri, "api-docs/")) {
		/* Serving up API docs */
		if (method != AST_HTTP_GET) {
			response.message =
				ast_json_pack("{s: s}",
					      "message", "Unsupported method");
			response.response_code = 405;
			response.response_text = "Method Not Allowed";
		} else {
			/* Skip the api-docs prefix */
			ast_ari_get_docs(strchr(uri, '/') + 1, headers, &response);
		}
	} else {
		/* Other RESTful resources */
		ast_ari_invoke(ser, uri, method, get_params, headers,
			&response);
	}

	if (response.no_response) {
		/* The handler indicates no further response is necessary.
		 * Probably because it already handled it */
		return 0;
	}

	/* If you explicitly want to have no content, set message to
	 * ast_json_null().
	 */
	ast_assert(response.message != NULL);
	ast_assert(response.response_code > 0);

	ast_str_append(&response_headers, 0, "%s", ast_str_buffer(response.headers));

	/* response.message could be NULL, in which case the empty response_body
	 * is correct
	 */
	if (response.message && !ast_json_is_null(response.message)) {
		ast_str_append(&response_headers, 0,
			       "Content-type: application/json\r\n");
		if (ast_json_dump_str_format(response.message, &response_body,
				conf->general->format) != 0) {
			/* Error encoding response */
			response.response_code = 500;
			response.response_text = "Internal Server Error";
			ast_str_set(&response_body, 0, "%s", "");
			ast_str_set(&response_headers, 0, "%s", "");
			ret = -1;
		}
	}

	ast_http_send(ser, method, response.response_code,
		      response.response_text, response_headers, response_body,
		      0, 0);
	/* ast_http_send takes ownership, so we don't have to free them */
	response_headers = NULL;
	response_body = NULL;

	ast_json_unref(response.message);
	return ret;
}