| 2616 | */ |
| 2617 | |
| 2618 | static char *make_variant_list(request_rec *r, negotiation_state *neg) |
| 2619 | { |
| 2620 | apr_array_header_t *arr; |
| 2621 | int i; |
| 2622 | int max_vlist_array = (neg->avail_vars->nelts * 15) + 2; |
| 2623 | |
| 2624 | /* In order to avoid O(n^2) memory copies in building the list, |
| 2625 | * we preallocate a apr_table_t with the maximum substrings possible, |
| 2626 | * fill it with the variant list, and then concatenate the entire array. |
| 2627 | */ |
| 2628 | arr = apr_array_make(r->pool, max_vlist_array, sizeof(char *)); |
| 2629 | |
| 2630 | *((const char **) apr_array_push(arr)) = "Available variants:\n<ul>\n"; |
| 2631 | |
| 2632 | for (i = 0; i < neg->avail_vars->nelts; ++i) { |
| 2633 | var_rec *variant = &((var_rec *) neg->avail_vars->elts)[i]; |
| 2634 | const char *filename = variant->file_name ? variant->file_name : ""; |
| 2635 | apr_array_header_t *languages = variant->content_languages; |
| 2636 | const char *description = variant->description |
| 2637 | ? variant->description |
| 2638 | : ""; |
| 2639 | |
| 2640 | /* The format isn't very neat, and it would be nice to make |
| 2641 | * the tags human readable (eg replace 'language en' with 'English'). |
| 2642 | * Note that if you change the number of substrings pushed, you also |
| 2643 | * need to change the calculation of max_vlist_array above. |
| 2644 | */ |
| 2645 | *((const char **) apr_array_push(arr)) = "<li><a href=\""; |
| 2646 | *((const char **) apr_array_push(arr)) = ap_escape_path_segment(r->pool, filename); |
| 2647 | *((const char **) apr_array_push(arr)) = "\">"; |
| 2648 | *((const char **) apr_array_push(arr)) = ap_escape_html(r->pool, filename); |
| 2649 | *((const char **) apr_array_push(arr)) = "</a> "; |
| 2650 | *((const char **) apr_array_push(arr)) = description; |
| 2651 | |
| 2652 | if (variant->mime_type && *variant->mime_type) { |
| 2653 | *((const char **) apr_array_push(arr)) = ", type "; |
| 2654 | *((const char **) apr_array_push(arr)) = variant->mime_type; |
| 2655 | } |
| 2656 | if (languages && languages->nelts) { |
| 2657 | *((const char **) apr_array_push(arr)) = ", language "; |
| 2658 | *((const char **) apr_array_push(arr)) = apr_array_pstrcat(r->pool, |
| 2659 | languages, ','); |
| 2660 | } |
| 2661 | if (variant->content_charset && *variant->content_charset) { |
| 2662 | *((const char **) apr_array_push(arr)) = ", charset "; |
| 2663 | *((const char **) apr_array_push(arr)) = variant->content_charset; |
| 2664 | } |
| 2665 | if (variant->content_encoding) { |
| 2666 | *((const char **) apr_array_push(arr)) = ", encoding "; |
| 2667 | *((const char **) apr_array_push(arr)) = variant->content_encoding; |
| 2668 | } |
| 2669 | *((const char **) apr_array_push(arr)) = "</li>\n"; |
| 2670 | } |
| 2671 | *((const char **) apr_array_push(arr)) = "</ul>\n"; |
| 2672 | |
| 2673 | return apr_array_pstrcat(r->pool, arr, '\0'); |
| 2674 | } |
| 2675 |
no test coverage detected