/* See content-disposition.h for documentation */ nserror http_parse_content_disposition(const char *header_value, http_content_disposition **result) { const char *pos = header_value; lwc_string *mtype; http_parameter *params = NULL; http_content_disposition *cd; nserror error; /* disposition-type *( ";" parameter ) */ http__skip_LWS(&pos); error = http__parse_token(&pos, &mtype); if (error != NSERROR_OK) return error; http__skip_LWS(&pos); if (*pos == ';') { error = http__item_list_parse(&pos, http__parse_parameter, NULL, ¶ms); if (error != NSERROR_OK && error != NSERROR_NOT_FOUND) { lwc_string_unref(mtype); return error; } } cd = malloc(sizeof(*cd)); if (cd == NULL) { http_parameter_list_destroy(params); lwc_string_unref(mtype); return NSERROR_NOMEM; } cd->disposition_type = mtype; cd->parameters = params; *result = cd; return NSERROR_OK; }
/** * Process fetch headers for a download context. * Extracts MIME type, total length, and creates gui_download_window * * \param ctx Context to process * \return NSERROR_OK on success, appropriate error otherwise */ static nserror download_context_process_headers(download_context *ctx) { const char *http_header; char *mime_type; http_parameter *params; unsigned long length; nserror error; /* Retrieve and parse Content-Type */ http_header = llcache_handle_get_header(ctx->llcache, "Content-Type"); if (http_header == NULL) http_header = "text/plain"; error = http_parse_content_type(http_header, &mime_type, ¶ms); if (error != NSERROR_OK) return error; /* Don't care about parameters */ http_parameter_list_destroy(params); /* Retrieve and parse Content-Length */ http_header = llcache_handle_get_header(ctx->llcache, "Content-Length"); if (http_header == NULL) length = 0; else length = strtoul(http_header, NULL, 10); ctx->mime_type = mime_type; ctx->total_length = length; /* Create the frontend window */ ctx->window = gui_download_window_create(ctx, ctx->parent); if (ctx->window == NULL) { free(ctx->mime_type); ctx->mime_type = NULL; return NSERROR_NOMEM; } return NSERROR_OK; }
/* See http.h for documentation */ nserror http_parse_content_type(const char *header_value, char **media_type, http_parameter **parameters) { const char *pos = header_value; char *type; char *subtype = NULL; http_parameter *params = NULL; char *mime; size_t mime_len; nserror error; /* type "/" subtype *( ";" parameter ) */ while (*pos == ' ' || *pos == '\t') pos++; error = http_parse_token(&pos, &type); if (error != NSERROR_OK) return error; while (*pos == ' ' || *pos == '\t') pos++; if (*pos == '/') { pos++; while (*pos == ' ' || *pos == '\t') pos++; error = http_parse_token(&pos, &subtype); if (error != NSERROR_OK) { free(type); return error; } while (*pos == ' ' || *pos == '\t') pos++; if (*pos == ';') { pos++; while (*pos == ' ' || *pos == '\t') pos++; error = http_parse_parameter_list(&pos, ¶ms); if (error != NSERROR_OK) { free(subtype); free(type); return error; } } } /* <type> + <subtype> + '/' */ mime_len = strlen(type) + (subtype != NULL ? strlen(subtype) : 0) + 1; mime = malloc(mime_len + 1); if (mime == NULL) { http_parameter_list_destroy(params); free(subtype); free(type); return NSERROR_OK; } sprintf(mime, "%s/%s", type, subtype != NULL ? subtype : ""); free(subtype); free(type); *media_type = mime; *parameters = params; return NSERROR_OK; }
/* See content-disposition.h for documentation */ void http_content_disposition_destroy(http_content_disposition *victim) { lwc_string_unref(victim->disposition_type); http_parameter_list_destroy(victim->parameters); free(victim); }
/* See content-type.h for documentation */ nserror http_parse_content_type(const char *header_value, http_content_type **result) { const char *pos = header_value; lwc_string *type; lwc_string *subtype = NULL; http_parameter *params = NULL; char *mime; size_t mime_len; lwc_string *imime; http_content_type *ct; nserror error; /* type "/" subtype *( ";" parameter ) */ http__skip_LWS(&pos); error = http__parse_token(&pos, &type); if (error != NSERROR_OK) return error; http__skip_LWS(&pos); if (*pos != '/') { lwc_string_unref(type); return NSERROR_NOT_FOUND; } pos++; http__skip_LWS(&pos); error = http__parse_token(&pos, &subtype); if (error != NSERROR_OK) { lwc_string_unref(type); return error; } http__skip_LWS(&pos); if (*pos == ';') { error = http__item_list_parse(&pos, http__parse_parameter, NULL, ¶ms); if (error != NSERROR_OK && error != NSERROR_NOT_FOUND) { lwc_string_unref(subtype); lwc_string_unref(type); return error; } } /* <type> + <subtype> + '/' */ mime_len = lwc_string_length(type) + lwc_string_length(subtype) + 1; mime = malloc(mime_len + 1); if (mime == NULL) { http_parameter_list_destroy(params); lwc_string_unref(subtype); lwc_string_unref(type); return NSERROR_NOMEM; } sprintf(mime, "%.*s/%.*s", (int) lwc_string_length(type), lwc_string_data(type), (int) lwc_string_length(subtype), lwc_string_data(subtype)); lwc_string_unref(subtype); lwc_string_unref(type); if (lwc_intern_string(mime, mime_len, &imime) != lwc_error_ok) { http_parameter_list_destroy(params); free(mime); return NSERROR_NOMEM; } free(mime); ct = malloc(sizeof(*ct)); if (ct == NULL) { lwc_string_unref(imime); http_parameter_list_destroy(params); return NSERROR_NOMEM; } ct->media_type = imime; ct->parameters = params; *result = ct; return NSERROR_OK; }
/* See content-type.h for documentation */ void http_content_type_destroy(http_content_type *victim) { lwc_string_unref(victim->media_type); http_parameter_list_destroy(victim->parameters); free(victim); }