static void fsp_directory(FSP_SESSION *ses, struct uri *uri) { struct string buf; FSP_DIR *dir; unsigned char *data = get_uri_string(uri, URI_DATA); unsigned char dircolor[8] = ""; if (!data) fsp_error(connection_state(S_OUT_OF_MEM)); decode_uri(data); if (!is_in_state(init_directory_listing(&buf, uri), S_OK)) fsp_error(connection_state(S_OUT_OF_MEM)); dir = fsp_opendir(ses, data); if (!dir) fsp_error(connection_state_for_errno(errno)); fprintf(stderr, "text/html"); fclose(stderr); puts(buf.source); if (get_opt_bool("document.browse.links.color_dirs", NULL)) { color_to_string(get_opt_color("document.colors.dirs", NULL), dircolor); } sort_and_display_entries(dir, dircolor); fsp_closedir(dir); puts("</pre><hr/></body></html>"); fsp_close_session(ses); exit(0); }
int decode_contact (struct sip_msg *msg,char *unused1,char *unused2) { str uri; str newUri; char separator; int res; uri.s = 0; uri.len = 0; #ifdef DEBUG fprintf (stdout,"---START--------DECODE CONTACT-----------------\n"); fprintf (stdout,"%.*s\n",50,msg->buf); fprintf (stdout, "INITIAL.s=[%.*s]\n", uri.len, uri.s); #endif separator = DEFAULT_SEPARATOR[0]; if (contact_flds_separator != NULL) if (strlen(contact_flds_separator)>=1) separator = contact_flds_separator[0]; if ((msg->new_uri.s == NULL) || (msg->new_uri.len == 0)) { uri = msg->first_line.u.request.uri; if (uri.s == NULL) return -1; } else { uri = msg->new_uri; } res = decode_uri (uri, separator, &newUri); #ifdef DEBUG if (res == 0) fprintf (stdout, "newuri.s=[%.*s]\n", newUri.len, newUri.s); #endif if (res != 0) { LM_ERR("failed decoding contact.Code %d\n", res); #ifdef STRICT_CHECK return res; #endif } else { /* we do not modify the original first line */ if ((msg->new_uri.s == NULL) || (msg->new_uri.len == 0)) msg->new_uri = newUri; else { pkg_free(msg->new_uri.s); msg->new_uri = newUri; } } return 1; }
void data_protocol_handler(struct connection *conn) { struct uri *uri = conn->uri; struct cache_entry *cached = get_cache_entry(uri); unsigned char *data_start, *data; int base64 = 0; if (!cached) { abort_connection(conn, connection_state(S_OUT_OF_MEM)); return; } conn->cached = cached; data_start = parse_data_protocol_header(conn, &base64); if (!data_start) { abort_connection(conn, connection_state(S_OUT_OF_MEM)); return; } /* Allocate the data string because URI decoding will possibly modify * it. */ data = memacpy(data_start, uri->datalen - (data_start - uri->data)); if (!data) { abort_connection(conn, connection_state(S_OUT_OF_MEM)); return; } if (base64) { unsigned char *decoded = base64_encode(data); if (!decoded) { abort_connection(conn, connection_state(S_OUT_OF_MEM)); return; } mem_free_set(&data, decoded); } else { decode_uri(data); } { /* Use strlen() to get the correct decoded length */ int datalen = strlen((const char *)data); add_fragment(cached, conn->from, data, datalen); conn->from += datalen; } mem_free(data); abort_connection(conn, connection_state(S_OK)); }
static unsigned char * get_file_download_text(struct listbox_item *item, struct terminal *term) { struct file_download *file_download = item->udata; unsigned char *uristring; uristring = get_uri_string(file_download->uri, URI_PUBLIC); if (uristring) { #ifdef CONFIG_UTF8 if (term->utf8_cp) decode_uri(uristring); else #endif /* CONFIG_UTF8 */ decode_uri_for_display(uristring); } return uristring; }
int decode_contact (struct sip_msg *msg,char *unused1,char *unused2) { str* uri; str newUri; str dst_uri; char separator; int res; separator = DEFAULT_SEPARATOR[0]; if (contact_flds_separator != NULL) if (strlen(contact_flds_separator)>=1) separator = contact_flds_separator[0]; if ((msg->new_uri.s == NULL) || (msg->new_uri.len == 0)) { uri = &msg->first_line.u.request.uri; }else{ uri = &msg->new_uri; } res = decode_uri (uri, separator, &newUri, &dst_uri); if (res != 0) { LOG (L_ERR,"ERROR: decode_contact:Failed decoding contact." "Code %d\n", res); return res; } else { /* we do not modify the original first line */ if (msg->new_uri.s) pkg_free(msg->new_uri.s); msg->new_uri = newUri; msg->parsed_uri_ok=0; msg->dst_uri = dst_uri; ruri_mark_new(); } return 1; }
int decode_contact_header (struct sip_msg *msg,char *unused1,char *unused2) { contact_body_t *cb; contact_t *c; str uri; str newUri; char separator; int res; #ifdef DEBUG str* ruri; fprintf (stdout,"---START--------DECODE CONTACT HEADER-----------------\n"); #endif if ((msg->contact == NULL)&&((parse_headers(msg,HDR_CONTACT_F,0) == -1) || (msg->contact== NULL) )) { LM_ERR("no Contact header present\n"); return -1; } separator = DEFAULT_SEPARATOR[0]; if (contact_flds_separator != NULL) if (strlen(contact_flds_separator)>=1) separator = contact_flds_separator[0]; #ifdef DEBUG fprintf (stdout,"Using separator %c\n",separator); ruri = GET_RURI(msg); fprintf (stdout,"[len = %d]New uri is->%.*s\n", ruri->len,ruri->len,ruri->s); ruri = &msg->first_line.u.request.uri; fprintf (stdout, "INITIAL.s=[%.*s]\n", ruri->len, ruri->s); #endif if (msg->contact->parsed == NULL) parse_contact (msg->contact); if (msg->contact->parsed != NULL) { cb = (contact_body_t *) msg->contact->parsed; c = cb->contacts; // we visit each contact if (c != NULL) { uri = c->uri; res = decode_uri (uri, separator, &newUri); #ifdef DEBUG fprintf (stdout, "newuri.s=[%.*s]\n", newUri.len, newUri.s); #endif if (res != 0) { LM_ERR("failed decoding contact.Code %d\n", res); #ifdef STRICT_CHECK return res; #endif } else if (patch (msg, uri.s, uri.len, newUri.s, newUri.len) < 0) { LM_ERR("lumping failed in mangling port \n"); return -2; } #ifdef DECODE_ALL_CONTACTS while (c->next != NULL) { c = c->next; uri = c->uri; res = decode_uri (uri, separator, &newUri); if (res != 0) { LM_ERR("failed decoding contact.Code %d\n",res); #ifdef STRICT_CHECK return res; #endif } else if (patch (msg, uri.s, uri.len, newUri.s, newUri.len) < 0) { LM_ERR("lumping failed in mangling port \n"); return -3; } } // end while #endif } // if c!= NULL } // end if else // after parsing still NULL { LM_ERR("unable to parse Contact header\n"); return -4; } #ifdef DEBUG fprintf (stdout,"---END--------DECODE CONTACT HEADER-----------------\n");fflush(stdout); #endif return 1; }
int decode_contact_header (struct sip_msg *msg,char *unused1,char *unused2) { contact_body_t *cb; contact_t *c; str* uri; str newUri; char separator; int res; if ((msg->contact == NULL)&&((parse_headers(msg,HDR_CONTACT_F,0) == -1) || (msg->contact== NULL) )) { LOG(L_ERR,"ERROR: decode_contact_header: no Contact header present\n"); return -1; } separator = DEFAULT_SEPARATOR[0]; if (contact_flds_separator != NULL) if (strlen(contact_flds_separator)>=1) separator = contact_flds_separator[0]; if (msg->contact->parsed == NULL) parse_contact (msg->contact); if (msg->contact->parsed != NULL) { cb = (contact_body_t *) msg->contact->parsed; c = cb->contacts; // we visit each contact if (c != NULL) { uri = &c->uri; res = decode_uri (uri, separator, &newUri, 0); if (res != 0) { LOG (L_ERR,"ERROR: decode_contact_header:Failed decoding contact.Code %d\n", res); #ifdef STRICT_CHECK return res; #endif } else if (patch (msg, uri->s, uri->len, newUri.s, newUri.len) < 0) { LOG (L_ERR,"ERROR: decode_contact:lumping failed in mangling port \n"); return -2; } #ifdef DECODE_ALL_CONTACTS while (c->next != NULL) { c = c->next; uri = &c->uri; res = decode_uri (uri, separator, &newUri, 0); if (res != 0) { LOG (L_ERR,"ERROR: decode_contact: Failed decoding contact.Code %d\n",res); #ifdef STRICT_CHECK return res; #endif } else if (patch (msg, uri->s, uri->len, newUri.s, newUri.len) < 0) { LOG (L_ERR,"ERROR: decode_contact:lumping failed in mangling port \n"); return -3; } } // end while #endif } // if c!= NULL } // end if else // after parsing still NULL { LOG(L_ERR,"ERROR: decode_contact: Unable to parse Contact header\n"); return -4; } return 1; }
cmd_response_t cmd_run(struct worker *w, struct http_client *client, const char *uri, size_t uri_len, const char *body, size_t body_len) { char *qmark = memchr(uri, '?', uri_len); char *slash; const char *p, *cmd_name = uri; int cmd_len; int param_count = 0, cur_param = 1; struct cmd *cmd; formatting_fun f_format; /* count arguments */ if(qmark) { uri_len = qmark - uri; } for(p = uri; p && p < uri + uri_len; param_count++) { p = memchr(p+1, '/', uri_len - (p+1-uri)); } if(body && body_len) { /* PUT request */ param_count++; } if(param_count == 0) { return CMD_PARAM_ERROR; } cmd = cmd_new(param_count); cmd->fd = client->fd; cmd->database = w->s->cfg->database; /* get output formatting function */ uri_len = cmd_select_format(client, cmd, uri, uri_len, &f_format); /* add HTTP info */ cmd_setup(cmd, client); /* check if we only have one command or more. */ slash = memchr(uri, '/', uri_len); if(slash) { /* detect DB number by checking if first arg is only numbers */ int has_db = 1; int db_num = 0; for(p = uri; p < slash; ++p) { if(*p < '0' || *p > '9') { has_db = 0; break; } db_num = db_num * 10 + (*p - '0'); } /* shift to next arg if a db was set up */ if(has_db) { char *next; cmd->database = db_num; cmd->count--; /* overcounted earlier */ cmd_name = slash + 1; if((next = memchr(cmd_name, '/', uri_len - (slash - uri)))) { cmd_len = next - cmd_name; } else { cmd_len = uri_len - (slash - uri + 1); } } else { cmd_len = slash - uri; } } else { cmd_len = uri_len; } /* there is always a first parameter, it's the command name */ cmd->argv[0] = malloc(cmd_len); memcpy(cmd->argv[0], cmd_name, cmd_len); cmd->argv_len[0] = cmd_len; /* check that the client is able to run this command */ if(!acl_allow_command(cmd, w->s->cfg, client)) { cmd_free(cmd); return CMD_ACL_FAIL; } if(cmd_is_subscribe(cmd)) { /* create a new connection to Redis */ cmd->ac = (redisAsyncContext*)pool_connect(w->pool, cmd->database, 0); /* register with the client, used upon disconnection */ client->pub_sub = cmd; cmd->pub_sub_client = client; } else if(cmd->database != w->s->cfg->database) { /* create a new connection to Redis for custom DBs */ cmd->ac = (redisAsyncContext*)pool_connect(w->pool, cmd->database, 0); } else { /* get a connection from the pool */ cmd->ac = (redisAsyncContext*)pool_get_context(w->pool); } /* no args (e.g. INFO command) */ if(!slash) { if(!cmd->ac) { cmd_free(cmd); return CMD_REDIS_UNAVAIL; } redisAsyncCommandArgv(cmd->ac, f_format, cmd, 1, (const char **)cmd->argv, cmd->argv_len); return CMD_SENT; } p = cmd_name + cmd_len + 1; while(p < uri + uri_len) { const char *arg = p; int arg_len; char *next = memchr(arg, '/', uri_len - (arg-uri)); if(!next || next > uri + uri_len) { /* last argument */ p = uri + uri_len; arg_len = p - arg; } else { /* found a slash */ arg_len = next - arg; p = next + 1; } /* record argument */ cmd->argv[cur_param] = decode_uri(arg, arg_len, &cmd->argv_len[cur_param], 1); cur_param++; } if(body && body_len) { /* PUT request */ cmd->argv[cur_param] = malloc(body_len); memcpy(cmd->argv[cur_param], body, body_len); cmd->argv_len[cur_param] = body_len; } /* send it off! */ if(cmd->ac) { cmd_send(cmd, f_format); return CMD_SENT; } /* failed to find a suitable connection to Redis. */ cmd_free(cmd); client->pub_sub = NULL; return CMD_REDIS_UNAVAIL; }
static void download_dialog_layouter(struct dialog_data *dlg_data) { struct file_download *file_download = dlg_data->dlg->udata; struct terminal *term = dlg_data->win->term; int w = dialog_max_width(term); int rw = w; int x, y = 0; int url_len; unsigned char *url; struct download *download = &file_download->download; struct color_pair *dialog_text_color = get_bfu_color(term, "dialog.text"); unsigned char *msg = get_download_msg(download, term, 1, 1, "\n"); int show_meter = (download_is_progressing(download) && download->progress->size >= 0); #if CONFIG_BITTORRENT int bittorrent = (file_download->uri->protocol == PROTOCOL_BITTORRENT && (show_meter || is_in_state(download->state, S_RESUME))); #endif redraw_windows(REDRAW_BEHIND_WINDOW, dlg_data->win); file_download->dlg_data = dlg_data; if (!msg) return; url = get_uri_string(file_download->uri, URI_PUBLIC); if (!url) { mem_free(msg); return; } #ifdef CONFIG_UTF8 if (term->utf8_cp) decode_uri(url); else #endif /* CONFIG_UTF8 */ decode_uri_for_display(url); url_len = strlen(url); if (show_meter) { int_lower_bound(&w, DOWN_DLG_MIN); } dlg_format_text_do(dlg_data, url, 0, &y, w, &rw, dialog_text_color, ALIGN_LEFT, 1); y++; if (show_meter) y += 2; #if CONFIG_BITTORRENT if (bittorrent) y += 2; #endif dlg_format_text_do(dlg_data, msg, 0, &y, w, &rw, dialog_text_color, ALIGN_LEFT, 1); y++; dlg_format_buttons(dlg_data, dlg_data->widgets_data, dlg_data->number_of_widgets, 0, &y, w, &rw, ALIGN_CENTER, 1); draw_dialog(dlg_data, w, y); w = rw; if (url_len > w) { /* Truncate too long urls */ url_len = w; url[url_len] = '\0'; if (url_len > 4) { url[--url_len] = '.'; url[--url_len] = '.'; url[--url_len] = '.'; } } y = dlg_data->box.y + DIALOG_TB + 1; x = dlg_data->box.x + DIALOG_LB; dlg_format_text_do(dlg_data, url, x, &y, w, NULL, dialog_text_color, ALIGN_LEFT, 0); if (show_meter) { y++; draw_progress_bar(download->progress, term, x, y, w, NULL, NULL); y++; } #if CONFIG_BITTORRENT if (bittorrent) { y++; draw_bittorrent_piece_progress(download, term, x, y, w, NULL, NULL); y++; } #endif y++; dlg_format_text_do(dlg_data, msg, x, &y, w, NULL, dialog_text_color, ALIGN_LEFT, 0); y++; dlg_format_buttons(dlg_data, dlg_data->widgets_data, dlg_data->number_of_widgets, x, &y, w, NULL, ALIGN_CENTER, 0); mem_free(url); mem_free(msg); }
/** Prepare to read POST data from a URI and possibly to upload files. * * @param http_post * Must have been initialized with init_http_post(). * @param[in] post_data * The body of the POST request as formatted by get_form_uri(). * However, unlike uri.post, @a post_data must not contain any * Content-Type. The caller must ensure that the @a post_data * pointer remains valid until done_http_post(). * @param[out] error * If the function fails, it writes the error state here so that * the caller can pass that on to abort_connection(). If the * function succeeds, the value of *@a error is undefined. * * This function does not parse the Content-Type from uri.post; the * caller must do that. This is because in local CGI, the child * process handles the Content-Type (saving it to an environment * variable before exec) but the parent process handles the body of * the request (feeding it to the child process via a pipe). * * @return nonzero on success, zero on error. * * @relates http_post */ int open_http_post(struct http_post *http_post, const unsigned char *post_data, struct connection_state *error) { off_t size = 0; size_t length = strlen((const char *)post_data); const unsigned char *end = post_data; done_http_post(http_post); http_post->post_data = end; while (1) { struct stat sb; const unsigned char *begin; int res; struct http_post_file *new_files; unsigned char *filename; begin = (const unsigned char *)strchr((char *)end, FILE_CHAR); if (!begin) break; end = (const unsigned char *)strchr((char *)(begin + 1), FILE_CHAR); if (!end) break; filename = memacpy(begin + 1, end - begin - 1); /* adds '\0' */ if (!filename) { done_http_post(http_post); *error = connection_state(S_OUT_OF_MEM); return 0; } decode_uri(filename); res = stat((const char *)filename, &sb); if (res) { *error = connection_state_for_errno(errno); done_http_post(http_post); return 0; } /* This use of mem_realloc() in a loop consumes O(n^2) * time but how many files are you really going to * upload in one request? */ new_files = (struct http_post_file *)mem_realloc(http_post->files, (http_post->file_count + 1) * sizeof(*new_files)); if (new_files == NULL) { mem_free(filename); done_http_post(http_post); *error = connection_state(S_OUT_OF_MEM); return 0; } http_post->files = new_files; new_files[http_post->file_count].name = filename; new_files[http_post->file_count].size = sb.st_size; http_post->file_count++; size += sb.st_size; length -= (end - begin + 1); end++; } size += (length / 2); http_post->total_upload_length = size; return 1; }
int cmd_run(struct server *s, struct evhttp_request *rq, const char *uri, size_t uri_len, const char *body, size_t body_len) { char *qmark = strchr(uri, '?'); char *slash; const char *p; int cmd_len; int param_count = 0, cur_param = 1, i; struct cmd *cmd; formatting_fun f_format; /* count arguments */ if(qmark) { uri_len = qmark - uri; } for(p = uri; p && p < uri + uri_len; param_count++) { p = strchr(p+1, '/'); } if(body && body_len) { /* PUT request */ param_count++; } cmd = cmd_new(rq, param_count); /* parse URI parameters */ evhttp_parse_query(uri, &cmd->uri_params); /* get output formatting function */ uri_len = cmd_select_format(cmd, uri, uri_len, &f_format); /* check if we only have one command or more. */ slash = memchr(uri, '/', uri_len); if(slash) { cmd_len = slash - uri; } else { cmd_len = uri_len; } /* there is always a first parameter, it's the command name */ cmd->argv[0] = uri; cmd->argv_len[0] = cmd_len; /* check that the client is able to run this command */ if(!acl_allow_command(cmd, s->cfg, rq)) { return -1; } /* check if we have to split the connection */ if(cmd_is_subscribe(cmd)) { struct pubsub_client *ps; ps = calloc(1, sizeof(struct pubsub_client)); ps->s = s = server_copy(s); ps->cmd = cmd; ps->rq = rq; evhttp_connection_set_closecb(rq->evcon, on_http_disconnect, ps); } /* no args (e.g. INFO command) */ if(!slash) { redisAsyncCommandArgv(s->ac, f_format, cmd, 1, cmd->argv, cmd->argv_len); return 0; } p = slash + 1; while(p < uri + uri_len) { const char *arg = p; int arg_len; char *next = strchr(arg, '/'); if(!next || next > uri + uri_len) { /* last argument */ p = uri + uri_len; arg_len = p - arg; } else { /* found a slash */ arg_len = next - arg; p = next + 1; } /* record argument */ cmd->argv[cur_param] = decode_uri(arg, arg_len, &cmd->argv_len[cur_param], 1); cur_param++; } if(body && body_len) { /* PUT request */ cmd->argv[cur_param] = body; cmd->argv_len[cur_param] = body_len; } /* push command to Redis. */ redisAsyncCommandArgv(s->ac, f_format, cmd, cmd->count, cmd->argv, cmd->argv_len); for(i = 1; i < cur_param; ++i) { free((char*)cmd->argv[i]); } return 0; }
static void do_fsp(struct connection *conn) { FSP_SESSION *ses; struct stat sb; struct uri *uri = conn->uri; struct auth_entry *auth; unsigned char *host = get_uri_string(uri, URI_HOST); unsigned char *data = get_uri_string(uri, URI_DATA); unsigned short port = (unsigned short)get_uri_port(uri); unsigned char *password = NULL; decode_uri(data); if (uri->passwordlen) { password = get_uri_string(uri, URI_PASSWORD); } else { auth = find_auth(uri); if (auth) password = auth->password; } /* fsp_open_session may not set errno if getaddrinfo fails * https://sourceforge.net/tracker/index.php?func=detail&aid=2036798&group_id=93841&atid=605738 * Try to detect this bug and use an ELinks-specific error * code instead, so that we can display a message anyway. */ errno = 0; ses = fsp_open_session(host, port, password); if (!ses) { if (errno) fsp_error(connection_state_for_errno(errno)); else fsp_error(connection_state(S_FSP_OPEN_SESSION_UNKN)); } /* fsplib 0.8 ABI depends on _FILE_OFFSET_BITS * https://sourceforge.net/tracker/index.php?func=detail&aid=1674729&group_id=93841&atid=605738 * If ELinks and fsplib are using different values of * _FILE_OFFSET_BITS, then they get different definitions of * struct stat, and the st_size stored by fsp_stat is * typically not the same as the st_size read by ELinks. * Fortunately, st_mode seems to have the same offset and size * in both versions of struct stat. * * If all the bytes used by the 32-bit st_size are also used * by the 64-bit st_size, then ELinks may be able to guess * which ones they are, because the current version 2 of FSP * supports only 32-bit file sizes in protocol packets. Begin * by filling struct stat with 0xAA so that it's easier to * detect which bytes fsp_stat has left unchanged. (Only * sb.st_size really needs to be filled, but filling the rest * too helps viewing the data with a debugger.) */ memset(&sb, 0xAA, sizeof(sb)); if (fsp_stat(ses, data, &sb)) fsp_error(connection_state_for_errno(errno)); if (S_ISDIR(sb.st_mode)) { fsp_directory(ses, uri); } else { /* regular file */ char buf[READ_SIZE]; FSP_FILE *file = fsp_fopen(ses, data, "r"); int r; if (!file) { fsp_error(connection_state_for_errno(errno)); } #if SIZEOF_OFF_T >= 8 if (sb.st_size < 0 || sb.st_size > 0xFFFFFFFF) { /* Probably a _FILE_OFFSET_BITS mismatch as * described above. Try to detect which half * of st_size is the real size. This may * depend on the endianness of the processor * and on the padding in struct stat. */ if ((sb.st_size & 0xFFFFFFFF00000000ULL) == 0xAAAAAAAA00000000ULL) sb.st_size = sb.st_size & 0xFFFFFFFF; else if ((sb.st_size & 0xFFFFFFFF) == 0xAAAAAAAA) sb.st_size = (sb.st_size >> 32) & 0xFFFFFFFF; else /* Can't figure it out. */ sb.st_size = 1; } #endif /* Send filesize */ fprintf(stderr, "%" OFF_PRINT_FORMAT "\n", (off_print_T) sb.st_size); fclose(stderr); while ((r = fsp_fread(buf, 1, READ_SIZE, file)) > 0) { int off = 0; while (r) { int w = safe_write(STDOUT_FILENO, buf + off, r); if (w == -1) goto out; off += w; r -= w; } } out: fsp_fclose(file); fsp_close_session(ses); exit(0); }