40 #include <gmime/gmime.h>
41 #if defined (__OpenBSD__) || defined(__FreeBSD__) || defined(__Darwin__)
57 #ifdef GMIME_TYPE_CONTENT_TYPE
58 #define AST_GMIME_VER_24
70 static void post_raw(GMimePart *part,
const char *post_dir,
const char *fn)
72 char filename[PATH_MAX];
73 GMimeDataWrapper *content;
77 snprintf(filename,
sizeof(filename),
"%s/%s", post_dir, fn);
79 ast_debug(1,
"Posting raw data to %s\n", filename);
81 if ((fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666)) == -1) {
87 stream = g_mime_stream_fs_new(fd);
89 content = g_mime_part_get_content_object(part);
90 g_mime_data_wrapper_write_to_stream(content, stream);
91 g_mime_stream_flush(stream);
93 #ifndef AST_GMIME_VER_24
94 g_object_unref(content);
96 g_object_unref(stream);
105 stream = g_mime_stream_file_new(f);
107 parser = g_mime_parser_new_with_stream(stream);
108 g_mime_parser_set_respect_content_length(parser, 1);
110 g_object_unref(stream);
112 message = g_mime_parser_construct_message(parser);
114 g_object_unref(parser);
119 #ifdef AST_GMIME_VER_24
130 if (GMIME_IS_MESSAGE_PART(part)) {
133 }
else if (GMIME_IS_MESSAGE_PARTIAL(part)) {
136 }
else if (GMIME_IS_MULTIPART(part)) {
137 #ifndef AST_GMIME_VER_24
140 ast_log(
LOG_WARNING,
"Got unexpected GMIME_IS_MULTIPART, trying to process subparts\n");
141 l = GMIME_MULTIPART(part)->subparts;
149 }
else if (GMIME_IS_PART(part)) {
150 const char *filename;
152 if (
ast_strlen_zero(filename = g_mime_part_get_filename(GMIME_PART(part)))) {
153 ast_debug(1,
"Skipping part with no filename\n");
159 ast_log(
LOG_ERROR,
"Encountered unknown MIME part. This should never happen!\n");
170 #ifdef AST_GMIME_VER_24
186 for (current = 0; current < inlen-matchlen; current++, inbuf++) {
187 if (*inbuf == *matchbuf) {
189 for (comp = 1; comp < matchlen; comp++) {
190 if (inbuf[comp] != matchbuf[comp]) {
216 static int readmimefile(FILE * fin, FILE * fout,
char * boundary,
int contentlen)
218 int find_filename = 0;
225 char * path_end, * path_start, * filespec;
227 if (NULL == fin || NULL == fout || NULL == boundary || 0 >= contentlen) {
231 boundary_len = strlen(boundary);
232 while (0 < contentlen || 0 < char_in_buf) {
234 if (contentlen >
sizeof(buf) - char_in_buf) {
235 num_to_read =
sizeof(buf)- char_in_buf;
237 num_to_read = contentlen;
240 if (0 < num_to_read) {
241 if (fread(&(buf[char_in_buf]), 1, num_to_read, fin) < num_to_read) {
245 contentlen -= num_to_read;
246 char_in_buf += num_to_read;
250 path_end = filespec = NULL;
251 x = strlen(
"filename=\"");
255 path_start = &buf[marker];
256 for (path_end = path_start, x = 0; x < char_in_buf-marker; x++, path_end++) {
257 if (
'\\' == *path_end) {
260 if (
'\"' == *path_end) {
262 filespec = basename(path_start);
269 if (fwrite(buf, 1, marker, fout) != marker) {
272 x = (int)(path_end+1 - filespec);
273 if (fwrite(filespec, 1, x, fout) != x) {
276 x = (int)(path_end+1 - buf);
277 memmove(buf, &(buf[x]), char_in_buf-x);
282 marker =
find_sequence(buf, char_in_buf, boundary, boundary_len);
284 if (char_in_buf < (boundary_len)) {
286 if (fwrite(buf, 1, char_in_buf, fout) != char_in_buf) {
292 if (fwrite(buf, 1, char_in_buf -(boundary_len -1), fout) != char_in_buf - (boundary_len - 1)) {
295 x = char_in_buf -(boundary_len -1);
296 memmove(buf, &(buf[x]), char_in_buf-x);
297 char_in_buf = (boundary_len -1);
301 if (fwrite(buf, 1, marker + boundary_len, fout) != marker + boundary_len) {
304 x = marker + boundary_len;
305 memmove(buf, &(buf[x]), char_in_buf-x);
306 char_in_buf -= marker + boundary_len;
317 unsigned long ident = 0;
322 int message_count = 0;
323 char * boundary_marker = NULL;
326 ast_http_error(ser, 501,
"Not Implemented",
"Attempt to use unimplemented / unsupported method");
331 ast_http_error(ser, 403,
"Access Denied",
"Sorry, I cannot let you do that, Dave.");
336 ast_http_error(ser, 400,
"Missing URI handle",
"There was an error parsing the request");
341 for (var = cookies;
var; var = var->
next) {
342 if (!strcasecmp(var->
name,
"mansession_id")) {
343 sscanf(var->
value,
"%30lx", &ident);
352 ast_http_error(ser, 401,
"Unauthorized",
"You are not authorized to make this request.");
356 ast_http_error(ser, 401,
"Unauthorized",
"You are not authorized to make this request.");
360 if (!(f = tmpfile())) {
362 ast_http_error(ser, 500,
"Internal server error",
"Could not create temp file.");
366 for (var = headers;
var; var = var->
next) {
367 fprintf(f,
"%s: %s\r\n", var->
name, var->
value);
369 if (!strcasecmp(var->
name,
"Content-Length")) {
370 if ((sscanf(var->
value,
"%30u", &content_len)) != 1) {
373 ast_http_error(ser, 500,
"Internal server error",
"Invalid Content-Length in POST request!");
376 ast_debug(1,
"Got a Content-Length of %d\n", content_len);
377 }
else if (!strcasecmp(var->
name,
"Content-Type")) {
378 boundary_marker = strstr(var->
value,
"boundary=");
379 if (boundary_marker) {
380 boundary_marker += strlen(
"boundary=");
387 if (0 >
readmimefile(ser->
f, f, boundary_marker, content_len)) {
396 if (fseek(f, SEEK_SET, 0)) {
399 ast_http_error(ser, 500,
"Internal server error",
"Failed to seek temp file back to beginning.");
403 post_dir = urih->
data;
410 ast_http_error(ser, 400,
"Bad Request",
"The was an error parsing the request.");
416 g_object_unref(message);
417 ast_http_error(ser, 400,
"Bad Request",
"The was an error parsing the request.");
420 g_object_unref(message);
443 if (!strcasecmp(v->
name,
"prefix")) {
445 if (prefix[strlen(prefix)] ==
'/') {
446 prefix[strlen(prefix)] =
'\0';
472 urih->
key = __FILE__;
Asterisk main include file. File version handling, generic pbx functions.
static void process_message_callback(GMimeObject *part, gpointer user_data)
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.
ast_http_callback callback
Asterisk version information.
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
int ast_http_uri_link(struct ast_http_uri *urihandler)
Register a URI handler.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
static int load_module(void)
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)
Structure for variables, used for configurations and for channel variables.
struct ast_str * ast_str_create(size_t init_len)
Create a malloc'ed dynamic length string.
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
uint32_t ast_http_manid_from_vars(struct ast_variable *headers) attribute_pure
Return manager id, if exist, from request headers.
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
static int inbuf(struct baseio *bio, FILE *fi)
utility used by inchar(), for base_encode()
Generic support for tcp/tls servers in Asterisk.
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
static char prefix[MAX_PREFIX]
void ast_config_destroy(struct ast_config *config)
Destroys a config.
#define CONFIG_STATUS_FILEMISSING
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Support for Private Asterisk HTTP Servers.
#define ast_debug(level,...)
Log a DEBUG message.
int astman_is_authed(uint32_t ident)
Determinie if a manager session ident is authenticated.
static int process_message(GMimeMessage *message, const char *post_dir)
Asterisk file paths, configured in asterisk.conf.
static int __ast_http_post_load(int reload)
static force_inline int attribute_pure ast_strlen_zero(const char *s)
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
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
int astman_verify_session_writepermissions(uint32_t ident, int perm)
Verify a session's write permissions against a permission mask.
static int unload_module(void)
Structure used to handle boolean flags.
static void post_raw(GMimePart *part, const char *post_dir, const char *fn)
Standard Command Line Interface.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition of a URI handler.
static GMimeMessage * parse_message(FILE *f)
void ast_http_uri_unlink_all_with_key(const char *key)
Unregister all handlers with matching key.
struct ast_variable * next
#define CONFIG_STATUS_FILEINVALID
ast_http_method
HTTP Request methods known by Asterisk.
static int find_sequence(char *inbuf, int inlen, char *matchbuf, int matchlen)
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
static int readmimefile(FILE *fin, FILE *fout, char *boundary, int contentlen)
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
struct ast_variable * ast_http_get_cookies(struct ast_variable *headers)
Get cookie from Request headers.
#define CONFIG_STATUS_FILEUNCHANGED