http_negotiate: do not delegate GSSAPI credentials
[elinks.git] / src / protocol / http / codes.c
blobc4a260fbc48f955661b97454c12e03696b1c59cf
1 /* HTTP response codes */
3 #ifndef _GNU_SOURCE
4 #define _GNU_SOURCE /* Needed for asprintf() */
5 #endif
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
11 #include "elinks.h"
13 #include "cache/cache.h"
14 #include "intl/gettext/libintl.h"
15 #include "network/connection.h"
16 #include "protocol/http/codes.h"
17 #include "protocol/uri.h"
18 #include "session/session.h"
19 #include "session/task.h"
20 #include "terminal/terminal.h"
21 #include "terminal/window.h"
22 #include "util/snprintf.h"
23 #include "viewer/text/draw.h"
26 struct http_code {
27 int num;
28 const unsigned char *str;
31 /* Source: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html */
32 static const struct http_code http_code[] = {
33 { 100, "Continue" },
34 { 101, "Switching Protocols" },
35 { 200, "OK" },
36 { 201, "Created" },
37 { 202, "Accepted" },
38 { 203, "Non-Authoritative Information" },
39 { 204, "No Content" },
40 { 205, "Reset Content" },
41 { 206, "Partial Content" },
42 { 300, "Multiple Choices" },
43 { 301, "Moved Permanently" },
44 { 302, "Found" },
45 { 303, "See Other" },
46 { 304, "Not Modified" },
47 { 305, "Use Proxy" },
48 { 306, "(Unused)" },
49 { 307, "Temporary Redirect" },
50 { 400, "Bad Request" },
51 { 401, "Unauthorized" },
52 { 402, "Payment Required" },
53 { 403, "Forbidden" },
54 { 404, "Not Found" },
55 { 405, "Method Not Allowed" },
56 { 406, "Not Acceptable" },
57 { 407, "Proxy Authentication Required" },
58 { 408, "Request Timeout" },
59 { 409, "Conflict" },
60 { 410, "Gone" },
61 { 411, "Length Required" },
62 { 412, "Precondition Failed" },
63 { 413, "Request Entity Too Large" },
64 { 414, "Request-URI Too Long" },
65 { 415, "Unsupported Media Type" },
66 { 416, "Requested Range Not Satisfiable" },
67 { 417, "Expectation Failed" },
68 { 500, "Internal Server Error" },
69 { 501, "Not Implemented" },
70 { 502, "Bad Gateway" },
71 { 503, "Service Unavailable" },
72 { 504, "Gateway Timeout" },
73 { 505, "HTTP Version Not Supported" },
76 static int
77 compare_http_codes(const void *key, const void *element)
79 int first = (long) key;
80 int second = ((const struct http_code *) element)->num;
82 return first - second;
85 static const unsigned char *
86 http_code_to_string(int code)
88 const struct http_code *element
89 = bsearch((void *) (long) code, http_code,
90 sizeof_array(http_code),
91 sizeof(*element),
92 compare_http_codes);
94 if (element) return element->str;
96 return NULL;
100 /* TODO: Some short intermediate document for the 3xx messages? --pasky */
101 static unsigned char *
102 get_http_error_document(struct terminal *term, struct uri *uri, int code)
104 const unsigned char *codestr = http_code_to_string(code);
105 unsigned char *title = asprintfa(_("HTTP error %03d", term), code);
106 struct string string;
108 if (!codestr) codestr = "Unknown error";
110 if (!init_string(&string)) {
111 mem_free_if(title);
112 return NULL;
115 add_format_to_string(&string,
116 "<html>\n"
117 " <head><title>%s</title></head>\n"
118 " <body>\n"
119 " <h1 align=\"left\">%s: %s</h1>\n"
120 #ifndef CONFIG_SMALL
121 " <hr />\n"
122 " <p>\n"
123 #endif
124 , title, title, codestr);
126 #ifndef CONFIG_SMALL
127 add_format_to_string(&string, _(
128 " An error occurred on the server while fetching the document you\n"
129 " requested. However, the server did not send back any explanation of what\n"
130 " happened, so it is unknown what went wrong. Please contact the web\n"
131 " server administrator about this, if you believe that this error should\n"
132 " not occur since it is not a nice behaviour from the web server at all\n"
133 " and indicates that there is some much deeper problem with the web server\n"
134 " software.\n",
135 term));
137 add_format_to_string(&string,
138 " </p>\n"
139 " <p>\n"
140 " URI: <a href=\"%s\">%s</a>\n", struri(uri), struri(uri));
141 #endif
142 add_format_to_string(&string,
143 #ifndef CONFIG_SMALL
144 " </p>\n"
145 " <hr />\n"
146 #endif
147 " </body>\n"
148 "</html>\n");
150 mem_free_if(title);
152 return string.source;
155 struct http_error_info {
156 int code;
157 struct uri *uri;
160 static void
161 show_http_error_document(struct session *ses, void *data)
163 struct http_error_info *info = data;
164 struct terminal *term = ses->tab->term;
165 struct cache_entry *cached = find_in_cache(info->uri);
166 struct cache_entry *cache = cached ? cached : get_cache_entry(info->uri);
167 unsigned char *str = NULL;
169 if (cache) str = get_http_error_document(term, info->uri, info->code);
171 if (str) {
172 /* The codepage that _("foo", term) used when it was
173 * called by get_http_error_document. */
174 const int gettext_codepage = get_terminal_codepage(term);
176 if (cached) delete_entry_content(cache);
178 /* If we run out of memory here, it's perhaps better
179 * to display a malformatted error message than none
180 * at all. */
181 mem_free_set(&cache->content_type, stracpy("text/html"));
182 mem_free_set(&cache->head,
183 straconcat("\r\nContent-Type: text/html; charset=",
184 get_cp_mime_name(gettext_codepage),
185 "\r\n", (unsigned char *) NULL));
186 add_fragment(cache, 0, str, strlen(str));
187 mem_free(str);
189 draw_formatted(ses, 1);
192 done_uri(info->uri);
193 mem_free(info);
197 void
198 http_error_document(struct connection *conn, int code)
200 struct http_error_info *info;
202 assert(conn && conn->uri);
204 info = mem_calloc(1, sizeof(*info));
205 if (!info) return;
207 info->code = code;
208 info->uri = get_uri_reference(conn->uri);
210 add_questions_entry(show_http_error_document, info);