herror_t httpc_mime_begin(httpc_conn_t * conn, const char *url, const char *related_start, const char *related_start_info, const char *related_type) { herror_t status; char buffer[300]; char temp[75]; char boundary[75]; /* Set Content-type Set multipart/related parameter type=..; start=.. ; start-info= ..; boundary=... */ sprintf(buffer, "multipart/related;"); /* using sprintf instead of snprintf because visual c does not support snprintf */ #ifdef WIN32 #define snprintf(buffer, num, s1, s2) sprintf(buffer, s1,s2) #endif if (related_type) { snprintf(temp, 75, " type=\"%s\";", related_type); strcat(buffer, temp); } if (related_start) { snprintf(temp, 75, " start=\"%s\";", related_start); strcat(buffer, temp); } if (related_start_info) { snprintf(temp, 75, " start-info=\"%s\";", related_start_info); strcat(buffer, temp); } _httpc_mime_get_boundary(conn, boundary); snprintf(temp, 75, " boundary=\"%s\"", boundary); strcat(buffer, temp); httpc_set_header(conn, HEADER_CONTENT_TYPE, buffer); status = httpc_post_begin(conn, url); return status; }
/*-------------------------------------------------- FUNCTION: httpc_header_set_date DESC: Adds the current date to the header. ----------------------------------------------------*/ static void httpc_header_set_date(httpc_conn_t * conn) { char buffer[32]; time_t ts; struct tm stm; ts = time(NULL); localtime_r(&ts, &stm); strftime(buffer, 32, "%a, %d %b %Y %H:%M:%S GMT", &stm); httpc_set_header(conn, HEADER_DATE, buffer); return; }
static int _httpc_set_basic_authorization_header(httpc_conn_t *conn, const char *key, const char *user, const char *password) { /* XXX: use malloc/free */ char in[64], out[64]; if (!user) user = ""; if (!password) password = ""; memset(in, 0, 64); memset(out, 0, 64); sprintf(in, "%s:%s", user, password); base64_encode(in, out); sprintf(in, "Basic %s", out); return httpc_set_header(conn, key, in); }
int main(int argc, char **argv) { httpc_conn_t *conn; /* Client connection object */ hresponse_t *res; /* Response object **/ herror_t status; FILE *f; size_t size; char url[50], file[50], id[50], content_type[50]; char buffer[MAX_BUFFER_SIZE+1]; /* Check usage */ if (argc < 5) { fprintf(stderr, "usage %s <url> <file> <id> <content-type>\n", argv[0]); exit(1); } /* Set log level to see more information written by the library */ // log_set_level(NANOHTTP_LOG_VERBOSE); /* Initialize httpc module */ if ((status = httpc_init(argc, argv)) != H_OK) { fprintf(stderr, "Cannot init httpc (%s)\n", herror_message(status)); herror_release(status); return 1; } /* Create the client connection object */ conn = httpc_new(); httpc_set_header(conn, HEADER_TRANSFER_ENCODING, TRANSFER_ENCODING_CHUNKED); /* Open connection for mime */ if ((status = httpc_mime_begin(conn, argv[1], argv[3], "", argv[4])) != H_OK) { fprintf(stderr, "Can not start MIME: %s\n", herror_message(status)); herror_release(status); exit(1); } if (!send_file(conn, argv[2], argv[3], argv[4])) { fprintf(stderr, "send_file failed\n"); exit(1); } while (1) { printf("Enter filename ['.' for finish]: "); gets(file); if (!strcmp(file, ".")) break; printf("Enter part id:"); gets(id); printf("Enter content-type:"); gets(content_type); if (!send_file(conn, file, id, content_type)) exit(1); } if ((status = httpc_mime_end(conn, &res)) != H_OK) { fprintf(stderr, "httpc_mime_end failed (%s)\n", herror_message(status)); herror_release(status); exit(1); } /* Show response */ show_response(res); /* clean up*/ hresponse_free(res); httpc_free(conn); return 0; }
/*-------------------------------------------------- FUNCTION: httpc_talk_to_server DESC: This function is the heart of the httpc module. It will send the request and process the response. Here the parameters: method: the request method. This can be HTTP_REQUEST_POST and HTTP_REQUEST_GET. conn: the connection object (created with httpc_new()) urlstr: the complete url in string format. http://<host>:<port>/<context> where <port> is not mendatory. start_cb: a callback function, which will be called when the response header is completely arrives. cb: a callback function, which will be called everytime when data arrives. content_size: size of content to send. (only if method is HTTP_REQUEST_POST) content: the content data to send. (only if method is HTTP_REQUEST_POST) userdata: a user define data, which will be passed to the start_cb and cb callbacks as a parameter. This can also be NULL. If success, this function will return 0. >0 otherwise. ----------------------------------------------------*/ static herror_t httpc_talk_to_server(hreq_method_t method, httpc_conn_t * conn, const char *urlstr) { hurl_t url; char buffer[4096]; herror_t status; int ssl; if (conn == NULL) { return herror_new("httpc_talk_to_server", GENERAL_INVALID_PARAM, "httpc_conn_t param is NULL"); } /* Build request header */ httpc_header_set_date(conn); if ((status = hurl_parse(&url, urlstr)) != H_OK) { log_error2("Can not parse URL '%s'", SAVE_STR(urlstr)); return status; } /* TODO (#1#): Check for HTTP protocol in URL */ /* Set hostname */ httpc_set_header(conn, HEADER_HOST, url.host); ssl = url.protocol == PROTOCOL_HTTPS ? 1 : 0; /* Open connection */ if ((status = hsocket_open(&conn->sock, url.host, url.port, ssl)) != H_OK) return status; switch(method) { case HTTP_REQUEST_GET: sprintf(buffer, "GET %s HTTP/%s\r\n", (url.context[0] != '\0') ? url.context : ("/"), (conn->version == HTTP_1_0) ? "1.0" : "1.1"); break; case HTTP_REQUEST_POST: sprintf(buffer, "POST %s HTTP/%s\r\n", (url.context[0] != '\0') ? url.context : ("/"), (conn->version == HTTP_1_0) ? "1.0" : "1.1"); break; default: log_error1("Unknown method type!"); return herror_new("httpc_talk_to_server", GENERAL_INVALID_PARAM, "hreq_method_t must be HTTP_REQUEST_GET or HTTP_REQUEST_POST"); } log_verbose1("Sending request..."); if ((status = hsocket_send(&(conn->sock), buffer)) != H_OK) { log_error2("Cannot send request (%s)", herror_message(status)); hsocket_close(&(conn->sock)); return status; } log_verbose1("Sending header..."); if ((status = httpc_send_header(conn)) != H_OK) { log_error2("Cannot send header (%s)", herror_message(status)); hsocket_close(&(conn->sock)); return status; } return H_OK; }