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