int main(void) { char req[] = "Post /test?name=value&name2=value2 HTTP/1.1\r\n" "Content-Length: 12345\r\n" "Host: www.example.com \r\n" "Pragma: no-cache\r\n" "Accept-Encoding: text/plain\r\n" "\r\nTHIS_IS_THE_BODY"; int len = strlen(req); printf("Body: %s\n", http_parse_body(req, len)); printf("Method: %d (%s)\n", http_parse_method(req), http_method_str[http_parse_method(req)]); printf("URI: '%s' (path is '%s')\n", http_parse_uri(req), http_parse_path(http_parse_uri(req))); printf("Pragma: '%s'\n", http_parse_header_field(req, len, "Pragma")); printf("Content-length: '%s'\n", http_parse_header_field(req, len, "Content-length")); printf("Accept-Encoding: '%s'\n", http_parse_header_field(req, len, "Accept-Encoding")); printf("Host: '%s'\n", http_parse_header_field(req, len, "Host")); printf("Body: %s\n", http_parse_body(req, len)); printf("Method: %d (%s)\n", http_parse_method(req), http_method_str[http_parse_method(req)]); printf("URI: '%s' (path is '%s')\n", http_parse_uri(req), http_parse_path(http_parse_uri(req))); printf("Pragma: '%s'\n", http_parse_header_field(req, len, "Pragma")); printf("Content-length: '%s'\n", http_parse_header_field(req, len, "Content-length")); printf("Accept-Encoding: '%s'\n", http_parse_header_field(req, len, "Accept-Encoding")); printf("Host: '%s'\n", http_parse_header_field(req, len, "Host")); return 0; }
void init_req_header(req_header * req, char * header){ int len = strlen(header); req->body = http_parse_body(header, len); req->method = http_parse_method((char *) header); req->uri = http_parse_uri(header); req->path = http_parse_path(http_parse_uri(header)); cookie * cookies = parse_cookies(header); req->cookies = cookies; req->connection = http_parse_header_field(header, len, "Connection"); }
void init_req_header(req_header * req, char * header){ char * cookie_header = malloc(strlen(header)); strcpy(cookie_header, header); int len = strlen(header); req->body = http_parse_body(header, len); req->method = http_parse_method((char *) header); req->uri = http_parse_uri(header); req->path = http_parse_path(http_parse_uri(header)); req->connection = http_parse_header_field( header, len, "Connection"); req->cache_control = http_parse_header_field(header, len, "Cache-Control"); cookie * cookies = parse_cookies(cookie_header, &(req->num_cookies)); req->cookies = cookies; }
/* Run the help command for the engine responsible for URI. */ gpg_error_t ks_action_help (ctrl_t ctrl, const char *url) { gpg_error_t err; parsed_uri_t parsed_uri; /* The broken down URI. */ if (!url || !*url) { ks_print_help (ctrl, "Known schemata:\n"); parsed_uri = NULL; } else { err = http_parse_uri (&parsed_uri, url, 1); if (err) return err; } /* Call all engines to give them a chance to print a help sting. */ err = ks_hkp_help (ctrl, parsed_uri); if (!err) err = ks_http_help (ctrl, parsed_uri); if (!err) err = ks_finger_help (ctrl, parsed_uri); if (!err) err = ks_kdns_help (ctrl, parsed_uri); if (!parsed_uri) ks_print_help (ctrl, "(Use an URL for engine specific help.)"); else http_release_parsed_uri (parsed_uri); return err; }
/* Retrieve keys from URL and write the result to the provided output stream OUTFP. */ gpg_error_t ks_action_fetch (ctrl_t ctrl, const char *url, estream_t outfp) { gpg_error_t err = 0; estream_t infp; parsed_uri_t parsed_uri; /* The broken down URI. */ if (!url) return gpg_error (GPG_ERR_INV_URI); err = http_parse_uri (&parsed_uri, url, 1); if (err) return err; if (parsed_uri->is_http) { err = ks_http_fetch (ctrl, url, &infp); if (!err) { err = copy_stream (infp, outfp); es_fclose (infp); } } else if (!parsed_uri->opaque) { err = gpg_error (GPG_ERR_INV_URI); } else if (!strcmp (parsed_uri->scheme, "finger")) { err = ks_finger_fetch (ctrl, parsed_uri, &infp); if (!err) { err = copy_stream (infp, outfp); es_fclose (infp); } } else if (!strcmp (parsed_uri->scheme, "kdns")) { err = ks_kdns_fetch (ctrl, parsed_uri, &infp); if (!err) { err = copy_stream (infp, outfp); es_fclose (infp); } } else err = gpg_error (GPG_ERR_INV_URI); http_release_parsed_uri (parsed_uri); return err; }
/* Mark the host NAME as dead. NAME may be given as an URL. Returns true if a host was really marked as dead or was already marked dead (e.g. by a concurrent session). */ static int mark_host_dead (const char *name) { const char *host; char *host_buffer = NULL; parsed_uri_t parsed_uri = NULL; int done = 0; if (name && *name && !http_parse_uri (&parsed_uri, name, 1)) { if (parsed_uri->v6lit) { host_buffer = strconcat ("[", parsed_uri->host, "]", NULL); if (!host_buffer) log_error ("out of core in mark_host_dead"); host = host_buffer; } else host = parsed_uri->host; } else host = name; if (host && *host && strcmp (host, "localhost")) { hostinfo_t hi; int idx; idx = find_hostinfo (host); if (idx != -1) { hi = hosttable[idx]; log_info ("marking host '%s' as dead%s\n", hi->name, hi->dead? " (again)":""); hi->dead = 1; hi->died_at = gnupg_get_time (); if (!hi->died_at) hi->died_at = 1; done = 1; } } http_release_parsed_uri (parsed_uri); xfree (host_buffer); return done; }
Request parse_request(char *reqstr) { http_method method = http_parse_method(reqstr); char *uri = http_parse_uri(reqstr); char *path = http_parse_path(uri); // field 1 // field 2 // field n // body; Request reqobj; reqobj.uri = uri; reqobj.path = path; return reqobj; }
int http_open(struct http_get *hg, int timeout_ms) { struct hostent *hostent; union { struct sockaddr sa; struct sockaddr_in in; } addr; struct timeval tv; int save, flags; char *proxy = getenv("http_proxy"); if (proxy) { hg->proxy = xnew(struct http_uri, 1); if (http_parse_uri(proxy, hg->proxy)) { d_print("Failed to parse HTTP proxy URI '%s'\n", proxy); return -1; } } else {
/** * This function initializes the tcp context global instance to 0 except for * file descriptor descriptor for stdin, stdout and stderr. * * @author Mohd Naushad Ahmed * @version 1.0 * @param none * @return none */ int http_parse_req ( int conn_id, char *http_req, int http_req_len ) { char *http_header_string; int mime_idx = 0; if (NULL != (http_header_string = strtok(http_req,"\r\n"))) { strcpy(g_http_ctx[conn_id].uri, http_header_string); } while (NULL != (http_header_string = strtok(NULL,"\r\n"))) { mime_idx++; /* starts the scanning until : is encountered & store them into global */ sscanf(http_header_string,"%[^:]:%s", g_http_ctx[conn_id].mime_header[mime_idx].mime_tag_name, g_http_ctx[conn_id].mime_header[mime_idx].mime_value); } g_http_ctx[conn_id].max_mime_header_num = mime_idx; http_parse_uri(conn_id); return ( 0 ); }/* http_parse_req */
int http_parse(h_parser_ctx * ctx) { h_head_info * info; lx_buffer * orig_buff; char * end, *buff,temp_buff; int parser_index,maxlen,tint; lx_kvlist_node * headers,*header ; loop: orig_buff = &ctx->orig_buff; buff = orig_buff->base; maxlen = orig_buff->len; parser_index = orig_buff->offset; info = (h_head_info *)&ctx->info; if(orig_buff->offset >= orig_buff->len ) goto need_more; switch(ctx->cur_stat) { case S_NONE: if(ctx->type == T_REQ){ ctx->cur_stat = S_REQ_METHOD; }else{ ctx->cur_stat = S_RESP_PROTOCAL; } info->type = ctx->type; info->base = orig_buff->base; goto loop; case S_REQ_METHOD: //if(info->mtod_str.offset == 0) // info->mtod_str.offset = parser_index; if((end = read2space(buff +parser_index , maxlen - parser_index )) == NULL ) goto need_more; if( (tint=match_str(buff+ parser_index, h_mtod_str,sizeof(h_mtod_str)/sizeof(h_mtod_str[0]) -1 ) ) == -1) return HEC_INVALID_METHOD; info->mtod = tint; orig_buff->offset = end - buff; ctx->cur_stat = S_ITEM_SPACE; ctx->next_stat = S_REQ_URI; goto loop; case S_REQ_URI: if(info->uri.offset == 0) info->uri.offset = parser_index; if((end = read2space(buff + parser_index, maxlen - parser_index )) == NULL ) goto need_more; orig_buff->offset = end - buff; ctx->last_stat = S_REQ_URI; ctx->cur_stat = S_ITEM_SPACE; ctx->next_stat = S_REQ_PROTOCAL; goto loop; case S_REQ_PROTOCAL: if(ctx->type ==T_REQ && info->prot_str.offset == 0) info->prot_str.offset = parser_index; if((end = read2nl(buff + parser_index , maxlen - parser_index )) == NULL ) goto need_more; if( tint = get_http_prot(buff + parser_index,end - buff - parser_index) == -1) return HEC_INVALID_PROT; info->prot = tint; orig_buff->offset = end - buff; ctx->cur_stat = S_NEW_LINE; ctx->next_stat = S_HEADER_KEY; goto loop; case S_RESP_PROTOCAL: //if(info->prot_str.offset == 0) // info->prot_str.offset = parser_index; if((end = read2space(buff + parser_index , maxlen - parser_index )) == NULL ) goto need_more; if( tint = get_http_prot(buff + parser_index,end - buff - parser_index) == -1) return HEC_INVALID_PROT; info->prot = tint; orig_buff->offset = end - buff; ctx->cur_stat = S_ITEM_SPACE; ctx->next_stat = S_RESP_CODE; goto loop; case S_RESP_CODE: if(ctx->temp_buff.offset == 0) ctx->temp_buff.offset = parser_index; if((end = read2space(buff +parser_index , maxlen - parser_index )) == NULL ) goto need_more; if( ((tint = atoi(buff+ parser_index)) < 0)) return HEC_INVALID_CODE; info->resp_code = tint; orig_buff->offset = end - buff; ctx->cur_stat = S_ITEM_SPACE; ctx->next_stat = S_RESP_STR; goto loop; case S_RESP_STR: if(info->code_str.offset == 0) info->code_str.offset = parser_index; if((end = read2nl(buff + parser_index , maxlen - parser_index )) == NULL ) goto need_more; orig_buff->offset = end - buff; ctx->cur_stat = S_NEW_LINE; ctx->next_stat = S_HEADER_KEY; goto loop; case S_HEADER_KEY: if(info->header_key.offset == 0) info->header_key.offset = parser_index; if( (end = read2str(buff+parser_index, maxlen - parser_index,HTTP_HEADER_SEP_STR)) == NULL) goto need_more; orig_buff->offset = end - buff; ctx->cur_stat = S_HEADER_SEP; goto loop; case S_HEADER_VALUE: if(info->header_value.offset == 0 ) info->header_value.offset = parser_index; if((end = read2nl(buff + parser_index , maxlen - parser_index )) == NULL ) goto need_more; header =(lx_kvlist_node *)list_append((lx_list_node **)&info->headers,sizeof(lx_kvlist_node),ctx->hmalloc); if(header == NULL) return HEC_APPNODE_ERR; header->key = info->header_key; header->value = info->header_value; info->header_key.offset = 0; info->header_value.offset = 0; orig_buff->offset = end - buff; ctx->cur_stat = S_NEW_LINE; ctx->next_stat = S_HEADER_KEY; goto loop; case S_HEADER_SEP: orig_buff->base[ orig_buff->offset] = 0; orig_buff->offset += strlen(HTTP_HEADER_SEP_STR); ctx->cur_stat = S_HEADER_VALUE; goto loop; case S_BODY: break; case S_ITEM_SPACE: orig_buff->base[ orig_buff->offset] = 0; orig_buff->offset++; if(ctx->last_stat == S_REQ_URI) if(http_parse_uri(ctx)) return HEC_PARSE_URI_ERR; ctx ->last_stat = S_NONE; ctx->cur_stat = ctx->next_stat; goto loop; case S_NEW_LINE: if(maxlen - orig_buff->offset <(int)(2 * strlen(HTTP_NEW_LINE_STR)) ) goto need_more; orig_buff->base[ orig_buff->offset] = 0; orig_buff->offset +=2; if( strncmp(orig_buff->base + orig_buff->offset , HTTP_NEW_LINE_STR,strlen(HTTP_NEW_LINE_STR ) ) == 0 ) { orig_buff->offset += 2; return HEC_OK; } ctx->cur_stat = ctx->next_stat; goto loop; default: ; } return 0; need_more: if(orig_buff->len == orig_buff->maxlen) { if( ctx->hextend(orig_buff) ) return HEC_EXTEND_ERR; info->base = orig_buff->base; } return HEC_NEED_MORE; };
/* ** parse http message: ** http_eoh - end of headers ** {http_header, Key, Value} - Key = atom() | string() ** {http_request, Method,Url,Version} ** {http_response, Version, Status, Message} ** {http_error, Error-Line} */ int packet_parse_http(const char* buf, int len, int* statep, PacketCallbacks* pcb, void* arg) { const char* ptr = buf; const char* p0; int n = len; /* remove trailing CRNL (accept NL as well) */ if ((n >= 2) && (buf[n-2] == '\r')) n -= 2; else if ((n >= 1) && (buf[n-1] == '\n')) n -= 1; if (*statep == 0) { /* start-line = Request-Line | Status-Line */ if (n >= 5 && (strncmp(buf, "HTTP/", 5) == 0)) { int major = 0; int minor = 0; int status = 0; /* Status-Line = HTTP-Version SP * Status-Code SP Reason-Phrase * CRNL * HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT */ ptr += 5; n -= 5; p0 = ptr; while (n && isdigit((int) *ptr)) { major = 10*major + (*ptr - '0'); ptr++; n--; } if (ptr==p0 || !n || (*ptr != '.')) return -1; ptr++; n--; p0 = ptr; while (n && isdigit((int) *ptr)) { minor = 10*minor + (*ptr - '0'); ptr++; n--; } if (ptr==p0) return -1; p0 = ptr; while (n && SP(ptr)) { ptr++; n--; } if (ptr==p0) return -1; while (n && isdigit((int) *ptr)) { status = 10*status + (*ptr - '0'); ptr++; n--; } p0 = ptr; while (n && SP(ptr)) { ptr++; n--; } if (ptr==p0 && n>0) return -1; /* NOTE: the syntax allows empty reason phrases */ (*statep) = !0; return pcb->http_response(arg, major, minor, status, ptr, n); } else { /* Request-Line = Method SP Request-URI SP HTTP-Version CRLF */ http_atom_t* meth; const char* meth_ptr = buf; int meth_len; PacketHttpURI uri; const char* uri_ptr; int uri_len; int major = 0; int minor = 0; unsigned long h = 0; while (n && !is_tspecial((unsigned char)*ptr)) { hash_update(h, (int)*ptr); ptr++; n--; } meth_len = ptr - meth_ptr; if (n == 0 || meth_len == 0 || !SP(ptr)) return -1; meth = http_hash_lookup(meth_ptr, meth_len, h, http_meth_hash, HTTP_METH_HASH_SIZE); while (n && SP(ptr)) { ptr++; n--; } uri_ptr = ptr; while (n && !SP(ptr)) { ptr++; n--; } if ((uri_len = (ptr - uri_ptr)) == 0) return -1; while (n && SP(ptr)) { ptr++; n--; } if (n == 0) { (*statep) = !0; http_parse_uri(&uri, uri_ptr, uri_len); return pcb->http_request(arg, meth, meth_ptr, meth_len, &uri, 0, 9); } if (n < 8) return -1; if (strncmp(ptr, "HTTP/", 5) != 0) return -1; ptr += 5; n -= 5; p0 = ptr; while (n && isdigit((int) *ptr)) { major = 10*major + (*ptr - '0'); ptr++; n--; } if (ptr==p0 || !n || (*ptr != '.')) return -1; ptr++; n--; p0 = ptr; while (n && isdigit((int) *ptr)) { minor = 10*minor + (*ptr - '0'); ptr++; n--; } if (ptr==p0) return -1; (*statep) = !0; http_parse_uri(&uri, uri_ptr, uri_len); return pcb->http_request(arg, meth, meth_ptr, meth_len, &uri, major, minor); } } else { int up = 1; /* make next char uppercase */ http_atom_t* name; char name_buf[HTTP_MAX_NAME_LEN]; const char* name_ptr = name_buf; int name_len; unsigned long h; if (n == 0) { /* end of headers */ *statep = 0; /* reset state (for next request) */ return pcb->http_eoh(arg); } h = 0; name_len = 0; while (!is_tspecial((unsigned char)*ptr)) { if (name_len < HTTP_MAX_NAME_LEN) { int c = *ptr; if (up) { if (islower(c)) { c = toupper(c); } up = 0; } else { if (isupper(c)) c = tolower(c); else if (c == '-') up = 1; } name_buf[name_len] = c; hash_update(h, c); } name_len++; ptr++; if (--n == 0) return -1; } while (n && SP(ptr)) { /* Skip white space before ':' */ ptr++; n--; } if (*ptr != ':') { return -1; } if (name_len <= HTTP_MAX_NAME_LEN) { name = http_hash_lookup(name_buf, name_len, h, http_hdr_hash, HTTP_HDR_HASH_SIZE); } else { /* Is it ok to return original name without case adjustments? */ name_ptr = buf; name = NULL; } ptr++; n--; /* Skip white space after ':' */ while (n && SP(ptr)) { ptr++; n--; } return pcb->http_header(arg, name, name_ptr, name_len, ptr, n); } return -1; }
int main (int argc, char **argv) { int last_argc = -1; gpg_error_t err; int rc; parsed_uri_t uri; uri_tuple_t r; http_t hd; int c; unsigned int my_http_flags = 0; int no_out = 0; int tls_dbg = 0; int no_crl = 0; const char *cafile = NULL; http_session_t session = NULL; unsigned int timeout = 0; gpgrt_init (); log_set_prefix (PGM, GPGRT_LOG_WITH_PREFIX | GPGRT_LOG_WITH_PID); if (argc) { argc--; argv++; } while (argc && last_argc != argc ) { last_argc = argc; if (!strcmp (*argv, "--")) { argc--; argv++; break; } else if (!strcmp (*argv, "--help")) { fputs ("usage: " PGM " URL\n" "Options:\n" " --verbose print timings etc.\n" " --debug flyswatter\n" " --tls-debug N use TLS debug level N\n" " --cacert FNAME expect CA certificate in file FNAME\n" " --timeout MS timeout for connect in MS\n" " --no-verify do not verify the certificate\n" " --force-tls use HTTP_FLAG_FORCE_TLS\n" " --force-tor use HTTP_FLAG_FORCE_TOR\n" " --no-out do not print the content\n" " --no-crl do not consuilt a CRL\n", stdout); exit (0); } else if (!strcmp (*argv, "--verbose")) { verbose++; argc--; argv++; } else if (!strcmp (*argv, "--debug")) { verbose += 2; debug++; argc--; argv++; } else if (!strcmp (*argv, "--tls-debug")) { argc--; argv++; if (argc) { tls_dbg = atoi (*argv); argc--; argv++; } } else if (!strcmp (*argv, "--cacert")) { argc--; argv++; if (argc) { cafile = *argv; argc--; argv++; } } else if (!strcmp (*argv, "--timeout")) { argc--; argv++; if (argc) { timeout = strtoul (*argv, NULL, 10); argc--; argv++; } } else if (!strcmp (*argv, "--no-verify")) { no_verify = 1; argc--; argv++; } else if (!strcmp (*argv, "--force-tls")) { my_http_flags |= HTTP_FLAG_FORCE_TLS; argc--; argv++; } else if (!strcmp (*argv, "--force-tor")) { my_http_flags |= HTTP_FLAG_FORCE_TOR; argc--; argv++; } else if (!strcmp (*argv, "--no-out")) { no_out = 1; argc--; argv++; } else if (!strcmp (*argv, "--no-crl")) { no_crl = 1; argc--; argv++; } else if (!strncmp (*argv, "--", 2)) { fprintf (stderr, PGM ": unknown option '%s'\n", *argv); exit (1); } } if (argc != 1) { fprintf (stderr, PGM ": no or too many URLS given\n"); exit (1); } if (!cafile) cafile = prepend_srcdir ("tls-ca.pem"); if (verbose) my_http_flags |= HTTP_FLAG_LOG_RESP; if (verbose || debug) http_set_verbose (verbose, debug); /* http.c makes use of the assuan socket wrapper. */ assuan_sock_init (); if ((my_http_flags & HTTP_FLAG_FORCE_TOR)) { enable_dns_tormode (1); if (assuan_sock_set_flag (ASSUAN_INVALID_FD, "tor-mode", 1)) { log_error ("error enabling Tor mode: %s\n", strerror (errno)); log_info ("(is your Libassuan recent enough?)\n"); } } #if HTTP_USE_NTBTLS log_info ("new session.\n"); err = http_session_new (&session, NULL, ((no_crl? HTTP_FLAG_NO_CRL : 0) | HTTP_FLAG_TRUST_DEF), my_http_tls_verify_cb, NULL); if (err) log_error ("http_session_new failed: %s\n", gpg_strerror (err)); ntbtls_set_debug (tls_dbg, NULL, NULL); #elif HTTP_USE_GNUTLS rc = gnutls_global_init (); if (rc) log_error ("gnutls_global_init failed: %s\n", gnutls_strerror (rc)); http_register_tls_callback (verify_callback); http_register_tls_ca (cafile); err = http_session_new (&session, NULL, ((no_crl? HTTP_FLAG_NO_CRL : 0) | HTTP_FLAG_TRUST_DEF), NULL, NULL); if (err) log_error ("http_session_new failed: %s\n", gpg_strerror (err)); /* rc = gnutls_dh_params_init(&dh_params); */ /* if (rc) */ /* log_error ("gnutls_dh_params_init failed: %s\n", gnutls_strerror (rc)); */ /* read_dh_params ("dh_param.pem"); */ /* rc = gnutls_certificate_set_x509_trust_file */ /* (certcred, "ca.pem", GNUTLS_X509_FMT_PEM); */ /* if (rc) */ /* log_error ("gnutls_certificate_set_x509_trust_file failed: %s\n", */ /* gnutls_strerror (rc)); */ /* gnutls_certificate_set_dh_params (certcred, dh_params); */ gnutls_global_set_log_function (my_gnutls_log); if (tls_dbg) gnutls_global_set_log_level (tls_dbg); #else (void)err; (void)tls_dbg; (void)no_crl; #endif /*HTTP_USE_GNUTLS*/ rc = http_parse_uri (&uri, *argv, 1); if (rc) { log_error ("'%s': %s\n", *argv, gpg_strerror (rc)); return 1; } printf ("Scheme: %s\n", uri->scheme); if (uri->opaque) printf ("Value : %s\n", uri->path); else { printf ("Auth : %s\n", uri->auth? uri->auth:"[none]"); printf ("Host : %s\n", uri->host); printf ("Port : %u\n", uri->port); printf ("Path : %s\n", uri->path); for (r = uri->params; r; r = r->next) { printf ("Params: %s", r->name); if (!r->no_value) { printf ("=%s", r->value); if (strlen (r->value) != r->valuelen) printf (" [real length=%d]", (int) r->valuelen); } putchar ('\n'); } for (r = uri->query; r; r = r->next) { printf ("Query : %s", r->name); if (!r->no_value) { printf ("=%s", r->value); if (strlen (r->value) != r->valuelen) printf (" [real length=%d]", (int) r->valuelen); } putchar ('\n'); } printf ("Flags :%s%s%s%s\n", uri->is_http? " http":"", uri->opaque? " opaque":"", uri->v6lit? " v6lit":"", uri->onion? " onion":""); printf ("TLS : %s\n", uri->use_tls? "yes": (my_http_flags&HTTP_FLAG_FORCE_TLS)? "forced" : "no"); printf ("Tor : %s\n", (my_http_flags&HTTP_FLAG_FORCE_TOR)? "yes" : "no"); } fflush (stdout); http_release_parsed_uri (uri); uri = NULL; if (session) http_session_set_timeout (session, timeout); rc = http_open_document (NULL, &hd, *argv, NULL, my_http_flags, NULL, session, NULL, NULL); if (rc) { log_error ("can't get '%s': %s\n", *argv, gpg_strerror (rc)); return 1; } log_info ("open_http_document succeeded; status=%u\n", http_get_status_code (hd)); { const char **names; int i; names = http_get_header_names (hd); if (!names) log_fatal ("http_get_header_names failed: %s\n", gpg_strerror (gpg_error_from_syserror ())); for (i = 0; names[i]; i++) printf ("HDR: %s: %s\n", names[i], http_get_header (hd, names[i])); xfree (names); } fflush (stdout); switch (http_get_status_code (hd)) { case 200: case 400: case 401: case 403: case 404: { unsigned long count = 0; while ((c = es_getc (http_get_read_ptr (hd))) != EOF) { count++; if (!no_out) putchar (c); } log_info ("Received bytes: %lu\n", count); } break; case 301: case 302: case 307: log_info ("Redirected to: %s\n", http_get_header (hd, "Location")); break; } http_close (hd, 0); http_session_release (session); #ifdef HTTP_USE_GNUTLS gnutls_global_deinit (); #endif /*HTTP_USE_GNUTLS*/ return 0; }
/* Send an HTTP request. On success returns an estream object at R_FP. HOSTPORTSTR is only used for diagnostics. If HTTPHOST is not NULL it will be used as HTTP "Host" header. If POST_CB is not NULL a post request is used and that callback is called to allow writing the post data. If R_HTTP_STATUS is not NULL, the http status code will be stored there. */ static gpg_error_t send_request (ctrl_t ctrl, const char *request, const char *hostportstr, const char *httphost, unsigned int httpflags, gpg_error_t (*post_cb)(void *, http_t), void *post_cb_value, estream_t *r_fp, unsigned int *r_http_status) { gpg_error_t err; http_session_t session = NULL; http_t http = NULL; int redirects_left = MAX_REDIRECTS; estream_t fp = NULL; char *request_buffer = NULL; parsed_uri_t uri = NULL; int is_onion; *r_fp = NULL; err = http_parse_uri (&uri, request, 0); if (err) goto leave; is_onion = uri->onion; err = http_session_new (&session, httphost, ((ctrl->http_no_crl? HTTP_FLAG_NO_CRL : 0) | HTTP_FLAG_TRUST_DEF), gnupg_http_tls_verify_cb, ctrl); if (err) goto leave; http_session_set_log_cb (session, cert_log_cb); http_session_set_timeout (session, ctrl->timeout); once_more: err = http_open (&http, post_cb? HTTP_REQ_POST : HTTP_REQ_GET, request, httphost, /* fixme: AUTH */ NULL, (httpflags |(opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY:0) |(dirmngr_use_tor ()? HTTP_FLAG_FORCE_TOR:0) |(opt.disable_ipv4? HTTP_FLAG_IGNORE_IPv4 : 0) |(opt.disable_ipv6? HTTP_FLAG_IGNORE_IPv6 : 0)), ctrl->http_proxy, session, NULL, /*FIXME curl->srvtag*/NULL); if (!err) { fp = http_get_write_ptr (http); /* Avoid caches to get the most recent copy of the key. We set both the Pragma and Cache-Control versions of the header, so we're good with both HTTP 1.0 and 1.1. */ es_fputs ("Pragma: no-cache\r\n" "Cache-Control: no-cache\r\n", fp); if (post_cb) err = post_cb (post_cb_value, http); if (!err) { http_start_data (http); if (es_ferror (fp)) err = gpg_error_from_syserror (); } } if (err) { /* Fixme: After a redirection we show the old host name. */ log_error (_("error connecting to '%s': %s\n"), hostportstr, gpg_strerror (err)); goto leave; } /* Wait for the response. */ dirmngr_tick (ctrl); err = http_wait_response (http); if (err) { log_error (_("error reading HTTP response for '%s': %s\n"), hostportstr, gpg_strerror (err)); goto leave; } if (http_get_tls_info (http, NULL)) { /* Update the httpflags so that a redirect won't fallback to an unencrypted connection. */ httpflags |= HTTP_FLAG_FORCE_TLS; } if (r_http_status) *r_http_status = http_get_status_code (http); switch (http_get_status_code (http)) { case 200: err = 0; break; /* Success. */ case 301: case 302: case 307: { const char *s = http_get_header (http, "Location"); log_info (_("URL '%s' redirected to '%s' (%u)\n"), request, s?s:"[none]", http_get_status_code (http)); if (s && *s && redirects_left-- ) { if (is_onion) { /* Make sure that an onion address only redirects to * another onion address. */ http_release_parsed_uri (uri); uri = NULL; err = http_parse_uri (&uri, s, 0); if (err) goto leave; if (! uri->onion) { err = gpg_error (GPG_ERR_FORBIDDEN); goto leave; } } xfree (request_buffer); request_buffer = xtrystrdup (s); if (request_buffer) { request = request_buffer; http_close (http, 0); http = NULL; goto once_more; } err = gpg_error_from_syserror (); } else err = gpg_error (GPG_ERR_NO_DATA); log_error (_("too many redirections\n")); } goto leave; case 501: err = gpg_error (GPG_ERR_NOT_IMPLEMENTED); goto leave; default: log_error (_("error accessing '%s': http status %u\n"), request, http_get_status_code (http)); err = gpg_error (GPG_ERR_NO_DATA); goto leave; } /* FIXME: We should register a permanent redirection and whether a host has ever used TLS so that future calls will always use TLS. */ fp = http_get_read_ptr (http); if (!fp) { err = gpg_error (GPG_ERR_BUG); goto leave; } /* Return the read stream and close the HTTP context. */ *r_fp = fp; http_close (http, 1); http = NULL; leave: http_close (http, 0); http_session_release (session); xfree (request_buffer); http_release_parsed_uri (uri); return err; }
static void work_http( connection* conn ) { int i; virtual_host * host; //check if the connection cannot work. if( conn->state != C_READY ) return; conn->state = C_REQUESTING; http_request( conn ); if( conn->state != C_REQUESTING ) return; //response conn->code = 200; conn->state = C_RESPONSING; /* Check Host and then set root directory. */ host = loop_search( &conn->server->loop_vhost, conn->host, vhost_searcher ); if( !host ){ host = loop_search( &conn->server->loop_vhost, "*", vhost_searcher ); } if( host ){ //read root conn->root_dir = host->root_dir; if( !loop_is_empty( &host->loop_rewrite ) ) loop_search( &host->loop_rewrite, (void*)conn, loop_rewrite_match ); http_parse_uri( conn ); DBG("[%s]%s%s", conn->client->ip_string, conn->host, conn->uri ); _RESPONSE: http_parse_path( conn ); conn->document_type = http_doctype( conn->server, conn->extension ); if( !conn->document_type ){ http_error( conn, 404, "<h1>File not found.</h1>" ); }else if( conn->extension[0] && strstr( conn->server->asp_exts, conn->extension ) ) { //php do ... exec_asp( conn ); }else if( host->proxy && ( !host->proxy_exts[0] || strstr( host->proxy_exts, conn->extension ) ) ) { // uses proxy server proxy_request( conn, host->proxy_ip, host->proxy_port ); }else if( access(conn->full_path, 0)==0 ){ if( is_dir(conn->full_path) ){ char* tmp; NEW( tmp, PATH_LEN+32 ); if( conn->script_name[strlen(conn->script_name)-1] != '/' ){ //Are you sure that script starts with '/'? sprintf( tmp, "http://%s%s/", conn->host, conn->script_name ); http_redirect( conn, tmp ); }else{ if( tmp ){ for( i = 0; i<10; i++ ) { if( !conn->server->default_pages[i][0] ) { i=10; break; } sprintf( tmp, "%s/%s", conn->full_path, conn->server->default_pages[i] ); if( access( tmp, 0 ) == 0 ) { //091004 by Huang Guan. sprintf( conn->script_name, "%s%s", conn->script_name, conn->server->default_pages[i] ); DEL( tmp ); goto _RESPONSE; } } } if( i == 10 ){ // List Directory if( host->list ){ int ret; NEW( conn->data_send, MAX_DATASEND+4 ); strcpy( conn->extension, "html" ); conn->document_type = http_doctype( conn->server, conn->extension ); ret = listdir( conn->data_send, MAX_DATASEND, conn->full_path, conn->script_name ); conn->data_size = ret; }else{ http_error( conn, 403, "<h1>Forbidden</h1>" ); } } } DEL( tmp ); }else{ http_sendfile( conn, conn->full_path ); } }else if( strncmp(conn->current_dir, "/system", 7)==0 && conn->root_dir==host->root_dir ){ strcpy(conn->script_name, conn->script_name+7); conn->root_dir = conn->client->server->root_dir; goto _RESPONSE; }else{ http_error( conn, 404, "<h1>File not found.</h1>" ); } }else{ http_error( conn, 403, "<h1>Unknown host name.</h1>" ); } if( conn->state == C_RESPONSING ) http_response( conn ); conn->requests ++; if( conn->form_data ) DEL( conn->form_data ); if( conn->data_send ) DEL( conn->data_send ); if( conn->session ) conn->session->reference --; conn->session = NULL; //next request if( conn->keep_alive ){ conn->state = C_READY; }else{ conn->state = C_END; } }
int main (int argc, char **argv) { int last_argc = -1; gpg_error_t err; int rc; parsed_uri_t uri; uri_tuple_t r; http_t hd; int c; unsigned int my_http_flags = 0; int no_out = 0; int tls_dbg = 0; const char *cafile = NULL; http_session_t session = NULL; gpgrt_init (); log_set_prefix (PGM, 1 | 4); if (argc) { argc--; argv++; } while (argc && last_argc != argc ) { last_argc = argc; if (!strcmp (*argv, "--")) { argc--; argv++; break; } else if (!strcmp (*argv, "--help")) { fputs ("usage: " PGM " URL\n" "Options:\n" " --verbose print timings etc.\n" " --debug flyswatter\n" " --gnutls-debug N use GNUTLS debug level N\n" " --cacert FNAME expect CA certificate in file FNAME\n" " --no-verify do not verify the certificate\n" " --force-tls use HTTP_FLAG_FORCE_TLS\n" " --no-out do not print the content\n", stdout); exit (0); } else if (!strcmp (*argv, "--verbose")) { verbose++; argc--; argv++; } else if (!strcmp (*argv, "--debug")) { verbose += 2; debug++; argc--; argv++; } else if (!strcmp (*argv, "--gnutls-debug")) { argc--; argv++; if (argc) { tls_dbg = atoi (*argv); argc--; argv++; } } else if (!strcmp (*argv, "--cacert")) { argc--; argv++; if (argc) { cafile = *argv; argc--; argv++; } } else if (!strcmp (*argv, "--no-verify")) { no_verify = 1; argc--; argv++; } else if (!strcmp (*argv, "--force-tls")) { my_http_flags |= HTTP_FLAG_FORCE_TLS; argc--; argv++; } else if (!strcmp (*argv, "--no-out")) { no_out = 1; argc--; argv++; } else if (!strncmp (*argv, "--", 2)) { fprintf (stderr, PGM ": unknown option '%s'\n", *argv); exit (1); } } if (argc != 1) { fprintf (stderr, PGM ": no or too many URLS given\n"); exit (1); } if (!cafile) cafile = prepend_srcdir ("tls-ca.pem"); #if HTTP_USE_NTBTLS (void)err; ntbtls_set_debug (tls_dbg, NULL, NULL); #elif HTTP_USE_GNUTLS rc = gnutls_global_init (); if (rc) log_error ("gnutls_global_init failed: %s\n", gnutls_strerror (rc)); http_register_tls_callback (verify_callback); http_register_tls_ca (cafile); err = http_session_new (&session, NULL); if (err) log_error ("http_session_new failed: %s\n", gpg_strerror (err)); /* rc = gnutls_dh_params_init(&dh_params); */ /* if (rc) */ /* log_error ("gnutls_dh_params_init failed: %s\n", gnutls_strerror (rc)); */ /* read_dh_params ("dh_param.pem"); */ /* rc = gnutls_certificate_set_x509_trust_file */ /* (certcred, "ca.pem", GNUTLS_X509_FMT_PEM); */ /* if (rc) */ /* log_error ("gnutls_certificate_set_x509_trust_file failed: %s\n", */ /* gnutls_strerror (rc)); */ /* gnutls_certificate_set_dh_params (certcred, dh_params); */ gnutls_global_set_log_function (my_gnutls_log); if (tls_dbg) gnutls_global_set_log_level (tls_dbg); #endif /*HTTP_USE_GNUTLS*/ rc = http_parse_uri (&uri, *argv, 1); if (rc) { log_error ("'%s': %s\n", *argv, gpg_strerror (rc)); return 1; } printf ("Scheme: %s\n", uri->scheme); if (uri->opaque) printf ("Value : %s\n", uri->path); else { printf ("Auth : %s\n", uri->auth? uri->auth:"[none]"); printf ("Host : %s\n", uri->host); printf ("Port : %u\n", uri->port); printf ("Path : %s\n", uri->path); for (r = uri->params; r; r = r->next) { printf ("Params: %s", r->name); if (!r->no_value) { printf ("=%s", r->value); if (strlen (r->value) != r->valuelen) printf (" [real length=%d]", (int) r->valuelen); } putchar ('\n'); } for (r = uri->query; r; r = r->next) { printf ("Query : %s", r->name); if (!r->no_value) { printf ("=%s", r->value); if (strlen (r->value) != r->valuelen) printf (" [real length=%d]", (int) r->valuelen); } putchar ('\n'); } printf ("TLS : %s\n", uri->use_tls? "yes": (my_http_flags&HTTP_FLAG_FORCE_TLS)? "forced" : "no"); } fflush (stdout); http_release_parsed_uri (uri); uri = NULL; rc = http_open_document (&hd, *argv, NULL, my_http_flags, NULL, session, NULL, NULL); if (rc) { log_error ("can't get '%s': %s\n", *argv, gpg_strerror (rc)); return 1; } log_info ("open_http_document succeeded; status=%u\n", http_get_status_code (hd)); { const char **names; int i; names = http_get_header_names (hd); if (!names) log_fatal ("http_get_header_names failed: %s\n", gpg_strerror (gpg_error_from_syserror ())); for (i = 0; names[i]; i++) printf ("HDR: %s: %s\n", names[i], http_get_header (hd, names[i])); xfree (names); } fflush (stdout); switch (http_get_status_code (hd)) { case 200: case 400: case 401: case 403: case 404: { unsigned long count = 0; while ((c = es_getc (http_get_read_ptr (hd))) != EOF) { count++; if (!no_out) putchar (c); } log_info ("Received bytes: %lu\n", count); } break; case 301: case 302: case 307: log_info ("Redirected to: %s\n", http_get_header (hd, "Location")); break; } http_close (hd, 0); http_session_release (session); #ifdef HTTP_USE_GNUTLS gnutls_global_deinit (); #endif /*HTTP_USE_GNUTLS*/ return 0; }
void handle_client(int socket) { node *cookie, *param; service cmd; http_method method; http_response resp; int bytes, s, expected_len, header_len; char req[BUFFER_SIZE], buf[BUFFER_SIZE]; const char *path; char *connection, *req_body_len; time_t since_time; /* TODO Loop receiving requests and sending appropriate responses, * until one of the conditions to close the connection is * met. */ cookie = param = resp.expire = resp.cookie = NULL; do { // New request free_list(resp.cookie); free_list(resp.expire); if (cookie) free_list(cookie); if (param) free_list(param); cookie = param = NULL; memset(&resp, 0, sizeof(http_response)); memset(req, 0, BUFFER_SIZE); bytes = 0; // Wait for HTTP header to complete do { bytes += recv(socket, req + bytes, BUFFER_SIZE, 0); header_len = http_header_complete(req, bytes); } while (header_len == -1); // Receive body if there is content length if (strstr(req, HDR_CONTENT_LEN)) { strcpy(buf, req); req_body_len = get_header_value_from_req(buf, HDR_CONTENT_LEN); expected_len = atoi(req_body_len) + header_len; while (bytes < expected_len) { bytes += recv(socket, req + bytes, BUFFER_SIZE, 0); } } // printf("recv %i bytes\n", bytes); // Get HTTP method method = http_parse_method(req); // Get path strcpy(buf, req); path = http_parse_path(http_parse_uri(buf)); // printf("Request: %s\n", path); // Parse cookies if (strstr(req, HDR_COOKIE)) { strcpy(buf, req); cookie = get_cookies_from_header(get_header_value_from_req(buf, HDR_COOKIE)); } else { cookie = NULL; } // Match service command cmd = SERV_UNKNOWN; for (s= 0; s < SERV_UNKNOWN; s++) { if (strncasecmp(path, service_str[s], strlen(service_str[s])) == 0) { cmd = s; break; } } // Handle command switch(cmd) { case SERV_KNOCK: case SERV_LOGIN: case SERV_LOGOUT: case SERV_GETFILE: case SERV_ADDCART: case SERV_DELCART: case SERV_CHECKOUT: if (method == METHOD_GET) { param = get_params_from_query(get_query_str_from_path(path)); if (cmd == SERV_KNOCK) { knock_handler(&resp, cookie); } else if (cmd == SERV_LOGIN) { login_handler(&resp, param); } else if (cmd == SERV_LOGOUT) { logout_handler(&resp, cookie); } else if (cmd == SERV_GETFILE) { since_time = 0; strcpy(buf, req); if (strstr(buf, HDR_IF_MOD_SINCE)) { if (!RFC_822_to_time(strstr(buf, HDR_IF_MOD_SINCE) + strlen(HDR_IF_MOD_SINCE), &since_time)) { since_time = 0; } } getfile_handler(&resp, param, since_time); } else if (cmd == SERV_ADDCART) { addcart_handler(&resp, param, cookie); } else if (cmd == SERV_DELCART) { delcart_handler(&resp, param, cookie); } else if (cmd == SERV_CHECKOUT) { checkout_handler(&resp, cookie); } else { resp.status = NOT_FOUND; } } else { resp.allow = METHOD_GET; resp.status = METHOD_NOT_ALLOWED; } break; case SERV_PUTFILE: if (method == METHOD_POST) { strcpy(buf, req); param = get_params_from_query((char*) http_parse_body(buf, bytes)); putfile_handler(&resp, cookie, param); } else { resp.allow = METHOD_POST; resp.status = METHOD_NOT_ALLOWED; } break; default: resp.status = NOT_FOUND; break; } // Check if status not ok or // client wants to close connection after completing request if (resp.status != OK) { resp.connection = CLOSE; } else if (strstr(req, "Connection:")) { connection = http_parse_header_field(buf, bytes, "Connection"); if (strcmp(connection, "close") == 0) { resp.connection = CLOSE; } } send_response(socket, &resp); } while (resp.connection != CLOSE); }
int main (int argc, char **argv) { gpg_error_t err; int rc; parsed_uri_t uri; uri_tuple_t r; http_t hd; int c; http_session_t session = NULL; gpgrt_init (); log_set_prefix ("t-http", 1 | 4); if (argc != 2) { fprintf (stderr, "usage: t-http uri\n"); return 1; } argc--; argv++; #ifdef HTTP_USE_GNUTLS rc = gnutls_global_init (); if (rc) log_error ("gnutls_global_init failed: %s\n", gnutls_strerror (rc)); http_register_tls_callback (verify_callback); http_register_tls_ca ("tls-ca.pem"); err = http_session_new (&session, NULL); if (err) log_error ("http_session_new failed: %s\n", gpg_strerror (err)); /* rc = gnutls_dh_params_init(&dh_params); */ /* if (rc) */ /* log_error ("gnutls_dh_params_init failed: %s\n", gnutls_strerror (rc)); */ /* read_dh_params ("dh_param.pem"); */ /* rc = gnutls_certificate_set_x509_trust_file */ /* (certcred, "ca.pem", GNUTLS_X509_FMT_PEM); */ /* if (rc) */ /* log_error ("gnutls_certificate_set_x509_trust_file failed: %s\n", */ /* gnutls_strerror (rc)); */ /* gnutls_certificate_set_dh_params (certcred, dh_params); */ gnutls_global_set_log_function (my_gnutls_log); /* gnutls_global_set_log_level (2); */ #endif /*HTTP_USE_GNUTLS*/ rc = http_parse_uri (&uri, *argv, 1); if (rc) { log_error ("'%s': %s\n", *argv, gpg_strerror (rc)); return 1; } printf ("Scheme: %s\n", uri->scheme); if (uri->opaque) printf ("Value : %s\n", uri->path); else { printf ("Auth : %s\n", uri->auth? uri->auth:"[none]"); printf ("Host : %s\n", uri->host); printf ("Port : %u\n", uri->port); printf ("Path : %s\n", uri->path); for (r = uri->params; r; r = r->next) { printf ("Params: %s", r->name); if (!r->no_value) { printf ("=%s", r->value); if (strlen (r->value) != r->valuelen) printf (" [real length=%d]", (int) r->valuelen); } putchar ('\n'); } for (r = uri->query; r; r = r->next) { printf ("Query : %s", r->name); if (!r->no_value) { printf ("=%s", r->value); if (strlen (r->value) != r->valuelen) printf (" [real length=%d]", (int) r->valuelen); } putchar ('\n'); } } http_release_parsed_uri (uri); uri = NULL; rc = http_open_document (&hd, *argv, NULL, 0, NULL, session, NULL, NULL); if (rc) { log_error ("can't get '%s': %s\n", *argv, gpg_strerror (rc)); return 1; } log_info ("open_http_document succeeded; status=%u\n", http_get_status_code (hd)); { const char **names; int i; names = http_get_header_names (hd); if (!names) log_fatal ("http_get_header_names failed: %s\n", gpg_strerror (gpg_error_from_syserror ())); for (i = 0; names[i]; i++) printf ("HDR: %s: %s\n", names[i], http_get_header (hd, names[i])); xfree (names); } switch (http_get_status_code (hd)) { case 200: case 400: case 401: case 403: case 404: while ((c = es_getc (http_get_read_ptr (hd))) != EOF) putchar (c); break; case 301: case 302: printf ("Redirected to '%s'\n", http_get_header (hd, "Location")); break; } http_close (hd, 0); http_session_release (session); #ifdef HTTP_USE_GNUTLS gnutls_global_deinit (); #endif /*HTTP_USE_GNUTLS*/ return 0; }