void uwsgi_sqlite3_config(char *file, char *magic_table[]) { sqlite3 *db; char *err = NULL; char *query = "SELECT * FROM uwsgi"; char *colon = uwsgi_get_last_char(file, ':'); if (colon) { colon[0] = 0; if (colon[1] != 0) { query = colon + 1; } } uwsgi_log("[uWSGI] getting sqlite3 configuration from %s\n", file); #ifdef sqlite3_open_v2 if (sqlite3_open_v2(file, &db, SQLITE_OPEN_READONLY, NULL)) { #else if (sqlite3_open(file, &db)) { #endif uwsgi_log("unable to open sqlite3 db: %s\n", sqlite3_errmsg(db)); sqlite3_close(db); exit(1); } if (sqlite3_exec(db, query, uwsgi_sqlite3_config_callback, (void *) magic_table, &err)) { uwsgi_log("sqlite3 error: %s\n", err); sqlite3_close(db); exit(1); } sqlite3_close(db); }
static int uwsgi_webdav_add_props(struct wsgi_request *wsgi_req, xmlNode *req_prop, xmlNode * multistatus, xmlNsPtr dav_ns, char *uri, char *filename, int with_values) { struct stat st; if (stat(filename, &st)) { uwsgi_error("uwsgi_webdav_add_props()/stat()"); return -1; } int is_collection = 0; xmlNode *response = xmlNewChild(multistatus, dav_ns, BAD_CAST "response", NULL); uint16_t uri_len = strlen(uri) ; char *encoded_uri = uwsgi_malloc( (uri_len * 3) + 1); http_url_encode(uri, &uri_len, encoded_uri); encoded_uri[uri_len] = 0; xmlNewChild(response, dav_ns, BAD_CAST "href", BAD_CAST encoded_uri); free(encoded_uri); xmlNode *r_propstat = xmlNewChild(response, dav_ns, BAD_CAST "propstat", NULL); char *r_status = uwsgi_concat2n(wsgi_req->protocol, wsgi_req->protocol_len, " 200 OK", 7); xmlNewChild(r_propstat, dav_ns, BAD_CAST "status", BAD_CAST r_status); free(r_status); xmlNode *r_prop = xmlNewChild(r_propstat, dav_ns, BAD_CAST "prop", NULL); if (with_values) { if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "displayname")) { char *base_uri = uwsgi_get_last_char(uri, '/'); if (base_uri) { xmlNewChild(r_prop, dav_ns, BAD_CAST "displayname", BAD_CAST base_uri+1); } else { xmlNewChild(r_prop, dav_ns, BAD_CAST "displayname", BAD_CAST uri); } } if (S_ISDIR(st.st_mode)) is_collection = 1; xmlNode *r_type = NULL; if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "resourcetype")) { r_type = xmlNewChild(r_prop, dav_ns, BAD_CAST "resourcetype", NULL); if (is_collection) { xmlNewChild(r_type, dav_ns, BAD_CAST "collection", NULL); is_collection = 1; } } if (!is_collection) { if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "getcontentlength")) { char *r_contentlength = uwsgi_num2str(st.st_size); xmlNewChild(r_prop, dav_ns, BAD_CAST "getcontentlength", BAD_CAST r_contentlength); free(r_contentlength); } if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "getcontenttype")) { size_t mime_type_len = 0; char *mime_type = uwsgi_get_mime_type(filename, strlen(filename), &mime_type_len); if (mime_type) { char *r_ctype = uwsgi_concat2n(mime_type, mime_type_len, "", 0); xmlNewTextChild(r_prop, dav_ns, BAD_CAST "getcontenttype", BAD_CAST r_ctype); free(r_ctype); } } } if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "creationdate")) { // there is no creation date on UNIX/POSIX, ctime is the nearest thing... char *cdate = uwsgi_webdav_new_date(st.st_ctime); if (cdate) { xmlNewTextChild(r_prop, dav_ns, BAD_CAST "creationdate", BAD_CAST cdate); free(cdate); } } if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "getlastmodified")) { char *mdate = uwsgi_webdav_new_date(st.st_mtime); if (mdate) { xmlNewTextChild(r_prop, dav_ns, BAD_CAST "getlastmodified", BAD_CAST mdate); free(mdate); } } if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "getetag")) { char *etag = uwsgi_num2str(st.st_mtime); xmlNewTextChild(r_prop, dav_ns, BAD_CAST "getetag", BAD_CAST etag); free(etag); } if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "executable")) { xmlNewChild(r_prop, dav_ns, BAD_CAST "executable", NULL); } if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "owner")) { xmlNewTextChild(r_prop, dav_ns, BAD_CAST "owner", NULL); } if (wsgi_req->remote_user_len > 0) { if (udav.principal_base) { if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "current-user-principal")) { char *current_user_principal = uwsgi_concat2n(udav.principal_base, strlen(udav.principal_base), wsgi_req->remote_user, wsgi_req->remote_user_len); xmlNode *cup = xmlNewChild(r_prop, dav_ns, BAD_CAST "current-user-principal", NULL); xmlNewTextChild(cup, dav_ns, BAD_CAST "href", BAD_CAST current_user_principal); if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "resourcetype")) { if (!strcmp(current_user_principal, uri)) { xmlNewChild(r_type, dav_ns, BAD_CAST "principal", NULL); } } free(current_user_principal); } } if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "current-user-privilege-set")) { xmlNode *cups = xmlNewChild(r_prop, dav_ns, BAD_CAST "current-user-privilege-set", NULL); xmlNode *privilege = xmlNewChild(cups, dav_ns, BAD_CAST "privilege", NULL); xmlNewChild(privilege, dav_ns, BAD_CAST "all", NULL); xmlNewChild(privilege, dav_ns, BAD_CAST "read", NULL); xmlNewChild(privilege, dav_ns, BAD_CAST "write", NULL); xmlNewChild(privilege, dav_ns, BAD_CAST "write-content", NULL); xmlNewChild(privilege, dav_ns, BAD_CAST "write-properties", NULL); } } if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "supported-report-set")) { xmlNode *report_set = xmlNewChild(r_prop, dav_ns, BAD_CAST "supported-report-set", NULL); xmlNode *supported_report = xmlNewChild(report_set, dav_ns, BAD_CAST "supported-report", NULL); xmlNewChild(supported_report, dav_ns, BAD_CAST "report", BAD_CAST "principal-property-search"); supported_report = xmlNewChild(report_set, dav_ns, BAD_CAST "supported-report", NULL); xmlNewChild(supported_report, dav_ns, BAD_CAST "report", BAD_CAST "sync-collection"); supported_report = xmlNewChild(report_set, dav_ns, BAD_CAST "supported-report", NULL); xmlNewChild(supported_report, dav_ns, BAD_CAST "report", BAD_CAST "expand-property"); supported_report = xmlNewChild(report_set, dav_ns, BAD_CAST "supported-report", NULL); xmlNewChild(supported_report, dav_ns, BAD_CAST "report", BAD_CAST "principal-search-property-set"); } uwsgi_webdav_foreach_prop(udav.add_prop, req_prop, r_prop, 0, NULL ); uwsgi_webdav_foreach_prop(udav.add_prop_href, req_prop, r_prop, 1, NULL); uwsgi_webdav_foreach_prop(udav.add_prop_comp,req_prop, r_prop, 2 , NULL); uwsgi_webdav_foreach_prop(udav.add_rtype_prop,req_prop, r_type, 0, "resourcetype"); if (is_collection) { uwsgi_webdav_foreach_prop(udav.add_rtype_collection_prop,req_prop, r_type, 0, "resourcetype"); uwsgi_webdav_foreach_prop(udav.add_collection_prop,req_prop, r_prop, 0, NULL); uwsgi_webdav_foreach_prop(udav.add_collection_prop_href,req_prop, r_prop, 1, NULL); uwsgi_webdav_foreach_prop(udav.add_collection_prop_comp,req_prop, r_prop, 2, NULL); } else { uwsgi_webdav_foreach_prop(udav.add_rtype_object_prop,req_prop, r_type, 0, "resourcetype"); uwsgi_webdav_foreach_prop(udav.add_object_prop,req_prop, r_prop, 0, NULL); uwsgi_webdav_foreach_prop(udav.add_object_prop_href,req_prop, r_prop, 1, NULL); uwsgi_webdav_foreach_prop(udav.add_object_prop_comp,req_prop, r_prop, 2, NULL); } } else { xmlNewChild(r_prop, dav_ns, BAD_CAST "displayname", NULL); xmlNewChild(r_prop, dav_ns, BAD_CAST "resourcetype", NULL); if (!S_ISDIR(st.st_mode)) { xmlNewChild(r_prop, dav_ns, BAD_CAST "getcontentlength", NULL); xmlNewChild(r_prop, dav_ns, BAD_CAST "getcontenttype", NULL); } xmlNewChild(r_prop, dav_ns, BAD_CAST "creationdate", NULL); xmlNewChild(r_prop, dav_ns, BAD_CAST "getlastmodified", NULL); xmlNewChild(r_prop, dav_ns, BAD_CAST "supported-report-set", NULL); if (wsgi_req->remote_user_len > 0) { xmlNewChild(r_prop, dav_ns, BAD_CAST "current-user-privilege-set", NULL); if (udav.principal_base) { xmlNewChild(r_prop, dav_ns, BAD_CAST "current-user-principal", NULL); } } } #if defined(__linux__) || defined(__APPLE__) // get xattr for user.uwsgi.webdav. #if defined(__linux__) ssize_t rlen = listxattr(filename, NULL, 0); #elif defined(__APPLE__) ssize_t rlen = listxattr(filename, NULL, 0, 0); #endif // do not return -1 as the previous xml is valid !!! if (rlen <= 0) return 0; // use calloc to avoid races char *xattrs = uwsgi_calloc(rlen); #if defined(__linux__) if (listxattr(filename, xattrs, rlen) <= 0) { #elif defined(__APPLE__) if (listxattr(filename, xattrs, rlen, 0) <= 0) { #endif free(xattrs); return 0; } // parse the name list ssize_t i; char *key = NULL; for(i=0;i<rlen;i++) { // check for wrong condition if (xattrs[i] == 0 && key == NULL) break; if (key && xattrs[i] == 0) { if (!uwsgi_starts_with(key, strlen(key), "user.uwsgi.webdav.", 18)) { if (uwsgi_string_list_has_item(udav.skip_prop, key + 18, strlen(key + 18))) continue; xmlNsPtr xattr_ns = NULL; // does it has a namespace ? char *separator = strchr(key + 18, '|'); char *xattr_key = key + 18; if (separator) { xattr_key = separator + 1; *separator = 0; if (!uwsgi_webdav_prop_requested(req_prop, key + 18, xattr_key)) continue; } else { if (!uwsgi_webdav_prop_requested(req_prop, NULL, xattr_key)) continue; } xmlNode *xattr_item = NULL; if (with_values) { #if defined(__linux__) ssize_t rlen2 = getxattr(filename, key, NULL, 0); #elif defined(__APPLE__) ssize_t rlen2 = getxattr(filename, key, NULL, 0, 0, 0); #endif if (rlen > 0) { // leave space for final 0 char *xvalue = uwsgi_calloc(rlen2 + 1); #if defined(__linux__) if (getxattr(filename, key, xvalue, rlen2) > 0) { #elif defined(__APPLE__) if (getxattr(filename, key, xvalue, rlen2, 0 ,0) > 0) { #endif xattr_item = xmlNewTextChild(r_prop, NULL, BAD_CAST xattr_key, BAD_CAST xvalue); } free(xvalue); } else if (rlen == 0) { xattr_item = xmlNewTextChild(r_prop, NULL, BAD_CAST xattr_key, NULL); } } else { xattr_item = xmlNewTextChild(r_prop, NULL, BAD_CAST xattr_key, NULL); } if (separator && xattr_item) { xattr_ns = xmlNewNs(xattr_item, BAD_CAST (key + 18), NULL); *separator = '|'; xmlSetNs(xattr_item, xattr_ns); } } key = NULL; } else if (key == NULL) { key = &xattrs[i]; } } free(xattrs); #endif return 0; } static size_t uwsgi_webdav_expand_path(struct wsgi_request *wsgi_req, char *item, uint16_t item_len, char *filename) { struct uwsgi_app *ua = &uwsgi_apps[wsgi_req->app_id]; char *docroot = ua->interpreter; size_t docroot_len = strlen(docroot); // merge docroot with path_info char *tmp_filename = uwsgi_concat3n(docroot, docroot_len, "/", 1, item, item_len); // try expanding the path if (!realpath(tmp_filename, filename)) { free(tmp_filename); return 0; } free(tmp_filename); return strlen(filename); } static size_t uwsgi_webdav_expand_fake_path(struct wsgi_request *wsgi_req, char *item, uint16_t item_len, char *filename) { char *last_slash = uwsgi_get_last_charn(item, item_len, '/'); if (!last_slash) return 0; size_t filename_len = uwsgi_webdav_expand_path(wsgi_req, item, last_slash - item, filename); if (!filename_len) return 0; // check for overflow if (filename_len + (item_len - (last_slash - item)) >= PATH_MAX) return 0; memcpy(filename + filename_len, last_slash, (item_len - (last_slash - item))); filename_len += (item_len - (last_slash - item)); filename[(int)filename_len] = 0; return filename_len; } static xmlDoc *uwsgi_webdav_manage_prop(struct wsgi_request *wsgi_req, xmlNode *req_prop, char *filename, size_t filename_len, int with_values) { // default 1 depth int depth = 1; uint16_t http_depth_len = 0; char *http_depth = uwsgi_get_var(wsgi_req, "HTTP_DEPTH", 10, &http_depth_len); if (http_depth) { depth = uwsgi_str_num(http_depth, http_depth_len); } xmlDoc *rdoc = xmlNewDoc(BAD_CAST "1.0"); xmlNode *multistatus = xmlNewNode(NULL, BAD_CAST "multistatus"); xmlDocSetRootElement(rdoc, multistatus); xmlNsPtr dav_ns = xmlNewNs(multistatus, BAD_CAST "DAV:", BAD_CAST "D"); xmlSetNs(multistatus, dav_ns); if (depth == 0) { char *uri = uwsgi_concat2n(wsgi_req->path_info, wsgi_req->path_info_len, "", 0); uwsgi_webdav_add_props(wsgi_req, req_prop, multistatus, dav_ns, uri, filename, with_values); free(uri); } else { DIR *collection = opendir(filename); struct dirent de; for (;;) { struct dirent *de_r = NULL; if (readdir_r(collection, &de, &de_r)) { uwsgi_error("uwsgi_wevdav_manage_propfind()/readdir_r()"); break; } if (de_r == NULL) { break; } char *uri = NULL; char *direntry = NULL; if (!strcmp(de.d_name, "..")) { // skip .. continue; } else if (!strcmp(de.d_name, ".")) { uri = uwsgi_concat2n(wsgi_req->path_info, wsgi_req->path_info_len, "", 0); direntry = uwsgi_concat2n(filename, filename_len, "", 0); } else if (wsgi_req->path_info[wsgi_req->path_info_len - 1] == '/') { uri = uwsgi_concat2n(wsgi_req->path_info, wsgi_req->path_info_len, de.d_name, strlen(de.d_name)); direntry = uwsgi_concat3n(filename, filename_len, "/", 1, de.d_name, strlen(de.d_name)); } else { uri = uwsgi_concat3n(wsgi_req->path_info, wsgi_req->path_info_len, "/", 1, de.d_name, strlen(de.d_name)); direntry = uwsgi_concat3n(filename, filename_len, "/", 1, de.d_name, strlen(de.d_name)); } uwsgi_webdav_add_props(wsgi_req, req_prop, multistatus, dav_ns, uri, direntry, with_values); free(uri); free(direntry); } closedir(collection); } return rdoc; }
void uwsgi_yaml_config(char *file, char *magic_table[]) { int len = 0; char *yaml; int in_uwsgi_section = 0; char *key = NULL; char *val = NULL; char *section_asked = "uwsgi"; char *colon; if (uwsgi_check_scheme(file)) { colon = uwsgi_get_last_char(file, '/'); colon = uwsgi_get_last_char(colon, ':'); } else { colon = uwsgi_get_last_char(file, ':'); } if (colon) { colon[0] = 0; if (colon[1] != 0) { section_asked = colon + 1; } } uwsgi_log("[uWSGI] getting YAML configuration from %s\n", file); yaml = uwsgi_open_and_read(file, &len, 1, magic_table); #ifdef UWSGI_LIBYAML yaml_parser_t parser; yaml_token_t token; int status = 0; int parsing = 1; if (!yaml_parser_initialize(&parser)) { uwsgi_log("unable to initialize YAML parser (libyaml)\n"); exit(1); } yaml_parser_set_input_string(&parser, (const unsigned char *) yaml, (size_t) len - 1); while (parsing) { if (!yaml_parser_scan(&parser, &token)) { uwsgi_log("error parsing YAML file: %s (%c)\n", parser.problem, yaml[parser.problem_offset]); exit(1); } switch (token.type) { case YAML_STREAM_END_TOKEN: parsing = 0; break; case YAML_KEY_TOKEN: status = 1; break; case YAML_VALUE_TOKEN: status = 2; break; case YAML_FLOW_SEQUENCE_START_TOKEN: case YAML_BLOCK_SEQUENCE_START_TOKEN: status = 3; break; case YAML_BLOCK_MAPPING_START_TOKEN: if (!in_uwsgi_section) { if (key) { if (!strcmp(section_asked, key)) { in_uwsgi_section = 1; } } } break; case YAML_BLOCK_END_TOKEN: if (in_uwsgi_section) { parsing = 0; break; } break; case YAML_SCALAR_TOKEN: case YAML_FLOW_ENTRY_TOKEN: case YAML_BLOCK_ENTRY_TOKEN: if (status == 1) { key = (char *) token.data.scalar.value; } else if (status == 2) { val = (char *) token.data.scalar.value; if (key && val && in_uwsgi_section) { add_exported_option(key, val, 0); } status = 0; } else if (status == 3) { val = (char *) token.data.scalar.value; if (key && val && in_uwsgi_section) { add_exported_option(key, val, 0); } } else { uwsgi_log("unsupported YAML token in %s block\n", section_asked); parsing = 0; break; } break; default: status = 0; } } #else int depth; int current_depth = 0; int lines = 1; char *yaml_line; char *section = ""; while (len) { yaml_line = yaml_get_line(yaml, len); if (yaml_line == NULL) { break; } lines++; // skip empty line if (yaml[0] == 0) goto next; depth = yaml_get_depth(yaml); if (depth <= current_depth) { current_depth = depth; // end the parsing cycle if (in_uwsgi_section) return; } else if (depth > current_depth && !in_uwsgi_section) { goto next; } key = yaml_lstrip(yaml); // skip empty line if (key[0] == 0) goto next; // skip list and {} defined dict if (key[0] == '-' || key[0] == '[' || key[0] == '{') { if (in_uwsgi_section) return; goto next; } if (!in_uwsgi_section) { section = strchr(key, ':'); if (!section) goto next; section[0] = 0; if (!strcmp(key, section_asked)) { in_uwsgi_section = 1; } } else { // get dict value val = strstr(key, ": "); if (!val) { val = strstr(key, ":\t"); } if (!val) return; // get the right key val[0] = 0; // yeah overengeneering.... yaml_rstrip(key); val = yaml_lstrip(val + 2); yaml_rstrip(val); //uwsgi_log("YAML: %s = %s\n", key, val); add_exported_option((char *) key, val, 0); } next: len -= (yaml_line - yaml); yaml += (yaml_line - yaml); } #endif }
void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) { void *plugin_handle = NULL; char *plugin_abs_path = NULL; char *plugin_filename = NULL; int need_free = 0; char *plugin_name = uwsgi_strip(uwsgi_str(plugin)); char *plugin_symbol_name_start = plugin_name; struct uwsgi_plugin *up; char linkpath_buf[1024], linkpath[1024]; int linkpath_size; char *colon = strchr(plugin_name, ':'); if (colon) { colon[0] = 0; modifier = atoi(plugin_name); plugin_name = colon + 1; colon[0] = ':'; } if (!uwsgi_endswith(plugin_name, "_plugin.so")) { plugin_name = uwsgi_concat2(plugin_name, "_plugin.so"); need_free = 1; } plugin_symbol_name_start = plugin_name; // step 1: check for absolute plugin (stop if it fails) if (strchr(plugin_name, '/')) { #ifdef UWSGI_ELF uwsgi_plugin_parse_section(plugin_name); #endif plugin_handle = dlopen(plugin_name, RTLD_NOW | RTLD_GLOBAL); if (!plugin_handle) { if (!has_option) uwsgi_log("%s\n", dlerror()); goto end; } plugin_symbol_name_start = uwsgi_get_last_char(plugin_name, '/'); plugin_symbol_name_start++; plugin_abs_path = plugin_name; goto success; } // step dir, check for user-supplied plugins directory struct uwsgi_string_list *pdir = uwsgi.plugins_dir; while (pdir) { plugin_filename = uwsgi_concat3(pdir->value, "/", plugin_name); #ifdef UWSGI_ELF uwsgi_plugin_parse_section(plugin_filename); #endif plugin_handle = dlopen(plugin_filename, RTLD_NOW | RTLD_GLOBAL); if (plugin_handle) { plugin_abs_path = plugin_filename; //free(plugin_filename); goto success; } free(plugin_filename); plugin_filename = NULL; pdir = pdir->next; } // last step: search in compile-time plugin_dir if (!plugin_handle) { plugin_filename = uwsgi_concat3(UWSGI_PLUGIN_DIR, "/", plugin_name); #ifdef UWSGI_ELF uwsgi_plugin_parse_section(plugin_filename); #endif plugin_handle = dlopen(plugin_filename, RTLD_NOW | RTLD_GLOBAL); plugin_abs_path = plugin_filename; //free(plugin_filename); } success: if (!plugin_handle) { if (!has_option) uwsgi_log("!!! UNABLE to load uWSGI plugin: %s !!!\n", dlerror()); } else { char *plugin_entry_symbol = uwsgi_concat2n(plugin_symbol_name_start, strlen(plugin_symbol_name_start) - 3, "", 0); up = dlsym(plugin_handle, plugin_entry_symbol); if (!up) { // is it a link ? memset(linkpath_buf, 0, 1024); memset(linkpath, 0, 1024); if ((linkpath_size = readlink(plugin_abs_path, linkpath_buf, 1023)) > 0) { do { linkpath_buf[linkpath_size] = '\0'; strncpy(linkpath, linkpath_buf, linkpath_size + 1); } while ((linkpath_size = readlink(linkpath, linkpath_buf, 1023)) > 0); #ifdef UWSGI_DEBUG uwsgi_log("%s\n", linkpath); #endif free(plugin_entry_symbol); char *slash = uwsgi_get_last_char(linkpath, '/'); if (!slash) { slash = linkpath; } else { slash++; } plugin_entry_symbol = uwsgi_concat2n(slash, strlen(slash) - 3, "", 0); up = dlsym(plugin_handle, plugin_entry_symbol); } } if (up) { if (!up->name) { uwsgi_log("the loaded plugin (%s) has no .name attribute\n", plugin_name); if (dlclose(plugin_handle)) { uwsgi_error("dlclose()"); } if (need_free) free(plugin_name); if (plugin_filename) free(plugin_filename); free(plugin_entry_symbol); return NULL; } if (plugin_already_loaded(up->name)) { if (dlclose(plugin_handle)) { uwsgi_error("dlclose()"); } if (need_free) free(plugin_name); if (plugin_filename) free(plugin_filename); free(plugin_entry_symbol); return NULL; } if (has_option) { struct uwsgi_option *op = up->options; int found = 0; while (op && op->name) { if (!strcmp(has_option, op->name)) { found = 1; break; } op++; } if (!found) { if (dlclose(plugin_handle)) { uwsgi_error("dlclose()"); } if (need_free) free(plugin_name); if (plugin_filename) free(plugin_filename); free(plugin_entry_symbol); return NULL; } } if (modifier != -1) { fill_plugin_table(modifier, up); up->modifier1 = modifier; } else { fill_plugin_table(up->modifier1, up); } if (need_free) free(plugin_name); if (plugin_filename) free(plugin_filename); free(plugin_entry_symbol); if (up->on_load) up->on_load(); return plugin_handle; } if (!has_option) uwsgi_log("%s\n", dlerror()); } end: if (need_free) free(plugin_name); if (plugin_filename) free(plugin_filename); return NULL; }
void uwsgi_ini_config(char *file, char *magic_table[]) { size_t len = 0; char *ini; char *ini_line; char *section = ""; char *key; char *val; int lines = 1; char *section_asked = "uwsgi"; char *colon; if (uwsgi_check_scheme(file)) { colon = uwsgi_get_last_char(file, '/'); colon = uwsgi_get_last_char(colon, ':'); } else { colon = uwsgi_get_last_char(file, ':'); } if (colon) { colon[0] = 0; if (colon[1] != 0) { section_asked = colon + 1; } } if (file[0] != 0) { uwsgi_log_initial("[uWSGI] getting INI configuration from %s\n", file); } ini = uwsgi_open_and_read(file, &len, 1, magic_table); while (len) { ini_line = ini_get_line(ini, len); if (ini_line == NULL) { break; } lines++; // skip empty line key = ini_lstrip(ini); ini_rstrip(key); if (key[0] != 0) { if (key[0] == '[') { section = key + 1; section[strlen(section) - 1] = 0; } else if (key[0] == ';' || key[0] == '#') { // this is a comment } else { // val is always valid, but (obviously) can be ignored val = ini_get_key(key); if (!strcmp(section, section_asked)) { ini_rstrip(key); val = ini_lstrip(val); ini_rstrip(val); add_exported_option((char *) key, val, 0); } } } len -= (ini_line - ini); ini += (ini_line - ini); } if (colon) { colon[0] = ':'; } }
static char *emperor_check_on_demand_socket(char *filename) { size_t len = 0; if (uwsgi.emperor_on_demand_extension) { char *tmp = uwsgi_concat2(filename, uwsgi.emperor_on_demand_extension); int fd = open(tmp, O_RDONLY); free(tmp); if (fd < 0) return NULL; char *ret = uwsgi_read_fd(fd, &len, 1); close(fd); // change the first non prinabel character to 0 size_t i; for(i=0;i<len;i++) { if (ret[i] < 32) { ret[i] = 0; break; } } if (ret[0] == 0) { free(ret); return NULL; } return ret; } else if (uwsgi.emperor_on_demand_directory) { // we need to build the socket path automagically char *start_of_vassal_name = uwsgi_get_last_char(filename, '/'); if (!start_of_vassal_name) { start_of_vassal_name = filename; } else { start_of_vassal_name++; } char *last_dot = uwsgi_get_last_char(filename, '.'); if (!last_dot) return NULL; return uwsgi_concat4n(uwsgi.emperor_on_demand_directory, strlen(uwsgi.emperor_on_demand_directory), "/", 1, start_of_vassal_name, last_dot - start_of_vassal_name, ".socket", 7); } else if (uwsgi.emperor_on_demand_exec) { int cpipe[2]; if (pipe(cpipe)) { uwsgi_error("emperor_check_on_demand_socket()pipe()"); return NULL; } char *cmd = uwsgi_concat4(uwsgi.emperor_on_demand_exec, " \"", filename, "\""); int r = uwsgi_run_command(cmd, NULL, cpipe[1]); free(cmd); if (r < 0) { close(cpipe[0]); close(cpipe[1]); return NULL; } char *ret = uwsgi_read_fd(cpipe[0], &len, 1); close(cpipe[0]); close(cpipe[1]); // change the first non prinabel character to 0 size_t i; for(i=0;i<len;i++) { if (ret[i] < 32) { ret[i] = 0; break; } } if (ret[0] == 0) { free(ret); return NULL; } return ret; } return NULL; }
/* extremely complex function for reading resources (files, url...) need a lot of refactoring... */ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_table[]) { int fd; struct stat sb; char *buffer = NULL; char byte; ssize_t len; char *uri, *colon; char *domain; char *ip; int body = 0; char *magic_buf; // stdin ? if (!strcmp(url, "-")) { buffer = uwsgi_read_fd(0, size, add_zero); } // fd ? else if (!strncmp("fd://", url, 5)) { fd = atoi(url + 5); buffer = uwsgi_read_fd(fd, size, add_zero); } // exec ? else if (!strncmp("exec://", url, 5)) { int cpipe[2]; if (pipe(cpipe)) { uwsgi_error("pipe()"); exit(1); } uwsgi_run_command(url + 7, NULL, cpipe[1]); buffer = uwsgi_read_fd(cpipe[0], size, add_zero); close(cpipe[0]); close(cpipe[1]); } // http url ? else if (!strncmp("http://", url, 7)) { domain = url + 7; uri = strchr(domain, '/'); if (!uri) { uwsgi_log("invalid http url\n"); exit(1); } uri[0] = 0; uwsgi_log("domain: %s\n", domain); colon = uwsgi_get_last_char(domain, ':'); if (colon) { colon[0] = 0; } ip = uwsgi_resolve_ip(domain); if (!ip) { uwsgi_log("unable to resolve address %s\n", domain); exit(1); } if (colon) { colon[0] = ':'; ip = uwsgi_concat2(ip, colon); } else { ip = uwsgi_concat2(ip, ":80"); } fd = uwsgi_connect(ip, 0, 0); if (fd < 0) { exit(1); } free(ip); uri[0] = '/'; len = write(fd, "GET ", 4); len = write(fd, uri, strlen(uri)); len = write(fd, " HTTP/1.0\r\n", 11); len = write(fd, "Host: ", 6); uri[0] = 0; len = write(fd, domain, strlen(domain)); uri[0] = '/'; len = write(fd, "\r\nUser-Agent: uWSGI on ", 23); len = write(fd, uwsgi.hostname, uwsgi.hostname_len); len = write(fd, "\r\n\r\n", 4); int http_status_code_ptr = 0; while (read(fd, &byte, 1) == 1) { if (byte == '\r' && body == 0) { body = 1; } else if (byte == '\n' && body == 1) { body = 2; } else if (byte == '\r' && body == 2) { body = 3; } else if (byte == '\n' && body == 3) { body = 4; } else if (body == 4) { *size = *size + 1; char *tmp = realloc(buffer, *size); if (!tmp) { uwsgi_error("uwsgi_open_and_read()/realloc()"); exit(1); } buffer = tmp; buffer[*size - 1] = byte; } else { body = 0; http_status_code_ptr++; if (http_status_code_ptr == 10) { if (byte != '2') { uwsgi_log("Not usable HTTP response: %cxx\n", byte); if (uwsgi.has_emperor) { exit(UWSGI_EXILE_CODE); } else { exit(1); } } } } } close(fd); if (add_zero) { *size = *size + 1; char *tmp = realloc(buffer, *size); if (!tmp) { uwsgi_error("uwsgi_open_and_read()/realloc()"); exit(1); } buffer = tmp; buffer[*size - 1] = 0; } } else if (!strncmp("emperor://", url, 10)) { if (uwsgi.emperor_fd_config < 0) { uwsgi_log("this is not a vassal instance\n"); exit(1); } ssize_t rlen; *size = 0; struct uwsgi_header uh; size_t remains = 4; char *ptr = (char *) &uh; while(remains) { int ret = uwsgi_waitfd(uwsgi.emperor_fd_config, 5); if (ret <= 0) { uwsgi_log("[uwsgi-vassal] error waiting for config header %s !!!\n", url); exit(1); } rlen = read(uwsgi.emperor_fd_config, ptr, remains); if (rlen <= 0) { uwsgi_log("[uwsgi-vassal] error reading config header from !!!\n", url); exit(1); } ptr+=rlen; remains-=rlen; } remains = uh.pktsize; if (!remains) { uwsgi_log("[uwsgi-vassal] invalid config from %s\n", url); exit(1); } buffer = uwsgi_calloc(remains + add_zero); ptr = buffer; while (remains) { int ret = uwsgi_waitfd(uwsgi.emperor_fd_config, 5); if (ret <= 0) { uwsgi_log("[uwsgi-vassal] error waiting for config %s !!!\n", url); exit(1); } rlen = read(uwsgi.emperor_fd_config, ptr, remains); if (rlen <= 0) { uwsgi_log("[uwsgi-vassal] error reading config from !!!\n", url); exit(1); } ptr+=rlen; remains-=rlen; } *size = uh.pktsize + add_zero; } #ifdef UWSGI_EMBED_CONFIG else if (url[0] == 0) { *size = &UWSGI_EMBED_CONFIG_END - &UWSGI_EMBED_CONFIG; if (add_zero) { *size += 1; } buffer = uwsgi_malloc(*size); memset(buffer, 0, *size); memcpy(buffer, &UWSGI_EMBED_CONFIG, &UWSGI_EMBED_CONFIG_END - &UWSGI_EMBED_CONFIG); } #endif else if (!strncmp("data://", url, 7)) { fd = open(uwsgi.binary_path, O_RDONLY); if (fd < 0) { uwsgi_error_open(uwsgi.binary_path); exit(1); } int slot = atoi(url + 7); if (slot < 0) { uwsgi_log("invalid binary data slot requested\n"); exit(1); } uwsgi_log("requesting binary data slot %d\n", slot); off_t fo = lseek(fd, 0, SEEK_END); if (fo < 0) { uwsgi_error("lseek()"); uwsgi_log("invalid binary data slot requested\n"); exit(1); } int i = 0; uint64_t datasize = 0; for (i = 0; i <= slot; i++) { fo = lseek(fd, -9, SEEK_CUR); if (fo < 0) { uwsgi_error("lseek()"); uwsgi_log("invalid binary data slot requested\n"); exit(1); } ssize_t len = read(fd, &datasize, 8); if (len != 8) { uwsgi_error("read()"); uwsgi_log("invalid binary data slot requested\n"); exit(1); } if (datasize == 0) { uwsgi_log("0 size binary data !!!\n"); exit(1); } fo = lseek(fd, -(datasize + 9), SEEK_CUR); if (fo < 0) { uwsgi_error("lseek()"); uwsgi_log("invalid binary data slot requested\n"); exit(1); } if (i == slot) { *size = datasize; if (add_zero) { *size += 1; } buffer = uwsgi_malloc(*size); memset(buffer, 0, *size); len = read(fd, buffer, datasize); if (len != (ssize_t) datasize) { uwsgi_error("read()"); uwsgi_log("invalid binary data slot requested\n"); exit(1); } } } } else if (!strncmp("sym://", url, 6)) { char *symbol = uwsgi_concat3("_binary_", url + 6, "_start"); void *sym_start_ptr = dlsym(RTLD_DEFAULT, symbol); if (!sym_start_ptr) { uwsgi_log("unable to find symbol %s\n", symbol); exit(1); } free(symbol); symbol = uwsgi_concat3("_binary_", url + 6, "_end"); void *sym_end_ptr = dlsym(RTLD_DEFAULT, symbol); if (!sym_end_ptr) { uwsgi_log("unable to find symbol %s\n", symbol); exit(1); } free(symbol); *size = sym_end_ptr - sym_start_ptr; if (add_zero) { *size += 1; } buffer = uwsgi_malloc(*size); memset(buffer, 0, *size); memcpy(buffer, sym_start_ptr, sym_end_ptr - sym_start_ptr); } #ifdef UWSGI_ELF else if (!strncmp("section://", url, 10)) { size_t s_len = 0; buffer = uwsgi_elf_section(uwsgi.binary_path, url + 10, &s_len); if (!buffer) { uwsgi_log("unable to find section %s in %s\n", url + 10, uwsgi.binary_path); exit(1); } *size = s_len; if (add_zero) *size += 1; } #endif // fallback to file else { fd = open(url, O_RDONLY); if (fd < 0) { uwsgi_error_open(url); exit(1); } if (fstat(fd, &sb)) { uwsgi_error("fstat()"); exit(1); } if (S_ISFIFO(sb.st_mode)) { buffer = uwsgi_read_fd(fd, size, add_zero); close(fd); goto end; } buffer = uwsgi_malloc(sb.st_size + add_zero); len = read(fd, buffer, sb.st_size); if (len != sb.st_size) { uwsgi_error("read()"); exit(1); } close(fd); *size = sb.st_size + add_zero; if (add_zero) buffer[sb.st_size] = 0; } end: if (magic_table) { magic_buf = magic_sub(buffer, *size, size, magic_table); free(buffer); return magic_buf; } return buffer; }
void uwsgi_json_config(char *file, char *magic_table[]) { size_t len = 0; char *json_data; const char *key; json_t *root; json_error_t error; json_t *config; json_t *config_value, *config_array_item; void *config_iter; char *object_asked = "uwsgi"; char *colon; int i; if (uwsgi_check_scheme(file)) { colon = uwsgi_get_last_char(file, '/'); colon = uwsgi_get_last_char(colon, ':'); } else { colon = uwsgi_get_last_char(file, ':'); } if (colon) { colon[0] = 0; if (colon[1] != 0) { object_asked = colon + 1; } } uwsgi_log_initial("[uWSGI] getting JSON configuration from %s\n", file); json_data = uwsgi_open_and_read(file, &len, 1, magic_table); #ifdef JANSSON_MAJOR_VERSION root = json_loads(json_data, 0, &error); #else root = json_loads(json_data, &error); #endif if (!root) { uwsgi_log("error parsing JSON data: line %d %s\n", error.line, error.text); exit(1); } config = json_object_get(root, object_asked); if (!json_is_object(config)) { uwsgi_log("you must define a object named %s in your JSON data\n", object_asked); exit(1); } config_iter = json_object_iter(config); while (config_iter) { key = json_object_iter_key(config_iter); config_value = json_object_iter_value(config_iter); if (json_is_string(config_value)) { add_exported_option((char *) key, (char *) json_string_value(config_value), 0); } else if (json_is_true(config_value)) { add_exported_option((char *) key, strdup("1"), 0); } else if (json_is_false(config_value) || json_is_null(config_value)) { add_exported_option((char *) key, strdup("0"), 0); } else if (json_is_integer(config_value)) { add_exported_option((char *) key, uwsgi_num2str(json_integer_value(config_value)), 0); } else if (json_is_array(config_value)) { for (i = 0; i < (int) json_array_size(config_value); i++) { config_array_item = json_array_get(config_value, i); if (json_is_string(config_array_item)) { add_exported_option((char *) key, (char *) json_string_value(config_array_item), 0); } else if (json_is_true(config_array_item)) { add_exported_option((char *) key, strdup("1"), 0); } else if (json_is_false(config_array_item) || json_is_null(config_array_item)) { add_exported_option((char *) key, strdup("0"), 0); } else if (json_is_integer(config_array_item)) { add_exported_option((char *) key, uwsgi_num2str(json_integer_value(config_array_item)), 0); } } } config_iter = json_object_iter_next(config, config_iter); } if (colon) colon[0] = ':'; }