Annotation of libwww/Library/src/HTDialog.c, revision 2.24
2.1 frystyk 1: /* HTDialog.c
2: ** MESSAGES AND DIALOGS
3: **
4: ** (c) COPYRIGHT MIT 1995.
5: ** Please first read the full copyright statement in the file COPYRIGH.
2.24 ! frystyk 6: ** @(#) $Id: HTDialog.c,v 2.23 1996/08/24 18:09:49 frystyk Exp $
2.1 frystyk 7: **
8: ** This module provides a default implementation of the application part
9: ** of the Message and Dialog part or the Library. You do not have to do
10: ** it like this - you can use exactly the model for mapping codes into
11: ** messages as you like
12: **
13: ** Authors
14: ** HFN Henrik Frystyk
15: */
16:
17: /* Library include files */
18: #include "WWWLib.h"
19: #include "WWWApp.h"
2.6 frystyk 20: #include "WWWHTTP.h"
2.1 frystyk 21: #include "HTDialog.h" /* Implemented here */
22:
23: /*
24: ** Dialog Messages
25: */
2.18 frystyk 26: PRIVATE const char * HTDialogs[HT_MSG_ELEMENTS] = {
2.1 frystyk 27: "Please enter username:",
2.20 frystyk 28: "Please enter username for proxy authentication:",
2.21 frystyk 29: "Please enter username for this FTP server:",
2.1 frystyk 30: "Password:",
31: "Please give name of file to save in:",
32: "Plase enter account:",
2.19 frystyk 33: "You might not be allowed to use this method here, continue?",
2.1 frystyk 34: "Location has moved, continue?",
2.17 frystyk 35: "A new set of rules is to be added to your setup - continue?",
36: "This file already exists - replace existing file?",
2.18 frystyk 37: "Authentication failed - retry?",
2.19 frystyk 38: "Proxy authentication failed - retry?",
2.18 frystyk 39: "This method has already been performed - repeat operation?",
40: "This document is very big - continue operation?",
41: "The source document for this operation has moved - continue operation with new location?",
42: "The destination document for this operation has moved - continue operation with new location?",
2.19 frystyk 43: "A redirection may change the behavior of this method - proceed anyway?"
2.1 frystyk 44: };
45:
46: /*
47: ** All errors that are not strictly HTTP errors but originates from, e.g.,
48: ** the FTP protocol all have element numbers > HTERR_HTTP_CODES_END, i.e.,
49: ** they should be placed after the blank line
50: */
51: typedef struct _HTErrorMessage {
52: int code; /* Error number */
53: char * msg; /* Short explanation */
54: char * url; /* Explaning URL */
55: } HTErrorMessage;
56:
57: PRIVATE HTErrorMessage HTErrors[HTERR_ELEMENTS] = {
58:
59: /* CODE ERROR MESSAGE ERROR URL */
60:
2.15 frystyk 61: { 100, "Continue", "information" },
62: { 101, "Switching Protocols", "information" },
63: { 200, "OK", "success" },
64: { 201, "Created", "success" },
65: { 202, "Accepted", "success" },
66: { 203, "Non-authoritative Information", "success" },
67: { 204, "No Content", "success" },
68: { 205, "Reset Content", "success" },
69: { 206, "Partial Content", "success" },
70: { 300, "Multiple Choices", "redirection" },
71: { 301, "Moved Permanently", "redirection" },
72: { 302, "Moved Temporarily", "redirection" },
73: { 303, "See Other", "redirection" },
74: { 304, "Not Modified", "redirection" },
75: { 305, "Use Proxy", "redirection" },
76: { 400, "Bad Request", "client_error" },
77: { 401, "Unauthorized", "client_error" },
78: { 402, "Payment Required", "client_error" },
79: { 403, "Forbidden", "client_error" },
80: { 404, "Not Found", "client_error" },
81: { 405, "Method Not Allowed", "client_error" },
82: { 406, "Not Acceptable", "client_error" },
83: { 407, "Proxy Authentication Required", "client_error" },
84: { 408, "Request Timeout", "client_error" },
85: { 409, "Conflict", "client_error" },
86: { 410, "Gone", "client_error" },
87: { 411, "Length Required", "client_error" },
88: { 412, "Precondition Failed", "client_error" },
89: { 413, "Request Entity Too Large", "client_error" },
90: { 414, "Request-URI Too Large", "client_error" },
91: { 415, "Unsupported Media Type", "client_error" },
92: { 500, "Internal Server Error", "server_error" },
93: { 501, "Not Implemented", "server_error" },
94: { 502, "Bad Gateway", "server_error" },
95: { 503, "Service Unavailable", "server_error" },
96: { 504, "Gateway Timeout", "server_error" },
97: { 505, "HTTP Version not supported", "server_error" },
98:
99: /* Cache Warnings */
100: { 10, "Response is Stale", "cache" },
101: { 11, "Revalidation Failed", "cache" },
102: { 12, "Disconnected Opeartion", "cache" },
103: { 13, "Heuristic Expiration", "cache" },
104: { 14, "Transformation Applied", "cache" },
105: { 99, "Cache warning", "cache" },
106:
107: /* Non-HTTP Error codes and warnings */
108: { 0, "Can't locate remote host", "internal" },
109: { 0, "No host name found", "internal" },
110: { 0, "No file name found or file not accessible", "internal" },
111: { 0, "FTP-server replies", "internal" },
112: { 0, "FTP-server doesn't reply", "internal" },
113: { 0, "Server timed out", "internal" },
114: { 0, "Gopher-server replies", "internal" },
115: { 0, "Data transfer interrupted", "internal" },
116: { 0, "Connection establishment interrupted", "internal" },
117: { 0, "CSO-server replies", "internal" },
118: { 0, "This is probably a HTTP server 0.9 or less","internal" },
119: { 0, "Bad, Incomplete, or Unknown Response", "internal" },
120: { 0, "Unknown access authentication scheme", "internal" },
121: { 0, "News-server replies", "internal" },
122: { 0, "Trying `ftp://' instead of `file://'", "internal" },
123: { 0, "Too many redirections", "internal" },
2.16 frystyk 124: { 0, "Method not suited for automatic redirection","internal" },
2.15 frystyk 125: { 0, "Premature End Of File", "internal" },
126: { 0, "Response from WAIS Server too Large - Extra lines ignored","internal"},
127: { 0, "WAIS-server doesn't return any data", "internal" },
128: { 0, "Can't connect to WAIS-server", "internal" },
129: { 0, "System replies", "internal" },
130: { 0, "Wrong or unknown access scheme", "internal" },
131: { 0, "Access scheme not allowed in this context", "internal" },
2.23 frystyk 132: { 0, "When you are connected, you can log in", "internal" },
133: { 0, "This version has expired and will be automatically reloaded", "internal" }
2.1 frystyk 134: };
135:
136: /* ------------------------------------------------------------------------- */
137:
138: PUBLIC BOOL HTProgress (HTRequest * request, HTAlertOpcode op,
2.10 frystyk 139: int msgnum, const char * dfault, void * input,
2.1 frystyk 140: HTAlertPar * reply)
141: {
2.24 ! frystyk 142: if (request && HTRequest_internal(request)) return NO;
2.1 frystyk 143: switch (op) {
144: case HT_PROG_DNS:
2.9 frystyk 145: HTTrace("Looking up %s\n", input ? (char *) input : "");
2.1 frystyk 146: break;
147:
148: case HT_PROG_CONNECT:
2.9 frystyk 149: HTTrace("Contacting %s\n", input ? (char *) input : "");
2.1 frystyk 150: break;
151:
152: case HT_PROG_ACCEPT:
2.8 eric 153: HTTrace("Waiting for connection...\n");
2.1 frystyk 154: break;
155:
156: case HT_PROG_READ:
2.24 ! frystyk 157: if (request) {
2.1 frystyk 158: long cl = HTAnchor_length(HTRequest_anchor(request));
159: if (cl > 0) {
160: long b_read = HTRequest_bytesRead(request);
161: double pro = (double) b_read/cl*100;
162: char buf[10];
163: HTNumToStr((unsigned long) cl, buf, 10);
2.8 eric 164: HTTrace("Read (%d%% of %s)\n", (int) pro, buf);
2.1 frystyk 165: } else
2.8 eric 166: HTTrace("Reading...\n");
2.1 frystyk 167: }
168: break;
169:
170: case HT_PROG_WRITE:
2.24 ! frystyk 171: if (request && HTMethod_hasEntity(HTRequest_method(request))) {
2.4 frystyk 172: HTParentAnchor *anchor=HTRequest_anchor(HTRequest_source(request));
173: long cl = HTAnchor_length(anchor);
174: if (cl > 0) {
175: long b_write = HTRequest_bytesWritten(request);
176: double pro = (double) b_write/cl*100;
177: char buf[10];
178: HTNumToStr((unsigned long) cl, buf, 10);
2.8 eric 179: HTTrace("Written (%d%% of %s)\n", (int) pro, buf);
2.4 frystyk 180: } else
2.8 eric 181: HTTrace("Writing...\n");
2.4 frystyk 182: }
2.1 frystyk 183: break;
184:
185: case HT_PROG_DONE:
2.22 frystyk 186: HTTrace("Connection closed\n");
2.1 frystyk 187: break;
188:
189: case HT_PROG_WAIT:
2.12 frystyk 190: HTTrace("Waiting for free socket...\n");
2.24 ! frystyk 191: break;
! 192:
! 193: case HT_PROG_GC:
! 194: HTTrace("Garbage colleting persistent cache - please wait...\n");
2.1 frystyk 195: break;
196:
197: default:
2.8 eric 198: HTTrace("UNKNOWN PROGRESS STATE\n");
2.1 frystyk 199: break;
200: }
201: return YES;
202: }
203:
204: PUBLIC BOOL HTConfirm (HTRequest * request, HTAlertOpcode op,
2.10 frystyk 205: int msgnum, const char * dfault, void * input,
2.1 frystyk 206: HTAlertPar * reply)
207: {
208: char response[4]; /* One more for terminating NULL -- AL */
2.8 eric 209: HTTrace("%s", HTDialogs[msgnum]);
210: if (input) HTTrace(" (%s)", (char *) input);
211: HTTrace(" (y/n) ");
2.1 frystyk 212: #ifndef NO_STDIO
2.2 frystyk 213: if (fgets(response, 4, stdin)) /* get reply, max 3 chars */
2.1 frystyk 214: #endif
2.2 frystyk 215: {
2.1 frystyk 216: char *ptr = response;
217: while (*ptr) {
218: if (*ptr == '\n') {
219: *ptr = '\0';
220: break;
221: }
222: *ptr = TOUPPER(*ptr);
223: ptr++;
224: }
225: return (!strcmp(response, "YES") || !strcmp(response, "Y")) ? YES : NO;
226: }
227: return NO;
228: }
229:
230: /* Prompt for answer and get text back. Reply text is either NULL on
2.10 frystyk 231: ** error or a dynamic string which the caller must HT_FREE.
2.1 frystyk 232: */
233: PUBLIC BOOL HTPrompt (HTRequest * request, HTAlertOpcode op,
2.10 frystyk 234: int msgnum, const char * dfault, void * input,
2.1 frystyk 235: HTAlertPar * reply)
236: {
2.8 eric 237: HTTrace("%s ", HTDialogs[msgnum]);
238: if (input) HTTrace(" (%s) ", (char *) input);
239: if (dfault) HTTrace("(RETURN for [%s]) ", (char *) dfault);
2.1 frystyk 240: if (reply && msgnum>=0) {
241: #ifndef NO_STDIO
2.5 frystyk 242: char buffer[200];
2.1 frystyk 243: if (!fgets(buffer, 200, stdin)) return NO;
244: buffer[strlen(buffer)-1] = '\0'; /* Overwrite newline */
245: if (*buffer)
246: HTAlert_setReplyMessage(reply, buffer);
247: else if (dfault)
248: HTAlert_setReplyMessage(reply, (char *) dfault);
249: else
250: return NO;
251: return YES;
252: #endif
253: }
254: return NO;
255: }
256:
257: /* Prompt for password without echoing the reply. Reply text is
2.10 frystyk 258: ** either NULL on error or a dynamic string which the caller must HT_FREE.
2.1 frystyk 259: */
260: PUBLIC BOOL HTPromptPassword (HTRequest * request, HTAlertOpcode op,
2.10 frystyk 261: int msgnum, const char * dfault, void * input,
2.1 frystyk 262: HTAlertPar * reply)
263: {
264: if (reply && msgnum>=0) {
2.10 frystyk 265: #ifdef HAVE_GETPASS
2.1 frystyk 266: char * pw = (char *) getpass(HTDialogs[msgnum]);
2.2 frystyk 267: if (pw) HTAlert_setReplySecret(reply, pw);
2.1 frystyk 268: return YES;
2.10 frystyk 269: #else
2.11 eric 270: return NO; /* needed for WWW_MSWINDOWS */
2.10 frystyk 271: #endif /* HAVE_GETPASS */
2.1 frystyk 272: }
273: return NO;
274: }
275:
276: /* Username and password
277: ** ---------------------
278: ** Prompt Username and password as an atomic operation
279: */
280: PUBLIC BOOL HTPromptUsernameAndPassword (HTRequest * request, HTAlertOpcode op,
2.10 frystyk 281: int msgnum, const char * dfault,
2.1 frystyk 282: void * input, HTAlertPar * reply)
283: {
2.21 frystyk 284: BOOL status = HTPrompt(request, op, msgnum, dfault, input, reply);
2.1 frystyk 285: return status ?
286: HTPromptPassword(request, op, HT_MSG_PW, dfault, input, reply) : NO;
287: }
288:
289: /* HTError_print
290: ** -------------
291: ** Default function that creates an error message using HTAlert() to
292: ** put out the contents of the error_stack messages. Furthermore, the
293: ** error_info structure contains a name of a help file that might be put
294: ** up as a link. This file can then be multi-linguistic.
295: */
296: PUBLIC BOOL HTError_print (HTRequest * request, HTAlertOpcode op,
2.10 frystyk 297: int msgnum, const char * dfault, void * input,
2.1 frystyk 298: HTAlertPar * reply)
299: {
300: HTList *cur = (HTList *) input;
301: HTError *pres;
302: HTErrorShow showmask = HTError_show();
303: HTChunk *msg = NULL;
304: int code;
2.8 eric 305: if (WWWTRACE) HTTrace("HTError..... Generating message\n");
2.1 frystyk 306: if (!request || !cur) return NO;
307: while ((pres = (HTError *) HTList_nextObject(cur))) {
308: int index = HTError_index(pres);
309: if (HTError_doShow(pres)) {
310: if (!msg) {
311: HTSeverity severity = HTError_severity(pres);
2.3 frystyk 312: msg = HTChunk_new(128);
2.1 frystyk 313: if (severity == ERR_WARN)
2.3 frystyk 314: HTChunk_puts(msg, "Warning: ");
2.1 frystyk 315: else if (severity == ERR_NON_FATAL)
2.3 frystyk 316: HTChunk_puts(msg, "Non Fatal Error: ");
2.1 frystyk 317: else if (severity == ERR_FATAL)
2.3 frystyk 318: HTChunk_puts(msg, "Fatal Error: ");
2.1 frystyk 319: else if (severity == ERR_INFO)
2.3 frystyk 320: HTChunk_puts(msg, "Information: ");
2.1 frystyk 321: else {
322: if (WWWTRACE)
2.8 eric 323: HTTrace("HTError..... Unknown Classification of Error (%d)...\n", severity);
2.3 frystyk 324: HTChunk_delete(msg);
2.1 frystyk 325: return NO;
326: }
327:
328: /* Error number */
329: if ((code = HTErrors[index].code) > 0) {
330: char buf[10];
331: sprintf(buf, "%d ", code);
2.3 frystyk 332: HTChunk_puts(msg, buf);
2.1 frystyk 333: }
334: } else
2.3 frystyk 335: HTChunk_puts(msg, "\nReason: ");
336: HTChunk_puts(msg, HTErrors[index].msg); /* Error message */
2.1 frystyk 337:
338: if (showmask & HT_ERR_SHOW_PARS) { /* Error parameters */
339: int length;
340: int cnt;
341: char *pars = (char *) HTError_parameter(pres, &length);
342: if (length && pars) {
2.3 frystyk 343: HTChunk_puts(msg, " (");
2.1 frystyk 344: for (cnt=0; cnt<length; cnt++) {
345: char ch = *(pars+cnt);
346: if (ch < 0x20 || ch >= 0x7F)
2.3 frystyk 347: HTChunk_putc(msg, '#');
2.1 frystyk 348: else
2.3 frystyk 349: HTChunk_putc(msg, ch);
2.1 frystyk 350: }
2.3 frystyk 351: HTChunk_puts(msg, ") ");
2.1 frystyk 352: }
353: }
354:
355: if (showmask & HT_ERR_SHOW_LOCATION) { /* Error Location */
2.3 frystyk 356: HTChunk_puts(msg, "This occured in ");
357: HTChunk_puts(msg, HTError_location(pres));
358: HTChunk_putc(msg, '\n');
2.1 frystyk 359: }
360:
361: /*
362: ** Make sure that we don't get this error more than once even
363: ** if we are keeping the error stack from one request to another
364: */
365: HTError_setIgnore(pres);
366:
367: /* If we only are show the most recent entry then break here */
368: if (showmask & HT_ERR_SHOW_FIRST)
369: break;
370: }
371: }
372: if (msg) {
2.3 frystyk 373: HTChunk_putc(msg, '\n');
2.8 eric 374: HTTrace("WARNING: %s\n", HTChunk_data(msg));
2.3 frystyk 375: HTChunk_delete(msg);
2.1 frystyk 376: }
377: return YES;
378: }
379:
2.6 frystyk 380: /* HTError_response
381: ** ----------------
382: ** Default function that creates an error message using HTAlert() to
383: ** put out the contents of the error_stack messages. Furthermore, the
384: ** error_info structure contains a name of a help file that might be put
385: ** up as a link. This file can then be multi-linguistic.
386: */
387: PUBLIC BOOL HTError_response (HTRequest * request, HTAlertOpcode op,
2.10 frystyk 388: int msgnum, const char * dfault, void * input,
2.6 frystyk 389: HTAlertPar * reply)
390: {
391: HTList * cur = (HTList *) input;
392: HTError * pres;
393: HTErrorShow showmask = HTError_show();
394: HTChunk * msg = NULL;
395: int code;
2.8 eric 396: if (WWWTRACE) HTTrace("HTError..... Generating HTTP response\n");
2.6 frystyk 397: if (!request || !cur || !reply) return NO;
398: while ((pres = (HTError *) HTList_nextObject(cur))) {
399: int index = HTError_index(pres);
400: if (HTError_doShow(pres)) {
401: if (!msg) {
402: msg = HTChunk_new(128);
403: if ((code = HTErrors[index].code) > 0) {
404: char * reason = HTErrors[index].msg;
2.7 frystyk 405: char * buf;
406: if ((buf = (char *) HT_MALLOC(20 + strlen(reason))) == NULL)
407: HT_OUTOFMEM("HTError_response");
2.6 frystyk 408: sprintf(buf,"%s %d %s%c%c",HTTP_VERSION,code,reason,CR,LF);
409: HTAlert_assignReplyMessage(reply, buf);
410: }
411: } else {
412: HTChunk_puts(msg, "\nReason: ");
413: HTChunk_puts(msg, HTErrors[index].msg); /* Error message */
414: }
415:
416: if (showmask & HT_ERR_SHOW_PARS) { /* Error parameters */
417: int length;
418: int cnt;
419: char *pars = (char *) HTError_parameter(pres, &length);
420: if (length && pars) {
421: HTChunk_puts(msg, " (");
422: for (cnt=0; cnt<length; cnt++) {
423: char ch = *(pars+cnt);
424: if (ch < 0x20 || ch >= 0x7F)
425: HTChunk_putc(msg, '#');
426: else
427: HTChunk_putc(msg, ch);
428: }
429: HTChunk_puts(msg, ") ");
430: }
431: }
432:
433: if (showmask & HT_ERR_SHOW_LOCATION) { /* Error Location */
434: HTChunk_puts(msg, "This occured in ");
435: HTChunk_puts(msg, HTError_location(pres));
436: HTChunk_putc(msg, '\n');
437: }
438:
439: /*
440: ** Make sure that we don't get this error more than once even
441: ** if we are keeping the error stack from one request to another
442: */
443: HTError_setIgnore(pres);
444:
445: /* If we only are show the most recent entry then break here */
446: if (showmask & HT_ERR_SHOW_FIRST)
447: break;
448: }
449: }
450: if (msg) {
451: HTChunk_putc(msg, '\n');
452: #if 0
2.8 eric 453: HTTrace("WARNING: %s\n", HTChunk_data(msg));
2.6 frystyk 454: #endif
455: HTChunk_delete(msg);
456: }
457: return YES;
458: }
Webmaster