38#include <gmime/gmime.h>
39#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__) || defined(__Darwin__) || defined(SOLARIS)
55#ifdef GMIME_TYPE_CONTENT_TYPE
56#define AST_GMIME_VER_24
58#if defined(GMIME_MAJOR_VERSION) && (GMIME_MAJOR_VERSION >= 3)
59#define AST_GMIME_VER_30
71static void post_raw(GMimePart *part,
const char *post_dir,
const char *fn)
74 GMimeDataWrapper *content;
78 snprintf(filename,
sizeof(filename),
"%s/%s", post_dir, fn);
80 ast_debug(1,
"Posting raw data to %s\n", filename);
82 if ((fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666)) == -1) {
88 stream = g_mime_stream_fs_new(fd);
90#ifdef AST_GMIME_VER_30
91 content = g_mime_part_get_content(part);
93 content = g_mime_part_get_content_object(part);
95 g_mime_data_wrapper_write_to_stream(content, stream);
96 g_mime_stream_flush(stream);
98#ifndef AST_GMIME_VER_24
99 g_object_unref(content);
101 g_object_unref(stream);
110 stream = g_mime_stream_file_new(f);
112 parser = g_mime_parser_new_with_stream(stream);
113 g_mime_parser_set_respect_content_length(parser, 1);
115 g_object_unref(stream);
117 message = g_mime_parser_construct_message(parser
118#ifdef AST_GMIME_VER_30
123 g_object_unref(parser);
128#ifdef AST_GMIME_VER_24
139 if (GMIME_IS_MESSAGE_PART(part)) {
142 }
else if (GMIME_IS_MESSAGE_PARTIAL(part)) {
145 }
else if (GMIME_IS_MULTIPART(part)) {
146#ifndef AST_GMIME_VER_24
149 ast_log(
LOG_WARNING,
"Got unexpected GMIME_IS_MULTIPART, trying to process subparts\n");
150 l = GMIME_MULTIPART(part)->subparts;
158 }
else if (GMIME_IS_PART(part)) {
159 const char *filename;
161 if (
ast_strlen_zero(filename = g_mime_part_get_filename(GMIME_PART(part)))) {
162 ast_debug(1,
"Skipping part with no filename\n");
168 ast_log(
LOG_ERROR,
"Encountered unknown MIME part. This should never happen!\n");
179#ifdef AST_GMIME_VER_24
196 if (*
inbuf == *matchbuf) {
198 for (comp = 1; comp < matchlen; comp++) {
199 if (
inbuf[comp] != matchbuf[comp]) {
227 int find_filename = 0;
234 char * path_end, * path_start, * filespec;
236 if (
NULL ==
in ||
NULL == fout ||
NULL == boundary || 0 >= contentlen) {
240 boundary_len = strlen(boundary);
241 while (0 < contentlen || 0 < char_in_buf) {
243 if (contentlen >
sizeof(
buf) - char_in_buf) {
244 num_to_read =
sizeof(
buf)- char_in_buf;
246 num_to_read = contentlen;
249 if (0 < num_to_read) {
254 contentlen -= num_to_read;
255 char_in_buf += num_to_read;
259 path_end = filespec =
NULL;
260 x = strlen(
"filename=\"");
264 path_start = &
buf[marker];
265 for (path_end = path_start, x = 0; x < char_in_buf-marker; x++, path_end++) {
266 if (
'\\' == *path_end) {
269 if (
'\"' == *path_end) {
271 filespec = basename(path_start);
278 if (fwrite(
buf, 1, marker, fout) != marker) {
281 x = (int)(path_end+1 - filespec);
282 if (fwrite(filespec, 1, x, fout) != x) {
285 x = (int)(path_end+1 -
buf);
286 memmove(
buf, &(
buf[x]), char_in_buf-x);
293 if (char_in_buf < (boundary_len)) {
295 if (fwrite(
buf, 1, char_in_buf, fout) != char_in_buf) {
301 if (fwrite(
buf, 1, char_in_buf -(boundary_len -1), fout) != char_in_buf - (boundary_len - 1)) {
304 x = char_in_buf -(boundary_len -1);
305 memmove(
buf, &(
buf[x]), char_in_buf-x);
306 char_in_buf = (boundary_len -1);
310 if (fwrite(
buf, 1, marker + boundary_len, fout) != marker + boundary_len) {
313 x = marker + boundary_len;
314 memmove(
buf, &(
buf[x]), char_in_buf-x);
315 char_in_buf -= marker + boundary_len;
331 char *boundary_marker =
NULL;
334 ast_http_error(ser, 501,
"Not Implemented",
"Attempt to use unimplemented / unsupported method");
339 ast_http_error(ser, 400,
"Missing URI handle",
"There was an error parsing the request");
346 ast_http_error(ser, 403,
"Access Denied",
"Sorry, I cannot let you do that, Dave.");
352 ast_http_error(ser, 401,
"Unauthorized",
"You are not authorized to make this request.");
356 if (!(f = tmpfile())) {
358 ast_http_error(ser, 500,
"Internal server error",
"Could not create temp file.");
363 fprintf(f,
"%s: %s\r\n",
var->name,
var->value);
365 if (!strcasecmp(
var->name,
"Content-Length")) {
366 if ((sscanf(
var->value,
"%30u", &content_len)) != 1) {
370 ast_http_error(ser, 400,
"Bad Request",
"Invalid Content-Length in POST request!");
373 ast_debug(1,
"Got a Content-Length of %d\n", content_len);
374 }
else if (!strcasecmp(
var->name,
"Content-Type")) {
375 boundary_marker = strstr(
var->value,
"boundary=");
376 if (boundary_marker) {
377 boundary_marker += strlen(
"boundary=");
393 ast_debug(1,
"Cannot find boundary marker in POST request.\n");
395 ast_http_error(ser, 400,
"Bad Request",
"Cannot find boundary marker in POST request.");
399 if (fseek(f, SEEK_SET, 0)) {
402 ast_http_error(ser, 500,
"Internal server error",
"Failed to seek temp file back to beginning.");
406 post_dir = urih->
data;
412 ast_http_error(ser, 400,
"Bad Request",
"There was an error parsing the request.");
419 ast_http_error(ser, 400,
"Bad Request",
"There was an error parsing the request.");
445 if (!strcasecmp(v->
name,
"prefix")) {
474 urih->
key = __FILE__;
501#ifndef AST_GMIME_VER_30
Asterisk version information.
Asterisk main include file. File version handling, generic pbx functions.
#define ast_strdup(str)
A wrapper for strdup()
#define ast_calloc(num, len)
A wrapper for calloc()
Standard Command Line Interface.
Support for Private Asterisk HTTP Servers.
ast_http_method
HTTP Request methods known by Asterisk.
uint32_t ast_http_manid_from_vars(struct ast_variable *headers) attribute_pure
Return manager id, if exist, from request headers.
void ast_http_request_close_on_completion(struct ast_tcptls_session_instance *ser)
Request the HTTP connection be closed after this HTTP request.
void ast_http_error(struct ast_tcptls_session_instance *ser, int status, const char *title, const char *text)
Send HTTP error message and close socket.
int ast_http_uri_link(struct ast_http_uri *urihandler)
Register a URI handler.
void ast_http_uri_unlink_all_with_key(const char *key)
Unregister all handlers with matching key.
void ast_http_body_read_status(struct ast_tcptls_session_instance *ser, int read_success)
Update the body read success status.
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
@ CONFIG_FLAG_FILEUNCHANGED
#define ast_debug(level,...)
Log a DEBUG message.
ssize_t ast_iostream_read(struct ast_iostream *stream, void *buffer, size_t count)
Read data from an iostream.
A set of macros to manage forward-linked lists.
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define EVENT_FLAG_CONFIG
int astman_verify_session_writepermissions(uint32_t ident, int perm)
Verify a session's write permissions against a permission mask.
int astman_is_authed(uint32_t ident)
Determine if a manager session ident is authenticated.
Asterisk module definitions.
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
@ AST_MODULE_SUPPORT_CORE
#define ASTERISK_GPL_KEY
The text the key() function should return.
@ AST_MODULE_LOAD_SUCCESS
Asterisk file paths, configured in asterisk.conf.
static int readmimefile(struct ast_iostream *in, FILE *fout, char *boundary, int contentlen)
static GMimeMessage * parse_message(FILE *f)
static void process_message_callback(GMimeObject *part, gpointer user_data)
static void post_raw(GMimePart *part, const char *post_dir, const char *fn)
static char prefix[MAX_PREFIX]
static int find_sequence(char *inbuf, int inlen, char *matchbuf, int matchlen)
static int __ast_http_post_load(int reload)
static int http_post_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_vars, struct ast_variable *headers)
static int load_module(void)
static int unload_module(void)
static int process_message(GMimeMessage *message, const char *post_dir)
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Structure used to handle boolean flags.
Definition of a URI handler.
ast_http_callback callback
Support for dynamic strings.
describes a server instance
struct ast_iostream * stream
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
Generic support for tcp/tls servers in Asterisk.
static int inbuf(struct baseio *bio, FILE *fi)
utility used by inchar(), for base_encode()