Annotation of libwww/Library/src/HTDialog.c, revision 2.12
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.
6: **
7: ** This module provides a default implementation of the application part
8: ** of the Message and Dialog part or the Library. You do not have to do
9: ** it like this - you can use exactly the model for mapping codes into
10: ** messages as you like
11: **
12: ** Authors
13: ** HFN Henrik Frystyk
14: */
15:
16: /* Library include files */
17: #include "WWWLib.h"
18: #include "WWWApp.h"
2.6 frystyk 19: #include "WWWHTTP.h"
2.1 frystyk 20: #include "HTReqMan.h"
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:
51: { 200, "OK", "ok" },
52: { 201, "Created", "created" },
53: { 202, "Accepted", "accepted" },
54: { 203, "Provisional Information", "partial" },
55: { 204, "No Content", "no_response" },
56: { 301, "Moved Permanently", "moved" },
57: { 302, "Moved Temporarily", "moved" },
58: { 303, "Method", "method" },
59: { 304, "Not Modified", "not_modified" },
60: { 400, "Bad Request", "bad_request" },
61: { 401, "Unauthorized", "unauthorized" },
62: { 402, "Payment Required", "payment" },
63: { 403, "Forbidden", "forbidden" },
64: { 404, "Not Found", "not_found" },
65: { 405, "Method Not Allowed", "method" },
66: { 406, "None Acceptable", "none" },
67: { 407, "Proxy Authentication Required", "proxy" },
68: { 408, "Request Timeout", "timeout" },
69: { 500, "Internal Server Error", "internal" },
70: { 501, "Not Implemented", "not_made" },
71: { 502, "Bad Gateway", "bad_gate" },
72: { 503, "Service Unavailable", "unavailable" },
73: { 504, "Gateway Timeout", "timeout" },
74: { 0, "-------------------------", "----------------------------------" },
75: { 0, "Can't locate remote host", "host" },
76: { 0, "No host name found", "host" },
77: { 0, "No file name found or file not accessible", "file" },
78: { 0, "FTP-server replies", "ftp" },
79: { 0, "FTP-server doesn't reply", "no_server" },
80: { 0, "Server timed out", "time_out" },
81: { 0, "Gopher-server replies", "gopher" },
82: { 0, "Data transfer interrupted", "interrupt" },
83: { 0, "Connection establishment interrupted", "interrupt" },
84: { 0, "CSO-server replies", "cso" },
85: { 0, "This is probably a HTTP server 0.9 or less","http_version" },
86: { 0, "Bad, Incomplete, or Unknown Response", "bad_reply" },
87: { 0, "Unknown access authentication scheme", "control" },
88: { 0, "News-server replies", "news" },
89: { 0, "Trying `ftp://' instead of `file://'", "ftpfile" },
90: { 0, "Too many redirections", "redirections" },
91: { 0, "Premature End Of File", "EOF" },
92: { 0, "Response from WAIS Server too Large - Extra lines ignored",
93: "wais" },
94: { 0, "WAIS-server doesn't return any data", "wais" },
95: { 0, "Can't connect to WAIS-server", "wais" },
96: { 0, "System replies", "system" },
97: { 0, "Wrong or unknown access scheme", "class" },
98: { 0, "Access scheme not allowed in this context", "class" },
99: { 0, "When you are connected, you can log in", "telnet" }
100: };
101:
102: /* ------------------------------------------------------------------------- */
103:
104: PUBLIC BOOL HTProgress (HTRequest * request, HTAlertOpcode op,
2.10 frystyk 105: int msgnum, const char * dfault, void * input,
2.1 frystyk 106: HTAlertPar * reply)
107: {
108: if (!request) {
2.8 eric 109: if (WWWTRACE) HTTrace("HTProgress.. Bad argument\n");
2.1 frystyk 110: return NO;
111: }
112: switch (op) {
113: case HT_PROG_DNS:
2.9 frystyk 114: HTTrace("Looking up %s\n", input ? (char *) input : "");
2.1 frystyk 115: break;
116:
117: case HT_PROG_CONNECT:
2.9 frystyk 118: HTTrace("Contacting %s\n", input ? (char *) input : "");
2.1 frystyk 119: break;
120:
121: case HT_PROG_ACCEPT:
2.8 eric 122: HTTrace("Waiting for connection...\n");
2.1 frystyk 123: break;
124:
125: case HT_PROG_READ:
126: {
127: long cl = HTAnchor_length(HTRequest_anchor(request));
128: if (cl > 0) {
129: long b_read = HTRequest_bytesRead(request);
130: double pro = (double) b_read/cl*100;
131: char buf[10];
132: HTNumToStr((unsigned long) cl, buf, 10);
2.8 eric 133: HTTrace("Read (%d%% of %s)\n", (int) pro, buf);
2.1 frystyk 134: } else
2.8 eric 135: HTTrace("Reading...\n");
2.1 frystyk 136: }
137: break;
138:
139: case HT_PROG_WRITE:
2.4 frystyk 140: if (HTRequest_isPostWeb(request)) {
141: HTParentAnchor *anchor=HTRequest_anchor(HTRequest_source(request));
142: long cl = HTAnchor_length(anchor);
143: if (cl > 0) {
144: long b_write = HTRequest_bytesWritten(request);
145: double pro = (double) b_write/cl*100;
146: char buf[10];
147: HTNumToStr((unsigned long) cl, buf, 10);
2.8 eric 148: HTTrace("Written (%d%% of %s)\n", (int) pro, buf);
2.4 frystyk 149: } else
2.8 eric 150: HTTrace("Writing...\n");
2.4 frystyk 151: }
2.1 frystyk 152: break;
153:
154: case HT_PROG_DONE:
2.8 eric 155: HTTrace("Finished\n");
2.1 frystyk 156: break;
157:
158: case HT_PROG_WAIT:
2.12 ! frystyk 159: HTTrace("Waiting for free socket...\n");
2.1 frystyk 160: break;
161:
162: default:
2.8 eric 163: HTTrace("UNKNOWN PROGRESS STATE\n");
2.1 frystyk 164: break;
165: }
166: return YES;
167: }
168:
169: PUBLIC BOOL HTConfirm (HTRequest * request, HTAlertOpcode op,
2.10 frystyk 170: int msgnum, const char * dfault, void * input,
2.1 frystyk 171: HTAlertPar * reply)
172: {
173: char response[4]; /* One more for terminating NULL -- AL */
2.8 eric 174: HTTrace("%s", HTDialogs[msgnum]);
175: if (input) HTTrace(" (%s)", (char *) input);
176: HTTrace(" (y/n) ");
2.1 frystyk 177: #ifndef NO_STDIO
2.2 frystyk 178: if (fgets(response, 4, stdin)) /* get reply, max 3 chars */
2.1 frystyk 179: #endif
2.2 frystyk 180: {
2.1 frystyk 181: char *ptr = response;
182: while (*ptr) {
183: if (*ptr == '\n') {
184: *ptr = '\0';
185: break;
186: }
187: *ptr = TOUPPER(*ptr);
188: ptr++;
189: }
190: return (!strcmp(response, "YES") || !strcmp(response, "Y")) ? YES : NO;
191: }
192: return NO;
193: }
194:
195: /* Prompt for answer and get text back. Reply text is either NULL on
2.10 frystyk 196: ** error or a dynamic string which the caller must HT_FREE.
2.1 frystyk 197: */
198: PUBLIC BOOL HTPrompt (HTRequest * request, HTAlertOpcode op,
2.10 frystyk 199: int msgnum, const char * dfault, void * input,
2.1 frystyk 200: HTAlertPar * reply)
201: {
2.8 eric 202: HTTrace("%s ", HTDialogs[msgnum]);
203: if (input) HTTrace(" (%s) ", (char *) input);
204: if (dfault) HTTrace("(RETURN for [%s]) ", (char *) dfault);
2.1 frystyk 205: if (reply && msgnum>=0) {
206: #ifndef NO_STDIO
2.5 frystyk 207: char buffer[200];
2.1 frystyk 208: if (!fgets(buffer, 200, stdin)) return NO;
209: buffer[strlen(buffer)-1] = '\0'; /* Overwrite newline */
210: if (*buffer)
211: HTAlert_setReplyMessage(reply, buffer);
212: else if (dfault)
213: HTAlert_setReplyMessage(reply, (char *) dfault);
214: else
215: return NO;
216: return YES;
217: #endif
218: }
219: return NO;
220: }
221:
222: /* Prompt for password without echoing the reply. Reply text is
2.10 frystyk 223: ** either NULL on error or a dynamic string which the caller must HT_FREE.
2.1 frystyk 224: */
225: PUBLIC BOOL HTPromptPassword (HTRequest * request, HTAlertOpcode op,
2.10 frystyk 226: int msgnum, const char * dfault, void * input,
2.1 frystyk 227: HTAlertPar * reply)
228: {
229: if (reply && msgnum>=0) {
2.10 frystyk 230: #ifdef HAVE_GETPASS
2.1 frystyk 231: char * pw = (char *) getpass(HTDialogs[msgnum]);
2.2 frystyk 232: if (pw) HTAlert_setReplySecret(reply, pw);
2.1 frystyk 233: return YES;
2.10 frystyk 234: #else
2.11 eric 235: return NO; /* needed for WWW_MSWINDOWS */
2.10 frystyk 236: #endif /* HAVE_GETPASS */
2.1 frystyk 237: }
238: return NO;
239: }
240:
241: /* Username and password
242: ** ---------------------
243: ** Prompt Username and password as an atomic operation
244: */
245: PUBLIC BOOL HTPromptUsernameAndPassword (HTRequest * request, HTAlertOpcode op,
2.10 frystyk 246: int msgnum, const char * dfault,
2.1 frystyk 247: void * input, HTAlertPar * reply)
248: {
249: BOOL status = HTPrompt(request, op, HT_MSG_UID, dfault, input, reply);
250: return status ?
251: HTPromptPassword(request, op, HT_MSG_PW, dfault, input, reply) : NO;
252: }
253:
254: /* HTError_print
255: ** -------------
256: ** Default function that creates an error message using HTAlert() to
257: ** put out the contents of the error_stack messages. Furthermore, the
258: ** error_info structure contains a name of a help file that might be put
259: ** up as a link. This file can then be multi-linguistic.
260: */
261: PUBLIC BOOL HTError_print (HTRequest * request, HTAlertOpcode op,
2.10 frystyk 262: int msgnum, const char * dfault, void * input,
2.1 frystyk 263: HTAlertPar * reply)
264: {
265: HTList *cur = (HTList *) input;
266: HTError *pres;
267: HTErrorShow showmask = HTError_show();
268: HTChunk *msg = NULL;
269: int code;
2.8 eric 270: if (WWWTRACE) HTTrace("HTError..... Generating message\n");
2.1 frystyk 271: if (!request || !cur) return NO;
272: while ((pres = (HTError *) HTList_nextObject(cur))) {
273: int index = HTError_index(pres);
274: if (HTError_doShow(pres)) {
275: if (!msg) {
276: HTSeverity severity = HTError_severity(pres);
2.3 frystyk 277: msg = HTChunk_new(128);
2.1 frystyk 278: if (severity == ERR_WARN)
2.3 frystyk 279: HTChunk_puts(msg, "Warning: ");
2.1 frystyk 280: else if (severity == ERR_NON_FATAL)
2.3 frystyk 281: HTChunk_puts(msg, "Non Fatal Error: ");
2.1 frystyk 282: else if (severity == ERR_FATAL)
2.3 frystyk 283: HTChunk_puts(msg, "Fatal Error: ");
2.1 frystyk 284: else if (severity == ERR_INFO)
2.3 frystyk 285: HTChunk_puts(msg, "Information: ");
2.1 frystyk 286: else {
287: if (WWWTRACE)
2.8 eric 288: HTTrace("HTError..... Unknown Classification of Error (%d)...\n", severity);
2.3 frystyk 289: HTChunk_delete(msg);
2.1 frystyk 290: return NO;
291: }
292:
293: /* Error number */
294: if ((code = HTErrors[index].code) > 0) {
295: char buf[10];
296: sprintf(buf, "%d ", code);
2.3 frystyk 297: HTChunk_puts(msg, buf);
2.1 frystyk 298: }
299: } else
2.3 frystyk 300: HTChunk_puts(msg, "\nReason: ");
301: HTChunk_puts(msg, HTErrors[index].msg); /* Error message */
2.1 frystyk 302:
303: if (showmask & HT_ERR_SHOW_PARS) { /* Error parameters */
304: int length;
305: int cnt;
306: char *pars = (char *) HTError_parameter(pres, &length);
307: if (length && pars) {
2.3 frystyk 308: HTChunk_puts(msg, " (");
2.1 frystyk 309: for (cnt=0; cnt<length; cnt++) {
310: char ch = *(pars+cnt);
311: if (ch < 0x20 || ch >= 0x7F)
2.3 frystyk 312: HTChunk_putc(msg, '#');
2.1 frystyk 313: else
2.3 frystyk 314: HTChunk_putc(msg, ch);
2.1 frystyk 315: }
2.3 frystyk 316: HTChunk_puts(msg, ") ");
2.1 frystyk 317: }
318: }
319:
320: if (showmask & HT_ERR_SHOW_LOCATION) { /* Error Location */
2.3 frystyk 321: HTChunk_puts(msg, "This occured in ");
322: HTChunk_puts(msg, HTError_location(pres));
323: HTChunk_putc(msg, '\n');
2.1 frystyk 324: }
325:
326: /*
327: ** Make sure that we don't get this error more than once even
328: ** if we are keeping the error stack from one request to another
329: */
330: HTError_setIgnore(pres);
331:
332: /* If we only are show the most recent entry then break here */
333: if (showmask & HT_ERR_SHOW_FIRST)
334: break;
335: }
336: }
337: if (msg) {
2.3 frystyk 338: HTChunk_putc(msg, '\n');
2.8 eric 339: HTTrace("WARNING: %s\n", HTChunk_data(msg));
2.3 frystyk 340: HTChunk_delete(msg);
2.1 frystyk 341: }
342: return YES;
343: }
344:
2.6 frystyk 345: /* HTError_response
346: ** ----------------
347: ** Default function that creates an error message using HTAlert() to
348: ** put out the contents of the error_stack messages. Furthermore, the
349: ** error_info structure contains a name of a help file that might be put
350: ** up as a link. This file can then be multi-linguistic.
351: */
352: PUBLIC BOOL HTError_response (HTRequest * request, HTAlertOpcode op,
2.10 frystyk 353: int msgnum, const char * dfault, void * input,
2.6 frystyk 354: HTAlertPar * reply)
355: {
356: HTList * cur = (HTList *) input;
357: HTError * pres;
358: HTErrorShow showmask = HTError_show();
359: HTChunk * msg = NULL;
360: int code;
2.8 eric 361: if (WWWTRACE) HTTrace("HTError..... Generating HTTP response\n");
2.6 frystyk 362: if (!request || !cur || !reply) return NO;
363: while ((pres = (HTError *) HTList_nextObject(cur))) {
364: int index = HTError_index(pres);
365: if (HTError_doShow(pres)) {
366: if (!msg) {
367: msg = HTChunk_new(128);
368: if ((code = HTErrors[index].code) > 0) {
369: char * reason = HTErrors[index].msg;
2.7 frystyk 370: char * buf;
371: if ((buf = (char *) HT_MALLOC(20 + strlen(reason))) == NULL)
372: HT_OUTOFMEM("HTError_response");
2.6 frystyk 373: sprintf(buf,"%s %d %s%c%c",HTTP_VERSION,code,reason,CR,LF);
374: HTAlert_assignReplyMessage(reply, buf);
375: }
376: } else {
377: HTChunk_puts(msg, "\nReason: ");
378: HTChunk_puts(msg, HTErrors[index].msg); /* Error message */
379: }
380:
381: if (showmask & HT_ERR_SHOW_PARS) { /* Error parameters */
382: int length;
383: int cnt;
384: char *pars = (char *) HTError_parameter(pres, &length);
385: if (length && pars) {
386: HTChunk_puts(msg, " (");
387: for (cnt=0; cnt<length; cnt++) {
388: char ch = *(pars+cnt);
389: if (ch < 0x20 || ch >= 0x7F)
390: HTChunk_putc(msg, '#');
391: else
392: HTChunk_putc(msg, ch);
393: }
394: HTChunk_puts(msg, ") ");
395: }
396: }
397:
398: if (showmask & HT_ERR_SHOW_LOCATION) { /* Error Location */
399: HTChunk_puts(msg, "This occured in ");
400: HTChunk_puts(msg, HTError_location(pres));
401: HTChunk_putc(msg, '\n');
402: }
403:
404: /*
405: ** Make sure that we don't get this error more than once even
406: ** if we are keeping the error stack from one request to another
407: */
408: HTError_setIgnore(pres);
409:
410: /* If we only are show the most recent entry then break here */
411: if (showmask & HT_ERR_SHOW_FIRST)
412: break;
413: }
414: }
415: if (msg) {
416: HTChunk_putc(msg, '\n');
417: #if 0
2.8 eric 418: HTTrace("WARNING: %s\n", HTChunk_data(msg));
2.6 frystyk 419: #endif
420: HTChunk_delete(msg);
421: }
422: return YES;
423: }
Webmaster