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 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 195 for (current = 0; current < inlen-matchlen; current++, inbuf++) {
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);
291 marker =
find_sequence(buf, char_in_buf, boundary, boundary_len);
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.");
362 for (var = headers;
var; var = var->
next) {
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.");
418 g_object_unref(message);
419 ast_http_error(ser, 400,
"Bad Request",
"There was an error parsing the request.");
422 g_object_unref(message);
445 if (!strcasecmp(v->
name,
"prefix")) {
474 urih->
key = __FILE__;
501 #ifndef AST_GMIME_VER_30
struct ast_variable * next
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_name)
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.
#define CONFIG_STATUS_FILEINVALID
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)
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Structure for variables, used for configurations and for channel variables.
uint32_t ast_http_manid_from_vars(struct ast_variable *headers) attribute_pure
Return manager id, if exist, from request headers.
#define ast_strdup(str)
A wrapper for strdup()
static int inbuf(struct baseio *bio, FILE *fi)
utility used by inchar(), for base_encode()
Generic support for tcp/tls servers in Asterisk.
static char prefix[MAX_PREFIX]
#define ast_strlen_zero(foo)
ssize_t ast_iostream_read(struct ast_iostream *stream, void *buffer, size_t count)
Read data from an iostream.
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.
static int readmimefile(struct ast_iostream *in, FILE *fout, char *boundary, int contentlen)
#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)
void ast_config_destroy(struct ast_config *config)
Destroys a config.
A set of macros to manage forward-linked lists.
describes a server instance
#define CONFIG_STATUS_FILEUNCHANGED
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_http_body_read_status(struct ast_tcptls_session_instance *ser, int read_success)
Update the body read success status.
int astman_verify_session_writepermissions(uint32_t ident, int perm)
Verify a session's write permissions against a permission mask.
#define ast_calloc(num, len)
A wrapper for calloc()
static int unload_module(void)
Structure used to handle boolean flags.
struct ast_iostream * stream
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
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.
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.
void ast_http_request_close_on_completion(struct ast_tcptls_session_instance *ser)
Request the HTTP connection be closed after this HTTP request.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.