#include "asterisk.h"
#include <sys/stat.h>
#include <fcntl.h>
#include <gmime/gmime.h>
#include "asterisk/linkedlists.h"
#include "asterisk/http.h"
#include "asterisk/paths.h"
#include "asterisk/tcptls.h"
#include "asterisk/manager.h"
#include "asterisk/cli.h"
#include "asterisk/module.h"
#include "asterisk/ast_version.h"
Go to the source code of this file.
Data Structures | |
struct | mime_cbinfo |
Defines | |
#define | MAX_PREFIX 80 |
Functions | |
static int | __ast_http_post_load (int reload) |
static void | __reg_module (void) |
static void | __unreg_module (void) |
static struct ast_str * | 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 *vars, struct ast_variable *headers, int *status, char **title, int *contentlength) |
static int | load_module (void) |
static GMimeMessage * | parse_message (FILE *f) |
static void | post_raw (GMimePart *part, const char *post_dir, const char *fn) |
static int | process_message (GMimeMessage *message, const char *post_dir) |
static void | process_message_callback (GMimeObject *part, gpointer user_data) |
static int | reload (void) |
static int | unload_module (void) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "HTTP POST support" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } |
static struct ast_module_info * | ast_module_info = &__mod_info |
static char | prefix [MAX_PREFIX] |
Definition in file res_http_post.c.
#define MAX_PREFIX 80 |
Definition at line 50 of file res_http_post.c.
static int __ast_http_post_load | ( | int | reload | ) | [static] |
Definition at line 269 of file res_http_post.c.
References ast_calloc, ast_config_destroy(), ast_config_load2(), ast_copy_string(), ast_free, ast_http_uri_link(), ast_http_uri_unlink_all_with_key(), ast_str_create(), ast_str_set(), ast_strdup, ast_variable_browse(), CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEUNCHANGED, http_post_callback(), ast_variable::name, ast_variable::next, and ast_variable::value.
Referenced by load_module(), and reload().
00270 { 00271 struct ast_config *cfg; 00272 struct ast_variable *v; 00273 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 00274 00275 if ((cfg = ast_config_load2("http.conf", "http", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) { 00276 return 0; 00277 } 00278 00279 if (reload) { 00280 ast_http_uri_unlink_all_with_key(__FILE__); 00281 } 00282 00283 if (cfg) { 00284 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) { 00285 if (!strcasecmp(v->name, "prefix")) { 00286 ast_copy_string(prefix, v->value, sizeof(prefix)); 00287 if (prefix[strlen(prefix)] == '/') { 00288 prefix[strlen(prefix)] = '\0'; 00289 } 00290 } 00291 } 00292 00293 for (v = ast_variable_browse(cfg, "post_mappings"); v; v = v->next) { 00294 struct ast_http_uri *urih; 00295 struct ast_str *ds; 00296 00297 if (!(urih = ast_calloc(sizeof(*urih), 1))) { 00298 ast_config_destroy(cfg); 00299 return -1; 00300 } 00301 00302 if (!(ds = ast_str_create(32))) { 00303 ast_free(urih); 00304 ast_config_destroy(cfg); 00305 return -1; 00306 } 00307 00308 urih->description = ast_strdup("HTTP POST mapping"); 00309 urih->uri = ast_strdup(v->name); 00310 ast_str_set(&ds, 0, "%s", v->value); 00311 urih->data = ds; 00312 urih->has_subtree = 0; 00313 urih->supports_get = 0; 00314 urih->supports_post = 1; 00315 urih->callback = http_post_callback; 00316 urih->key = __FILE__; 00317 urih->mallocd = urih->dmallocd = 1; 00318 00319 ast_http_uri_link(urih); 00320 } 00321 00322 ast_config_destroy(cfg); 00323 } 00324 return 0; 00325 }
static void __reg_module | ( | void | ) | [static] |
Definition at line 354 of file res_http_post.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 354 of file res_http_post.c.
static struct ast_str* 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 * | vars, | |||
struct ast_variable * | headers, | |||
int * | status, | |||
char ** | title, | |||
int * | contentlength | |||
) | [static] |
Definition at line 156 of file res_http_post.c.
References ast_http_error(), ast_strdup, buf, f, and var.
Referenced by __ast_http_post_load().
00157 { 00158 struct ast_variable *var; 00159 unsigned long ident = 0; 00160 char buf[4096]; 00161 FILE *f; 00162 size_t res; 00163 int content_len = 0; 00164 struct ast_str *post_dir; 00165 GMimeMessage *message; 00166 int message_count = 0; 00167 00168 if (!urih) { 00169 return ast_http_error((*status = 400), 00170 (*title = ast_strdup("Missing URI handle")), 00171 NULL, "There was an error parsing the request"); 00172 } 00173 00174 for (var = vars; var; var = var->next) { 00175 if (strcasecmp(var->name, "mansession_id")) { 00176 continue; 00177 } 00178 00179 if (sscanf(var->value, "%30lx", &ident) != 1) { 00180 return ast_http_error((*status = 400), 00181 (*title = ast_strdup("Bad Request")), 00182 NULL, "The was an error parsing the request."); 00183 } 00184 00185 if (!astman_verify_session_writepermissions(ident, EVENT_FLAG_CONFIG)) { 00186 return ast_http_error((*status = 401), 00187 (*title = ast_strdup("Unauthorized")), 00188 NULL, "You are not authorized to make this request."); 00189 } 00190 00191 break; 00192 } 00193 00194 if (!var) { 00195 return ast_http_error((*status = 401), 00196 (*title = ast_strdup("Unauthorized")), 00197 NULL, "You are not authorized to make this request."); 00198 } 00199 00200 if (!(f = tmpfile())) { 00201 ast_log(LOG_ERROR, "Could not create temp file.\n"); 00202 return NULL; 00203 } 00204 00205 for (var = headers; var; var = var->next) { 00206 fprintf(f, "%s: %s\r\n", var->name, var->value); 00207 00208 if (!strcasecmp(var->name, "Content-Length")) { 00209 if ((sscanf(var->value, "%30u", &content_len)) != 1) { 00210 ast_log(LOG_ERROR, "Invalid Content-Length in POST request!\n"); 00211 fclose(f); 00212 00213 return NULL; 00214 } 00215 ast_debug(1, "Got a Content-Length of %d\n", content_len); 00216 } 00217 } 00218 00219 fprintf(f, "\r\n"); 00220 00221 for (res = sizeof(buf); content_len; content_len -= res) { 00222 if (content_len < res) { 00223 res = content_len; 00224 } 00225 if (fread(buf, 1, res, ser->f) != res) { 00226 ast_log(LOG_WARNING, "fread() failed: %s\n", strerror(errno)); 00227 continue; 00228 } 00229 if (fwrite(buf, 1, res, f) != res) { 00230 ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno)); 00231 continue; 00232 } 00233 } 00234 00235 if (fseek(f, SEEK_SET, 0)) { 00236 ast_log(LOG_ERROR, "Failed to seek temp file back to beginning.\n"); 00237 fclose(f); 00238 00239 return NULL; 00240 } 00241 00242 post_dir = urih->data; 00243 00244 message = parse_message(f); /* Takes ownership and will close f */ 00245 00246 if (!message) { 00247 ast_log(LOG_ERROR, "Error parsing MIME data\n"); 00248 00249 return ast_http_error((*status = 400), 00250 (*title = ast_strdup("Bad Request")), 00251 NULL, "The was an error parsing the request."); 00252 } 00253 00254 if (!(message_count = process_message(message, post_dir->str))) { 00255 ast_log(LOG_ERROR, "Invalid MIME data, found no parts!\n"); 00256 g_object_unref(message); 00257 return ast_http_error((*status = 400), 00258 (*title = ast_strdup("Bad Request")), 00259 NULL, "The was an error parsing the request."); 00260 } 00261 00262 g_object_unref(message); 00263 00264 return ast_http_error((*status = 200), 00265 (*title = ast_strdup("OK")), 00266 NULL, "File successfully uploaded."); 00267 }
static int load_module | ( | void | ) | [static] |
Definition at line 341 of file res_http_post.c.
References __ast_http_post_load(), and AST_MODULE_LOAD_SUCCESS.
00342 { 00343 g_mime_init(0); 00344 00345 __ast_http_post_load(0); 00346 00347 return AST_MODULE_LOAD_SUCCESS; 00348 }
static GMimeMessage* parse_message | ( | FILE * | f | ) | [static] |
Definition at line 88 of file res_http_post.c.
00089 { 00090 GMimeMessage *message; 00091 GMimeParser *parser; 00092 GMimeStream *stream; 00093 00094 stream = g_mime_stream_file_new(f); 00095 00096 parser = g_mime_parser_new_with_stream(stream); 00097 g_mime_parser_set_respect_content_length(parser, 1); 00098 00099 g_object_unref(stream); 00100 00101 message = g_mime_parser_construct_message(parser); 00102 00103 g_object_unref(parser); 00104 00105 return message; 00106 }
static void post_raw | ( | GMimePart * | part, | |
const char * | post_dir, | |||
const char * | fn | |||
) | [static] |
Definition at line 61 of file res_http_post.c.
References ast_debug, ast_log(), and LOG_WARNING.
Referenced by process_message_callback().
00062 { 00063 char filename[PATH_MAX]; 00064 GMimeDataWrapper *content; 00065 GMimeStream *stream; 00066 int fd; 00067 00068 snprintf(filename, sizeof(filename), "%s/%s", post_dir, fn); 00069 00070 ast_debug(1, "Posting raw data to %s\n", filename); 00071 00072 if ((fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666)) == -1) { 00073 ast_log(LOG_WARNING, "Unable to open %s for writing file from a POST!\n", filename); 00074 00075 return; 00076 } 00077 00078 stream = g_mime_stream_fs_new(fd); 00079 00080 content = g_mime_part_get_content_object(part); 00081 g_mime_data_wrapper_write_to_stream(content, stream); 00082 g_mime_stream_flush(stream); 00083 00084 g_object_unref(content); 00085 g_object_unref(stream); 00086 }
static int process_message | ( | GMimeMessage * | message, | |
const char * | post_dir | |||
) | [static] |
Definition at line 144 of file res_http_post.c.
References mime_cbinfo::count, and process_message_callback().
00145 { 00146 struct mime_cbinfo cbinfo = { 00147 .count = 0, 00148 .post_dir = post_dir, 00149 }; 00150 00151 g_mime_message_foreach_part(message, process_message_callback, &cbinfo); 00152 00153 return cbinfo.count; 00154 }
static void process_message_callback | ( | GMimeObject * | part, | |
gpointer | user_data | |||
) | [static] |
Definition at line 108 of file res_http_post.c.
References ast_debug, ast_log(), ast_strlen_zero(), mime_cbinfo::count, LOG_ERROR, LOG_WARNING, mime_cbinfo::post_dir, and post_raw().
Referenced by process_message().
00109 { 00110 struct mime_cbinfo *cbinfo = user_data; 00111 00112 cbinfo->count++; 00113 00114 /* We strip off the headers before we get here, so should only see GMIME_IS_PART */ 00115 if (GMIME_IS_MESSAGE_PART(part)) { 00116 ast_log(LOG_WARNING, "Got unexpected GMIME_IS_MESSAGE_PART\n"); 00117 return; 00118 } else if (GMIME_IS_MESSAGE_PARTIAL(part)) { 00119 ast_log(LOG_WARNING, "Got unexpected GMIME_IS_MESSAGE_PARTIAL\n"); 00120 return; 00121 } else if (GMIME_IS_MULTIPART(part)) { 00122 GList *l; 00123 00124 ast_log(LOG_WARNING, "Got unexpected GMIME_IS_MULTIPART, trying to process subparts\n"); 00125 l = GMIME_MULTIPART(part)->subparts; 00126 while (l) { 00127 process_message_callback(l->data, cbinfo); 00128 l = l->next; 00129 } 00130 } else if (GMIME_IS_PART(part)) { 00131 const char *filename; 00132 00133 if (ast_strlen_zero(filename = g_mime_part_get_filename(GMIME_PART(part)))) { 00134 ast_debug(1, "Skipping part with no filename\n"); 00135 return; 00136 } 00137 00138 post_raw(GMIME_PART(part), cbinfo->post_dir, filename); 00139 } else { 00140 ast_log(LOG_ERROR, "Encountered unknown MIME part. This should never happen!\n"); 00141 } 00142 }
static int reload | ( | void | ) | [static] |
Definition at line 334 of file res_http_post.c.
References __ast_http_post_load(), and AST_MODULE_LOAD_SUCCESS.
00335 { 00336 __ast_http_post_load(1); 00337 00338 return AST_MODULE_LOAD_SUCCESS; 00339 }
static int unload_module | ( | void | ) | [static] |
Definition at line 327 of file res_http_post.c.
References ast_http_uri_unlink_all_with_key().
00328 { 00329 ast_http_uri_unlink_all_with_key(__FILE__); 00330 00331 return 0; 00332 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "HTTP POST support" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 354 of file res_http_post.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 354 of file res_http_post.c.
char prefix[MAX_PREFIX] [static] |
Definition at line 59 of file res_http_post.c.