Annotation of libwww/LineMode/src/HTBrowse.c, revision 1.135
1.44 frystyk 1: /* HTBrowse.c
2: ** HYPERTEXT BROWSER FOR DUMB TERMINALS
3: **
1.62 frystyk 4: ** (c) COPRIGHT MIT 1995.
1.44 frystyk 5: ** Please first read the full copyright statement in the file COPYRIGH.
1.135 ! eric 6: ** @(#) $Id: HTBrowse.c,v 1.134 1996/05/07 18:10:18 eric Exp $
1.1 timbl 7: **
8: ** Authors:
9: ** NP: Nicola Pellow Tech.Student CERN 1990-91
1.61 frystyk 10: ** TBL: Tim Berners-Lee CERN (timbl@w3.org)
11: ** JFG: Jean-Francois Groff, Cooperant CERN 1991-92 (jfg@dxcern.cern.ch)
1.1 timbl 12: ** DR: Dudu Rashty +972-2-584848 <RASHTY@hujivms.bitnet>
1.8 duns 13: ** MD: Mark Donszelmann, DELPHI CERN, (duns@vxdeop.cern.ch)
1.96 frystyk 14: ** HFN: Henrik Frystyk Nielsen, MIT, (frystyk@w3.org)
1.1 timbl 15: **
16: ** History:
17: **
18: ** 4 Dec 90: Written from scratch (NP)
19: ** 11 Feb 91: Code written by TBL so that the browser could be linked with
20: ** code produced by Bernd Pollermann, enabling access to the
21: ** data on CERNVM. This involved changing the code to handle file
22: ** numbers rather than file pointers.
23: ** 18 Mar 91: The feature of history mechanism was included, enabling a
24: ** record of previous nodes visited to be kept.
25: ** 6 Apr 91: When a node is accessed, it is immediately read into a
1.40 frystyk 26: ** buffer, in an unformatted state, as soon as the connection is
1.120 frystyk 27: ** made, so that the server is HT_FREEd as quickly as possible.
1.1 timbl 28: ** The program now also uses the additional modules HTBufferFile.c
29: ** and HTBufferFile.h.
30: ** 17 Apr 91: Can be used on machines running ANSI C and ordinary C.
31: ** 10 May 91: Formatted text is stored in a linked list buffer which allows
32: ** scrolling and better page breaks in the middle of text.
33: ** Code incorporated by Tim BL, to enable anonymous FTP.
34: ** 21 May 91: Accepts various parameters on the command line.
35: ** 19 Aug 91: Currently available in Unix, VAX/VMS and MVS environments.
36: ** 21 Nov 91: Character grid uses new architecture. (TBL)
37: ** added -w option, new commands, print,
38: ** ... See Features.html for further details
39: ** 16 Jan 92: Put in VIOLA-compatible options - see \017 characters.
40: ** \017 and \016 bracket user-selectable input.
41: ** 27 Feb 92: New handling of user input, enhanced command syntax. (JFG)
42: ** 18 May 92: PS command see ifdef SLAVE_PRINTER (DR/TBL)
43: ** 6 Oct 92: Painful recovery from someone(?)'s attept to pretty print.(TBL)
44: ** Please see coding style guide before changing indentation etc!
45: ** Mar 93: Force on HTFile's HTDirAccess and HTDirReadme flags.
1.8 duns 46: ** 3 Nov 93: (MD) Changed vms into VMS
1.99 frystyk 47: ** (MD) Assigne OUTPUT in main, not at initialize (VMS only)
1.1 timbl 48: **
49: ** Compilation-time macro options
50: **
51: ** REF_MARK Printf string to be used for printing anchor numbers
52: ** END_MARK String to be used to denote the end of a document
53: */
54:
1.96 frystyk 55: #include "WWWLib.h"
56: #include "WWWMIME.h"
1.110 frystyk 57: #include "WWWRules.h"
58: #include "WWWCache.h"
1.96 frystyk 59: #include "WWWApp.h"
1.111 frystyk 60: #include "WWWInit.h"
1.92 frystyk 61:
1.127 frystyk 62: #include "HTTrans.h"
63: #include "HTReader.h"
64: #include "HTWriter.h"
65: #include "HTANSI.h"
66:
1.96 frystyk 67: #include "GridText.h" /* Hypertext definition */
1.68 frystyk 68: #include "HTBrowse.h" /* Things exported, short names */
1.121 eric 69: #include "CSLApp.h" /* the PICApp library should provide everything the app needs */
1.126 hallam 70: #include "CSLL.h"
1.121 eric 71: #include "CSUser.h"
1.124 eric 72: #include "CSUsrLst.h"
1.40 frystyk 73:
1.120 frystyk 74: #ifndef W3C_VERSION
75: #define W3C_VERSION "Unspecified"
1.40 frystyk 76: #endif
77:
1.96 frystyk 78: #define APP_NAME "W3CLineMode"
1.120 frystyk 79: #define APP_VERSION W3C_VERSION
1.86 frystyk 80:
1.68 frystyk 81: /* Default page for "Manual" command */
1.96 frystyk 82: #define MANUAL "http://www.w3.org/pub/WWW/LineMode/Defaults/QuickGuide.html"
1.40 frystyk 83:
1.68 frystyk 84: /* Default page for "help" command */
1.96 frystyk 85: #define C_HELP "http://www.w3.org/pub/WWW/LineMode/Defaults/Commands.html"
1.1 timbl 86:
1.68 frystyk 87: /* Default page for "-help" command line option */
1.96 frystyk 88: #define L_HELP "http://www.w3.org/pub/WWW/LineMode/Defaults/CommandLine.html"
1.37 howcome 89:
1.68 frystyk 90: #define DEFAULT_OUTPUT_FILE "www.out"
91: #define DEFAULT_RULE_FILE "www.conf"
92: #define DEFAULT_LOG_FILE "www.log"
1.126 hallam 93: #define DEFAULT_USERLIST_FILE "PICSusrs.html"
1.68 frystyk 94:
95: #define PROMPT "%s"
96: #define REF_MARK "[%d]"
97: #define END_MARK "[END]"
1.1 timbl 98:
1.72 frystyk 99: #define SCREEN_WIDTH 79 /* Default width of the screen */
1.13 frystyk 100: #define MIN_SCREEN_WIDTH 10
101: #define MAX_SCREEN_WIDTH 150
1.72 frystyk 102: #define SCREEN_HEIGHT 24 /* Default number of lines */
1.13 frystyk 103: #define MIN_SCREEN_HEIGHT 5
1.14 frystyk 104: #define MAX_SCREEN_HEIGHT 200
1.72 frystyk 105:
106: #define MAX_HISTORY 20 /* Don't list more than this in list */
1.1 timbl 107:
1.68 frystyk 108: #define RESPONSE_LENGTH 1024 /* Maximum length of users response */
1.16 frystyk 109:
1.94 frystyk 110: #define SHOW_MSG (WWWTRACE || HTAlert_interactive())
1.68 frystyk 111: #define CHECK_INPUT(a, b) (!strncasecomp ((a), (b), strlen((b))))
1.50 frystyk 112:
1.96 frystyk 113: #define DEFAULT_I_TIMEOUT 1 /* Interactive timeout in seconds */
114: #define DEFAULT_NI_TIMEOUT 10 /* Non-interactive timeout in seconds */
115:
116: #define DEFAULT_FORMAT WWW_PRESENT
1.81 frystyk 117:
1.50 frystyk 118: #if defined(__svr4__)
119: #define CATCH_SIG
120: #endif
1.40 frystyk 121:
122: /* HWL 18/7/94: applied patch from agl@glas2.glas.apc.org (Anton Tropashko) */
123: #ifdef CYRILLIC
1.68 frystyk 124: #include "a_stdio.h"
1.40 frystyk 125: struct ARc arc;
126: #endif
1.2 timbl 127:
1.68 frystyk 128: /* Screen size parameters */
1.40 frystyk 129: PUBLIC int HTScreenWidth = SCREEN_WIDTH; /* By default */
130: PUBLIC int HTScreenHeight = -1; /* -1 = Undefined */
1.68 frystyk 131:
132: /* Anchor specific information */
1.40 frystyk 133: PUBLIC BOOL display_anchors = YES; /* Show anchors in text? */
134: PUBLIC char * start_reference = NULL; /* Format for start anchor */
135: PUBLIC char * end_reference = REF_MARK; /* for end anchor */
136: PUBLIC char * reference_mark = "[%d] "; /* for reference lists */
137: PUBLIC char * end_mark = END_MARK; /* Format string for [End] */
1.8 duns 138:
1.96 frystyk 139: typedef enum _LMFlags {
140: LM_FILTER = 0x1,
141: LM_REFS = 0x2,
142: LM_REFORMAT = 0x4,
143: LM_PREEMTIVE= 0x8
144: } LMFlags;
145:
1.118 eric 146: struct _LineMode {
1.115 frystyk 147: HTRequest * console; /* For user input */
1.96 frystyk 148: HTParentAnchor * anchor;
149: struct timeval * tv; /* Timeout on socket */
150: HTList * active; /* List of acitve contexts */
151: HTList * converters;
152: HTList * presenters;
1.129 frystyk 153: HTList * encoders;
1.96 frystyk 154: HTHistory * history; /* History list */
155: char * cwd; /* Current dir URL */
156: char * rules;
157: char * logfile;
158: char * outputfile;
159: char * host;
160: int trace;
161: HTFormat format; /* Input format from console */
162: LMFlags flags;
1.118 eric 163: HTView * pView;
1.126 hallam 164: char * userList;
1.124 eric 165: CSUser_t * pCSUser;
1.132 eric 166: BOOL noPICSPasswords;
1.118 eric 167: };
1.96 frystyk 168:
169: typedef enum _LMState {
170: LM_UPDATE = 0x1,
171: LM_NO_UPDATE= 0x2,
172: LM_DONE = 0x4,
173: LM_INACTIVE = 0x8
174: } LMState;
175:
176: typedef struct _Context {
177: LMState state;
178: HTRequest * request;
179: LineMode * lm;
1.108 frystyk 180: HTParentAnchor * source; /* The source if we are using PUT or POST */
1.96 frystyk 181: } Context;
1.4 timbl 182:
1.106 frystyk 183: #ifndef WWW_WIN_WINDOW
1.118 eric 184: PRIVATE FILE * OUTPUT = stdout;
1.99 frystyk 185: #endif
1.96 frystyk 186:
1.106 frystyk 187: PRIVATE InputParser_t parse_command;
188: InputParser_t * PInputParser = &parse_command;
1.127 frystyk 189:
1.128 frystyk 190: /* Net callback handlers */
191: PRIVATE HTNetCallback terminate_handler;
192: PRIVATE HTNetCallback authentication_handler;
193: PRIVATE HTNetCallback redirection_handler;
1.127 frystyk 194:
1.62 frystyk 195: /* ------------------------------------------------------------------------- */
196:
1.96 frystyk 197: /* Create a Context Object
198: ** -----------------------
199: */
1.104 frystyk 200: PRIVATE Context * Context_new (LineMode *lm, HTRequest *request, LMState state)
1.96 frystyk 201: {
1.112 frystyk 202: Context * me;
203: if ((me = (Context *) HT_CALLOC(1, sizeof (Context))) == NULL)
204: HT_OUTOFMEM("Context_new");
1.104 frystyk 205: me->state = state;
1.96 frystyk 206: me->request = request;
207: me->lm = lm;
1.116 frystyk 208: HTRequest_setContext(request, (void *) me);
209: HTList_addObject(lm->active, (void *) me);
1.72 frystyk 210: return me;
211: }
212:
1.96 frystyk 213: /* Delete a Context Object
214: ** -----------------------
1.72 frystyk 215: */
1.96 frystyk 216: PRIVATE BOOL Context_delete (Context * old)
1.72 frystyk 217: {
1.112 frystyk 218: HT_FREE(old);
1.72 frystyk 219: return YES;
220: }
221:
1.118 eric 222: PUBLIC LineMode * Context_getLineMode(HTRequest * request)
223: {
224: return ((Context *) HTRequest_context(request))->lm;
225: }
226:
1.62 frystyk 227: /*
1.96 frystyk 228: ** This function creates a new request object and adds it to the global
1.62 frystyk 229: ** list of active threads
230: */
1.130 eric 231: CSDisposition_callback PICSCallback;
1.104 frystyk 232: PRIVATE HTRequest * Thread_new (LineMode * lm, BOOL Interactive, LMState state)
1.62 frystyk 233: {
1.96 frystyk 234: HTRequest * newreq = HTRequest_new();
235: if (!lm) return NULL;
1.104 frystyk 236: Context_new(lm, newreq, state);
1.96 frystyk 237: if (Interactive) HTRequest_setConversion(newreq, lm->presenters, NO);
1.108 frystyk 238: if (lm->flags & LM_PREEMTIVE) HTRequest_setPreemptive(newreq, YES);
1.104 frystyk 239: HTRequest_addRqHd(newreq, HT_C_HOST);
1.126 hallam 240: CSApp_registerReq(newreq, lm->pCSUser, PICSCallback,
241: CSApp_callOnBad, (void *)lm);
1.62 frystyk 242: return newreq;
243: }
244:
245: /*
1.96 frystyk 246: ** This function deletes all unused request objects
1.62 frystyk 247: */
1.96 frystyk 248: PRIVATE void Thread_cleanup (LineMode * lm)
1.62 frystyk 249: {
1.96 frystyk 250: if (lm && lm->active) {
251: HTList * cur = lm->active;
252: Context * pres;
253: while ((pres = (Context *) HTList_nextObject(cur))) {
1.104 frystyk 254: if (pres->state&LM_DONE && pres->state&LM_INACTIVE) {
255: if ((HTList_removeObject(lm->active, pres)) == NO)
1.118 eric 256: HTTrace("NOT FOUND\n");
1.96 frystyk 257: HTRequest_delete(pres->request);
258: Context_delete(pres);
259: cur = lm->active;
260: }
261: }
1.62 frystyk 262: }
263: }
264:
265: /*
266: ** This function deletes the whole list of active threads.
267: */
1.96 frystyk 268: PRIVATE void Thread_deleteAll (LineMode * lm)
1.62 frystyk 269: {
1.96 frystyk 270: if (lm && lm->active) {
271: HTList * cur = lm->active;
272: Context * pres;
273: while ((pres = (Context *) HTList_nextObject(cur))) {
1.104 frystyk 274: if (pres->request) {
275: HTRequest_delete(pres->request);
276: Context_delete(pres);
277: }
1.62 frystyk 278: }
1.96 frystyk 279: HTList_delete(lm->active);
280: lm->active = NULL;
1.62 frystyk 281: }
282: }
283:
1.96 frystyk 284: /* Create a Line Mode Object
285: ** -------------------------
286: */
287: PRIVATE LineMode * LineMode_new (void)
288: {
289: LineMode * me;
1.112 frystyk 290: if ((me = (LineMode *) HT_CALLOC(1, sizeof(LineMode))) == NULL ||
291: (me->tv = (struct timeval*) HT_CALLOC(1, sizeof(struct timeval))) == NULL)
292: HT_OUTOFMEM("LineMode_new");
1.96 frystyk 293: me->tv->tv_sec = -1;
294: me->cwd = HTFindRelatedName();
295: me->active = HTList_new();
1.115 frystyk 296: me->console = HTRequest_new();
297: Context_new(me, me->console, LM_UPDATE);
1.104 frystyk 298: me->trace = SHOW_ALL_TRACE;
1.124 eric 299: me->pCSUser = 0;
1.134 eric 300: if (!(me->pView = HTView_create("'nother Window", 25, 80, me)))
1.130 eric 301: return 0;
1.96 frystyk 302: return me;
303: }
304:
305: /* Delete a Line Mode Object
306: ** -------------------------
307: */
308: PRIVATE BOOL LineMode_delete (LineMode * lm)
309: {
310: if (lm) {
1.112 frystyk 311: HT_FREE(lm->tv);
1.96 frystyk 312: Thread_deleteAll(lm);
313: HTConversion_deleteAll(lm->converters);
314: HTPresentation_deleteAll(lm->presenters);
1.129 frystyk 315: HTCoding_deleteAll(lm->encoders);
1.96 frystyk 316: HTHistory_delete(lm->history);
1.112 frystyk 317: HT_FREE(lm->cwd);
1.96 frystyk 318: if (lm->logfile) HTLog_close();
1.124 eric 319: if (lm->pCSUser)
320: CSLoadedUser_remove(lm->pCSUser);
1.118 eric 321: HTView_destroy(lm->pView);
1.106 frystyk 322: #ifndef WWW_WIN_WINDOW
1.118 eric 323: if (OUTPUT && OUTPUT != stdout) fclose(OUTPUT);
1.99 frystyk 324: #endif
1.112 frystyk 325: HT_FREE(lm);
1.96 frystyk 326: return YES;
327: }
328: return NO;
329: }
330:
1.118 eric 331: PUBLIC HTRequest * LineMode_getConsole(LineMode * pLm)
332: {
333: return pLm->console;
334: }
335:
336: PUBLIC HTView * LineMode_getView(LineMode * pLm)
337: {
338: return pLm ? pLm->pView : 0;
339: }
340:
1.124 eric 341: PRIVATE BOOL LineMode_load(LineMode * lm, HTParentAnchor * anchor,
342: char * url, BOOL preemptive, HTRequest ** pPReq)
343: {
344: char * fullURL;
345: HTParentAnchor * pAnchor;
346:
347: *pPReq = Thread_new(lm, YES, LM_NO_UPDATE);
348: if (preemptive)
349: HTRequest_setPreemptive(*pPReq, YES);
350: if (anchor)
351: return HTLoadRelative(url, anchor, *pPReq);
352: fullURL = HTParse(url, lm->cwd, PARSE_ALL);
353: pAnchor = (HTParentAnchor *) HTAnchor_findAddress(fullURL);
354: HT_FREE(fullURL);
355: return HTLoadAnchor((HTAnchor *) pAnchor, *pPReq);
356: }
357:
1.96 frystyk 358: PRIVATE void Cleanup (LineMode * me, int status)
359: {
360: if (HTAlert_interactive()) /* Terminate with a LF if not interactive */
1.118 eric 361: OutputData(me->pView, "\n");
1.126 hallam 362: CSLoadedUser_deleteAll();
1.133 eric 363: CSApp_unregisterApp();
1.96 frystyk 364: LineMode_delete(me);
1.119 frystyk 365:
366: HTAuthInfo_deleteAll();
367:
1.96 frystyk 368: HTLibTerminate();
369: #ifdef VMS
370: exit(status ? status : 1);
371: #else
372: exit(status ? status : 0);
373: #endif
374: }
1.7 secret 375:
376: /*
1.100 frystyk 377: ** Get size of the output screen. Stolen from less.
1.40 frystyk 378: */
1.90 frystyk 379: PRIVATE void scrsize (int * p_height, int * p_width)
1.7 secret 380: {
1.120 frystyk 381: #if defined(HAVE_IOCTL) && defined(HAVE_WINSIZE)
1.96 frystyk 382: register char *s;
383: int ioctl();
384: struct winsize w;
385: if (ioctl(2, TIOCGWINSZ, &w) == 0 && w.ws_row > 0)
386: *p_height = w.ws_row;
387: else if ((s = getenv("LINES")) != NULL)
388: *p_height = atoi(s);
389: else
390: *p_height = SCREEN_HEIGHT;
391:
392: if (ioctl(2, TIOCGWINSZ, &w) == 0 && w.ws_col > 0)
393: *p_width = w.ws_col;
394: else if ((s = getenv("COLUMNS")) != NULL)
395: *p_width = atoi(s);
396: else
397: *p_width = 80;
1.120 frystyk 398: #else
399: *p_height = SCREEN_HEIGHT;
400: *p_width = SCREEN_WIDTH;
401: #endif /* HAVE_IOCTL && HAVE_WINSIZE */
1.7 secret 402: }
403:
1.50 frystyk 404: #ifdef CATCH_SIG
405: #include <signal.h>
406: /* SetSignal
407: ** This function sets up signal handlers. This might not be necessary to
408: ** call if the application has its own handlers.
409: */
1.90 frystyk 410: PRIVATE void SetSignal (void)
1.50 frystyk 411: {
412: /* On some systems (SYSV) it is necessary to catch the SIGPIPE signal
413: ** when attemting to connect to a remote host where you normally should
414: ** get `connection refused' back
415: */
416: if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
1.118 eric 417: if (PROT_TRACE) HTTrace("HTSignal.... Can't catch SIGPIPE\n");
1.50 frystyk 418: } else {
1.118 eric 419: if (PROT_TRACE) HTTrace("HTSignal.... Ignoring SIGPIPE\n");
1.50 frystyk 420: }
421: }
422: #endif /* CATCH_SIG */
423:
1.96 frystyk 424: /* Print version information
425: ** -------------------------
426: */
1.118 eric 427: PRIVATE void VersionInfo (LineMode * lm)
1.96 frystyk 428: {
1.118 eric 429: HTView * pView = lm ? lm->pView : 0;
430: OutputData(pView, "\n\nW3C Reference Software\n\n");
431: OutputData(pView, "\tW3C Line Mode Browser version %s.\n", APP_VERSION);
432: OutputData(pView, "\tW3C Reference Library version %s.\n\n",HTLib_version());
433: OutputData(pView, "Please send feedback to <www-bug@w3.org>\n");
1.96 frystyk 434: }
1.7 secret 435:
1.40 frystyk 436: /* Reference_List
437: ** --------------
1.96 frystyk 438: ** Print out a list of HyperText References from current document
1.40 frystyk 439: */
1.96 frystyk 440: PRIVATE void Reference_List (LineMode * lm, BOOL titles)
1.40 frystyk 441: {
1.50 frystyk 442: int refs = HText_sourceAnchors(HTMainText);
443: if (refs <= 0) {
1.118 eric 444: OutputData(lm->pView, "\n\nThere are no references from this document.\n\n");
1.40 frystyk 445: } else {
1.68 frystyk 446: int cnt;
1.118 eric 447: OutputData(lm->pView, "\n*** References from this document ***\n");
1.50 frystyk 448: for (cnt=1; cnt<=refs; cnt++) {
449: HTAnchor *dest =
450: HTAnchor_followMainLink((HTAnchor *)
451: HText_childNumber(HTMainText, cnt));
452: HTParentAnchor * parent = HTAnchor_parent(dest);
453: char * address = HTAnchor_address(dest);
1.120 frystyk 454: const char * title = titles ? HTAnchor_title(parent) : NULL;
1.118 eric 455: OutputData(lm->pView, reference_mark, cnt);
456: OutputData(lm->pView, "%s%s\n",
1.50 frystyk 457: ((HTAnchor*)parent!=dest) && title ? "in " : "",
1.40 frystyk 458: (char *)(title ? title : address));
1.112 frystyk 459: HT_FREE(address);
1.40 frystyk 460: }
1.106 frystyk 461: #ifndef WWW_WIN_WINDOW
1.99 frystyk 462: fflush(OUTPUT);
463: #endif
1.40 frystyk 464: }
465: }
1.1 timbl 466:
1.96 frystyk 467: /* History_List
468: ** ------------
1.68 frystyk 469: ** Display a history list of nodes visited during the session.
1.1 timbl 470: */
1.96 frystyk 471: PRIVATE void History_List (LineMode * lm)
472: {
473: int current = HTHistory_position(lm->history);
474: int max = HTHistory_count(lm->history);
1.70 frystyk 475: int cnt;
1.118 eric 476: OutputData(lm->pView, "\n Documents you have visited: ");
1.70 frystyk 477: if (max > MAX_HISTORY) {
478: max = MAX_HISTORY;
1.118 eric 479: OutputData(lm->pView, "(truncated)\n");
1.70 frystyk 480: } else
1.118 eric 481: OutputData(lm->pView, "\n");
1.70 frystyk 482: for (cnt=1; cnt<=max; cnt++) {
1.96 frystyk 483: HTAnchor *anchor = HTHistory_list(lm->history, cnt);
1.70 frystyk 484: char *address = HTAnchor_address(anchor);
485: HTParentAnchor *parent = HTAnchor_parent(anchor);
1.120 frystyk 486: const char *title = HTAnchor_title(parent);
1.118 eric 487: OutputData(lm->pView, "%s R %d\t%s%s\n",
1.70 frystyk 488: (cnt==current) ? "*" : " ",
489: cnt,
1.68 frystyk 490: ((HTAnchor*)parent!=anchor) && title ? "in " : "",
491: title ? title : address);
1.112 frystyk 492: HT_FREE(address);
1.70 frystyk 493: }
1.118 eric 494: OutputData(lm->pView, "\n");
1.1 timbl 495: }
496:
1.94 frystyk 497: /* Prompt for answer and get text back. Reply text is either NULL on
1.120 frystyk 498: ** error or a dynamic string which the caller must HT_FREE.
1.94 frystyk 499: */
1.120 frystyk 500: PRIVATE char * AskUser (HTRequest * request, const char * Msg,
501: const char * deflt)
1.94 frystyk 502: {
503: char buffer[200];
504: char *reply = NULL;
1.118 eric 505: HTTrace("%s ", Msg ? Msg : "UNKNOWN");
1.94 frystyk 506: if (deflt)
1.118 eric 507: HTTrace("(RETURN for [%s]) ", deflt);
1.94 frystyk 508:
509: #ifndef NO_STDIO
510: if (!fgets(buffer, 200, stdin))
511: return NULL; /* NULL string on error, Henrik */
512: buffer[strlen(buffer)-1] = '\0'; /* Overwrite newline */
513: if (*buffer)
514: StrAllocCopy(reply, buffer);
515: else if (deflt)
516: StrAllocCopy(reply, deflt);
517: #endif
518: return reply;
519: }
520:
1.120 frystyk 521: PRIVATE BOOL confirm (HTRequest * request, const char * Msg)
1.94 frystyk 522: {
1.96 frystyk 523: char response[4];
1.118 eric 524: HTTrace("%s (y/n) ", Msg ? Msg : "UNKNOWN");
1.94 frystyk 525: #ifndef NO_STDIO
1.96 frystyk 526: if (fgets(response, 4, stdin)) /* get reply, max 3 chars */
1.94 frystyk 527: #endif
1.96 frystyk 528: {
529: char *ptr = response;
530: while (*ptr) {
531: if (*ptr == '\n') {
532: *ptr = '\0';
533: break;
534: }
535: *ptr = TOUPPER(*ptr);
536: ptr++;
537: }
538: return (!strcmp(response, "YES") || !strcmp(response, "Y")) ? YES : NO;
1.94 frystyk 539: }
1.96 frystyk 540: return NO;
1.94 frystyk 541: }
1.1 timbl 542:
1.96 frystyk 543: /* MakeCommandLine
544: ** ---------------
1.40 frystyk 545: ** Generate the Prompt line and flush it to the user
1.1 timbl 546: */
1.96 frystyk 547: PRIVATE void MakeCommandLine (LineMode * lm, BOOL is_index)
1.40 frystyk 548: {
1.70 frystyk 549: /* First Line */
1.69 frystyk 550: if (HTAnchor_hasChildren(HTMainAnchor)) {
1.40 frystyk 551: int refs = HText_sourceAnchors(HTMainText);
1.69 frystyk 552: if (refs>1)
1.118 eric 553: OutputData(lm->pView, "1-%d, ", refs);
1.69 frystyk 554: else
1.118 eric 555: OutputData(lm->pView, "1, ");
1.40 frystyk 556: }
1.70 frystyk 557: if (HText_canScrollUp(HTMainText)) {
1.118 eric 558: OutputData(lm->pView, "Top, ");
559: OutputData(lm->pView, "Up, ");
1.70 frystyk 560: }
561: if (HText_canScrollDown(HTMainText)) {
1.118 eric 562: OutputData(lm->pView, "BOttom, ");
563: OutputData(lm->pView, "Down or <RETURN> for more,");
1.70 frystyk 564: }
1.69 frystyk 565:
1.70 frystyk 566: /* Second Line */
1.118 eric 567: OutputData(lm->pView, "\n");
1.96 frystyk 568: if (HTHistory_canBacktrack(lm->history))
1.118 eric 569: OutputData(lm->pView, "Back, ");
1.96 frystyk 570: if (HTHistory_canForward(lm->history))
1.118 eric 571: OutputData(lm->pView, "Forward, ");
1.70 frystyk 572: if (is_index)
1.118 eric 573: OutputData(lm->pView, "FIND <keywords>, ");
574: OutputData(lm->pView, "Quit, or Help: ");
1.44 frystyk 575: fflush(stdout); /* For use to flush out the prompt */
1.40 frystyk 576: return;
577: }
1.1 timbl 578:
1.40 frystyk 579: /*
1.110 frystyk 580: ** Test function for posting data from memory
581: ** Returns the result of the load function.
582: */
583: PRIVATE int EditAnchor (LineMode * lm, HTRequest * req, HTMethod method)
584: {
585: char * base = HTAnchor_address((HTAnchor*) HTMainAnchor);
586: char * scr_url = "file:/tmp/testanchor";
587: char * dest_url = NULL;
588: int status = HT_INTERNAL;
589: if ((dest_url = AskUser(req, "Destination:", NULL)) != NULL) {
590: BOOL doit = YES;
591: char * fd = HTParse(HTStrip(dest_url), base, PARSE_ALL);
592: char * fs = HTParse(HTStrip(scr_url), base, PARSE_ALL);
593: HTParentAnchor * dest = (HTParentAnchor *) HTAnchor_findAddress(fd);
594: HTParentAnchor * src = (HTParentAnchor *) HTAnchor_findAddress(fs);
595: HTLink * link = HTAnchor_findLink((HTAnchor *) src, (HTAnchor *) dest);
596:
597: /* Now link the two anchors together if not already done */
598: if (link) {
1.112 frystyk 599: char *msg;
600: if ((msg = (char *) HT_MALLOC(128)) == NULL)
601: HT_OUTOFMEM("Upload");
1.110 frystyk 602: sprintf(msg, "The destination is already related to the source with a %s method - result %d, continue?",
603: HTMethod_name(HTLink_method(link)), HTLink_result(link));
604: doit = confirm(req, msg);
1.112 frystyk 605: HT_FREE(msg);
1.110 frystyk 606: } else {
607: HTAnchor_removeAllLinks((HTAnchor *) src);
608: HTAnchor_link((HTAnchor *) src, (HTAnchor *) dest, NULL, method);
609: }
610: if (doit) {
611: char * data = NULL;
612: HTRequest * new_request = Thread_new(lm, YES, LM_UPDATE);
613: Context * new_context = (Context *) HTRequest_context(new_request);
614: new_context->source = src;
615:
616: StrAllocCopy(data, "THIS IS A TEST ON POSTING FROM MEMORY");
617: HTAnchor_setDocument(src, data);
618:
619: /* HERE WE SHOULD FILL IN THE METAINFORMATION WE KNOW IN THE
620: SOURCE ANCHOR. IF WE DON'T KNOW THE CONTENT LENGTH THEN THIS
621: IS FINE AS WE CAN SIMPLY ADD THE CONTENT LENGTH COUNTER STREAM
622: TO THE TARGET WE GET IN OUR POST CALLBACK FUNCTION */
623:
624: status = HTUploadAnchor((HTAnchor *) src, new_request,
625: HTUpload_callback);
626: }
1.112 frystyk 627: HT_FREE(fd);
628: HT_FREE(fs);
1.110 frystyk 629: }
1.112 frystyk 630: HT_FREE(scr_url);
631: HT_FREE(dest_url);
632: HT_FREE(base);
1.110 frystyk 633: return status;
634: }
635:
636: /*
1.62 frystyk 637: ** Upload a document either from local file or from a HTTP server
638: ** to a HTTP server. The method can be either PUT or POST.
639: ** Returns the result of the load function.
1.1 timbl 640: */
1.96 frystyk 641: PRIVATE int Upload (LineMode * lm, HTRequest * req, HTMethod method)
1.40 frystyk 642: {
1.96 frystyk 643: char * base = HTAnchor_address((HTAnchor*) HTMainAnchor);
644: char * scr_url = NULL;
645: char * dest_url = NULL;
1.62 frystyk 646: int status = HT_INTERNAL;
1.96 frystyk 647: if ((scr_url = AskUser(req, "Source:", base)) != NULL &&
648: (dest_url = AskUser(req, "Destination:", NULL)) != NULL) {
1.94 frystyk 649: BOOL doit = YES;
1.96 frystyk 650: char * fd = HTParse(HTStrip(dest_url), base, PARSE_ALL);
651: char * fs = HTParse(HTStrip(scr_url), base, PARSE_ALL);
652: HTParentAnchor * dest = (HTParentAnchor *) HTAnchor_findAddress(fd);
653: HTParentAnchor * src = (HTParentAnchor *) HTAnchor_findAddress(fs);
654: HTLink * link = HTAnchor_findLink((HTAnchor *) src, (HTAnchor *) dest);
1.62 frystyk 655:
656: /* Now link the two anchors together if not already done */
1.68 frystyk 657: if (link) {
1.112 frystyk 658: char *msg;
659: if ((msg = (char *) HT_MALLOC(128)) == NULL)
660: HT_OUTOFMEM("Upload");
1.68 frystyk 661: sprintf(msg, "The destination is already related to the source with a %s method - result %d, continue?",
1.103 frystyk 662: HTMethod_name(HTLink_method(link)), HTLink_result(link));
1.96 frystyk 663: doit = confirm(req, msg);
1.112 frystyk 664: HT_FREE(msg);
1.108 frystyk 665: } else {
666: HTAnchor_removeAllLinks((HTAnchor *) src);
1.62 frystyk 667: HTAnchor_link((HTAnchor *) src, (HTAnchor *) dest, NULL, method);
1.108 frystyk 668: }
1.94 frystyk 669: if (doit) {
1.108 frystyk 670: HTRequest * new_request = Thread_new(lm, YES, LM_UPDATE);
671: Context * new_context = (Context *) HTRequest_context(new_request);
672: new_context->source = src;
673: status = HTCopyAnchor((HTAnchor *) src, new_request);
1.62 frystyk 674: }
1.112 frystyk 675: HT_FREE(fd);
676: HT_FREE(fs);
1.40 frystyk 677: }
1.112 frystyk 678: HT_FREE(scr_url);
679: HT_FREE(dest_url);
680: HT_FREE(base);
1.62 frystyk 681: return status;
1.40 frystyk 682: }
1.1 timbl 683:
684: /*
1.108 frystyk 685: ** Delete a URL
686: */
687: PRIVATE int DeleteURL (LineMode * lm, HTRequest * request)
688: {
689: char * base = HTAnchor_address((HTAnchor*) HTMainAnchor);
690: char * url = NULL;
691: int status = HT_INTERNAL;
692: if ((url = AskUser(request, "URL to delete:", base)) != NULL) {
693: char * full = HTParse(HTStrip(url), base, PARSE_ALL);
694: HTParentAnchor * anchor=(HTParentAnchor *) HTAnchor_findAddress(full);
695: request = Thread_new(lm, YES, LM_UPDATE);
696: HTRequest_setMethod(request, METHOD_DELETE);
697: status = HTLoadAnchor((HTAnchor *) anchor, request);
1.112 frystyk 698: HT_FREE(full);
1.108 frystyk 699: }
1.112 frystyk 700: HT_FREE(base);
701: HT_FREE(url);
1.108 frystyk 702: return status;
703: }
704:
705: /*
1.40 frystyk 706: ** This function puts up a stream to a file in order to save a document. This
707: ** is activated by '>', '>>' or '>!' from the prompt line.
1.1 timbl 708: */
1.90 frystyk 709: PRIVATE BOOL SaveOutputStream (HTRequest * req, char * This, char * Next)
1.40 frystyk 710: {
711: FILE *fp;
712: char *fname;
713: char *fmode;
714:
715: /* Checks if file exists. Can be overruled by using '>!' */
716: if (*(This+1) == '>') { /* Append to file */
1.74 frystyk 717: fmode = "ab";
1.40 frystyk 718: fname = *(This+2) ? (This+2) : Next;
719: } else if (*(This+1) == '!') {
1.74 frystyk 720: fmode = "wb"; /* Overwrite file */
1.40 frystyk 721: fname = *(This+2) ? (This+2) : Next;
722: } else { /* File name follows */
1.74 frystyk 723: fmode = "wb";
1.40 frystyk 724: fname = *(This+1) ? (This+1) : Next;
725: if (fname) { /* See if file exists */
726: if ((fp = fopen(fname, "r")) != NULL) {
727: fclose(fp);
1.94 frystyk 728: if (!confirm(req, "File exists - overwrite?"))
1.92 frystyk 729: return NO;
1.40 frystyk 730: }
731: }
732: }
733: if (!fname) /* No file name given */
734: return NO;
735: if ((fp = fopen(fname, fmode)) == NULL) {
1.118 eric 736: if (SHOW_MSG) HTTrace("Can't access file (%s)\n", fname);
1.40 frystyk 737: return NO;
738: }
1.109 frystyk 739: HTRequest_setOutputStream(req, HTFWriter_new(req, fp, NO));
1.118 eric 740: if (SHOW_MSG) HTTrace("Saving to file `%s\'\n", fname);
1.58 frystyk 741: return (HTLoadAnchor((HTAnchor*) HTMainAnchor, req) != HT_WOULD_BLOCK);
1.40 frystyk 742: }
1.1 timbl 743:
1.124 eric 744: CSError_t LoadedUsersCallback(CSUser_t * pCSUser, int index, void * pVoid)
1.121 eric 745: {
746: LineMode * lm = (LineMode *)pVoid;
1.124 eric 747: OutputData(lm->pView, "%d: %s\n", index, CSUser_name(pCSUser));
748: return CSError_OK;
1.121 eric 749: }
750:
1.124 eric 751: CSError_t UserListCallback(char * username, char * url, int index, void * pVoid)
1.121 eric 752: {
753: LineMode * lm = (LineMode *)pVoid;
754: OutputData(lm->pView, "%d: %s %s\n", index, username, url);
1.124 eric 755: return CSError_OK;
1.121 eric 756: }
757:
758: PRIVATE BOOL ShowPICSUsers(LineMode * lm)
759: {
760: OutputData(lm->pView, "Loaded users:\n");
1.124 eric 761: CSLoadedUser_enum(&LoadedUsersCallback, (void *)lm);
1.121 eric 762: OutputData(lm->pView, "Listed users:\n");
763: CSUserList_enum(&UserListCallback, (void *)lm);
764: return YES;
765: }
766:
1.126 hallam 767: PRIVATE int PICS_userCallback(CSUser_t * pCSUser, void * pVoid)
768: {
769: LineMode * lm = (LineMode *)pVoid;
770: char * userName;
771: char * password = NULL;
1.132 eric 772: HTAlertCallback *cbf;
1.126 hallam 773: int ret;
774: HTAlertPar * reply;
775:
1.132 eric 776: if (lm->noPICSPasswords) {
777: lm->pCSUser = pCSUser;
778: return 0;
779: }
780: if (!(cbf = HTAlert_find(HT_A_USER_PW)))
1.126 hallam 781: return -1;
782: reply = HTAlert_newReply();
783: userName = CSUser_name(pCSUser);
784: if ((ret = (*cbf)(lm->console, HT_A_USER_PW,
785: HT_MSG_NULL, userName, NULL, reply))) {
786: userName = HTAlert_replyMessage(reply);
787: password = HTAlert_replySecret(reply);
788: }
789: HTAlert_deleteReply(reply);
790: if (!ret) {
791: HTTrace("PICS set user *canceled*.\n");
792: return -1;
793: }
794: ret = -1;
795: if (!userName)
796: HTTrace("PICS cannot set to no name.\n");
797: else if (CSUser_checkPassword(pCSUser, password) == NO)
798: HTTrace("PICS password was not valid.\n");
799: else {
800: ret = 0;
801: lm->pCSUser = pCSUser;
802: }
803: HT_FREE(userName);
804: HT_FREE(password);
805: return ret;
806: }
807:
1.124 eric 808: PRIVATE BOOL SetPICSUser(LineMode * lm, char * userName)
1.121 eric 809: {
810: char * password = NULL;
1.132 eric 811: HTAlertCallback *cbf;
1.121 eric 812: BOOL ret;
1.124 eric 813: HTAlertPar * reply;
1.121 eric 814:
1.132 eric 815: if (!(cbf = HTAlert_find(HT_A_USER_PW)))
1.124 eric 816: return NO;
817: reply = HTAlert_newReply();
1.125 eric 818: if ((ret = (*cbf)(lm->console, HT_A_USER_PW,
819: HT_MSG_NULL, userName, NULL, reply))) {
1.124 eric 820: userName = HTAlert_replyMessage(reply);
821: password = HTAlert_replySecret(reply);
822: }
823: HTAlert_deleteReply(reply);
1.125 eric 824: if (!ret) {
825: HTTrace("PICS set user *canceled*.\n");
826: return NO;
827: }
1.126 hallam 828: ret = NO;
1.124 eric 829: if (!userName)
830: HTTrace("Canceled.\n");
1.126 hallam 831: else if (!(lm->pCSUser = CSApp_registerUserByName(userName, password))) {
1.124 eric 832: char * url;
833: if ((url = CSUserList_findURL(userName)) == NULL)
834: HTTrace("PICS user \"%s\" is unknown.\n", userName);
1.130 eric 835: else if (!CSLoadedUser_load(url, lm->cwd))
1.124 eric 836: HTTrace("Can't load PICS user \"%s\".\n", userName);
837: else if ((CSLoadedUser_find(userName)) == NO)
838: HTTrace("PICS user \"%s\" not found in \"%s\".\n", userName, url);
1.126 hallam 839: else if (!(lm->pCSUser = CSApp_registerUserByName(userName, password)))
1.124 eric 840: HTTrace("Failed to set PICS user to \"%s\".\n", userName);
1.126 hallam 841: ret = YES;
1.124 eric 842: HT_FREE(url);
843: }
844: HT_FREE(userName);
845: HT_FREE(password);
846: return ret;
847: }
848:
849: PRIVATE BOOL LoadPICSUser(LineMode * lm, char * url)
850: {
851: CSUser_t * pCSUser;
852: if (!(pCSUser = CSLoadedUser_load(url, lm->cwd)))
853: return NO;
1.126 hallam 854: lm->pCSUser = pCSUser;
855: return YES;
1.124 eric 856: }
857:
1.126 hallam 858: CSError_t PICSCallback(HTRequest* pReq, CSLabel_t * pCSLabel,
859: CSUser_t * pCSUser, CSError_t disposition, void * pVoid)
1.124 eric 860: {
861: LineMode * lm = (LineMode *)pVoid;
1.126 hallam 862: char * mesg;
1.124 eric 863: switch (disposition) {
1.126 hallam 864: case CSError_RATING_RANGE:
865: {
866: char * labelStr = CSLabel_getRatingStr(pCSLabel);
867: char * userStr = CSUser_getRatingStr(pCSUser);
1.135 ! eric 868: char * anchorStr = HTAnchor_address((HTAnchor*)HTRequest_anchor(pReq));
1.126 hallam 869: OutputData(lm->pView, "PICS user %s is not allowed to see document: %s\n",
1.135 ! eric 870: CSUser_name(pCSUser), anchorStr);
1.126 hallam 871: OutputData(lm->pView, " %s's \"%s\" rating for service %s (%s) did not include %s\n",
872: CSUser_name(pCSUser),
873: CSLabel_getRatingName(pCSLabel),
874: CSLabel_getServiceName(pCSLabel),
875: userStr, labelStr);
876: HT_FREE(userStr);
877: HT_FREE(labelStr);
1.135 ! eric 878: HT_FREE(anchorStr);
1.126 hallam 879: }
880: return disposition;
881: case CSError_BUREAU_NONE: mesg="label bureau was not contacted"; break;
1.134 eric 882: case CSError_RATING_VALUE: mesg="value"; break;
1.126 hallam 883: case CSError_RATING_MISSING: mesg="rating not found"; break;
1.134 eric 884: case CSError_SINGLELABEL_MISSING: mesg="no single-labels found"; break;
1.126 hallam 885: case CSError_SERVICE_MISSING: mesg="service not available";break;
886: case CSError_SERVICE_NONE: mesg="no services available for document"; break;
887: case CSError_RATING_NONE: mesg="no ratings in a service"; break;
888: case CSError_BAD_DATE: mesg="labels were out of date"; break;
889: default:HTTrace("PICSCallback: odd error code: %d\n", disposition); return disposition;
1.124 eric 890: }
1.126 hallam 891: OutputData(lm->pView, "PICS disallowed document: %s\n", mesg);
1.124 eric 892: return disposition;
1.121 eric 893: }
894:
1.62 frystyk 895: /* ------------------------------------------------------------------------- */
896: /* EVENT FUNCTIONS */
897: /* ------------------------------------------------------------------------- */
1.1 timbl 898:
1.89 frystyk 899: /* parse_command
1.76 frystyk 900: ** ------------
1.89 frystyk 901: ** Given the user's input, deal with it as necessary.
1.40 frystyk 902: ** Any Command which works returns from the routine. If nothing
903: ** works then a search or error message down at the bottom.
1.76 frystyk 904: **
905: ** Returns HT_ERROR Error has occured or we quit
906: ** HT_OK Call back was OK
1.1 timbl 907: */
1.91 frystyk 908: PRIVATE int parse_command (char* choice, SOCKET s, HTRequest *req, SockOps ops)
1.101 frystyk 909: {
1.68 frystyk 910: char * the_choice=NULL; /* preserved user command */
911: char * token=NULL; /* First word of command */
912: char * this_command; /* token and following */
1.40 frystyk 913: char * next_word; /* Second word */
914: char * other_words; /* Second word and following */
1.14 frystyk 915: BOOL is_index = HTAnchor_isIndex(HTMainAnchor);
1.48 frystyk 916: BOOL found = YES;
1.68 frystyk 917: BOOL OutSource = NO; /* Output source, YES/NO */
1.76 frystyk 918: int status = YES;
1.114 frystyk 919: HTRequest * cur_req = NULL;
920: Context * cur_context = NULL;
921: LineMode * lm = NULL;
1.101 frystyk 922:
1.114 frystyk 923: cur_req = req;
1.106 frystyk 924: cur_context = (Context *) HTRequest_context(req);
925: lm = cur_context->lm;
1.40 frystyk 926:
927: StrAllocCopy (the_choice, choice); /* Remember it as is, */
1.91 frystyk 928: if (*the_choice && the_choice[strlen(the_choice)-1] == '\n') /* final \n */
1.40 frystyk 929: the_choice[strlen(the_choice)-1] = '\0';
1.14 frystyk 930:
1.68 frystyk 931: token = strtok (choice, " \t\n\r"); /* Tokenize user input */
1.40 frystyk 932: this_command = the_choice;
1.68 frystyk 933: if (token) {
1.40 frystyk 934: next_word = strtok (NULL, " \t\n\r");
935: other_words = the_choice + (next_word - choice);
1.14 frystyk 936: }
1.40 frystyk 937: else
938: goto down; /* Empty input : scroll down */
939:
940: /* Process Command */
941: loop:
1.68 frystyk 942: switch (TOUPPER(*token)) {
1.40 frystyk 943: case '0':
944: case '1':
945: case '2':
946: case '3':
947: case '4':
948: case '5':
949: case '6':
950: case '7':
951: case '8':
952: case '9':
1.68 frystyk 953: {
954: int ref_num;
955: sscanf(token,"%d",&ref_num);
956: if (ref_num>0 && ref_num<=HText_sourceAnchors(HTMainText)) {
957: HTAnchor *destination;
958: HTChildAnchor *source = HText_childNumber(HTMainText, ref_num);
959: if (source) {
1.104 frystyk 960: req = Thread_new(lm, YES, LM_UPDATE);
1.68 frystyk 961: destination = HTAnchor_followMainLink((HTAnchor*) source);
1.69 frystyk 962:
963: /* Continous browsing, so we want Referer field */
1.90 frystyk 964: HTRequest_setParent(req,
965: HTAnchor_parent((HTAnchor*)source));
1.123 frystyk 966: HTLoadAnchor(destination, req);
1.68 frystyk 967: } else {
1.76 frystyk 968: status = NO; /* No anchor */
1.68 frystyk 969: }
1.45 frystyk 970: } else {
1.68 frystyk 971: if (SHOW_MSG)
1.118 eric 972: HTTrace("Warning: Invalid Reference Number: (%d)\n",
1.68 frystyk 973: ref_num);
1.44 frystyk 974: }
1.40 frystyk 975: }
976: break;
977:
978: case 'B':
1.68 frystyk 979: if (CHECK_INPUT("BACK", token)) { /* Return to previous node */
1.96 frystyk 980: if (HTHistory_canBacktrack(lm->history)) {
1.104 frystyk 981: req = Thread_new(lm, YES, LM_NO_UPDATE);
1.96 frystyk 982: status = HTLoadAnchor(HTHistory_back(lm->history), req);
1.40 frystyk 983: } else {
1.118 eric 984: OutputData(lm->pView, "\nThis is the first document in history list\n");
1.40 frystyk 985: }
1.68 frystyk 986: } else if (CHECK_INPUT("BOTTOM", token)) { /* Scroll to bottom */
1.40 frystyk 987: HText_scrollBottom(HTMainText);
1.48 frystyk 988: } else
989: found = NO;
1.40 frystyk 990: break;
991:
1.51 frystyk 992: case 'C':
1.120 frystyk 993: #ifdef HAVE_CHDIR
1.68 frystyk 994: if (CHECK_INPUT("CD", token)) { /* Change working directory ? */
1.40 frystyk 995: goto lcd;
1.64 frystyk 996: } else
1.120 frystyk 997: #endif /* HAVE_CHDIR */
1.69 frystyk 998: if (CHECK_INPUT("CLEAR", token)) { /* Clear History list */
1.96 frystyk 999: HTHistory_removeFrom(lm->history, 1);
1.69 frystyk 1000: } else
1.48 frystyk 1001: found = NO;
1.40 frystyk 1002: break;
1003:
1004: case 'D':
1.108 frystyk 1005: if (CHECK_INPUT("DELETE", token)) { /* DELETE */
1006: status = DeleteURL(lm, req);
1007: } else if (CHECK_INPUT("DOWN", token)) { /* Scroll down one page */
1.40 frystyk 1008: down:
1009: if (HText_canScrollDown(HTMainText))
1010: HText_scrollDown(HTMainText);
1.48 frystyk 1011: } else
1012: found = NO;
1.40 frystyk 1013: break;
1014:
1.51 frystyk 1015: case 'E':
1.68 frystyk 1016: if (CHECK_INPUT("EDIT", token)) {
1.110 frystyk 1017: status = EditAnchor(lm, req, METHOD_PUT);
1.68 frystyk 1018: } else if (CHECK_INPUT("EXIT", token)) { /* Quit program? */
1.76 frystyk 1019: status = NO;
1.48 frystyk 1020: } else
1021: found = NO;
1.40 frystyk 1022: break;
1023:
1024: case 'F': /* Keyword search ? */
1.68 frystyk 1025: if (is_index && CHECK_INPUT("FIND", token)) {
1.40 frystyk 1026: find:
1.47 frystyk 1027: {
1028: if (next_word) {
1.104 frystyk 1029: req = Thread_new(lm, YES, LM_UPDATE);
1.76 frystyk 1030: status = HTSearch(other_words, HTMainAnchor, req);
1.47 frystyk 1031: }
1032: }
1.69 frystyk 1033: } else if (CHECK_INPUT("FORWARD", token)) {
1.96 frystyk 1034: if (HTHistory_canForward(lm->history)) {
1.104 frystyk 1035: req = Thread_new(lm, YES, LM_NO_UPDATE);
1.96 frystyk 1036: status = HTLoadAnchor(HTHistory_forward(lm->history), req);
1.69 frystyk 1037: } else {
1.118 eric 1038: OutputData(lm->pView, "\nThis is the last document in history list.\n");
1.69 frystyk 1039: }
1.48 frystyk 1040: } else
1041: found = NO;
1.40 frystyk 1042: break;
1043:
1044: case 'G':
1.68 frystyk 1045: if (CHECK_INPUT("GOTO", token)) { /* GOTO */
1.124 eric 1046: if (next_word)
1047: status = LineMode_load(lm, HTMainAnchor, next_word, NO, &req);
1.48 frystyk 1048: } else
1049: found = NO;
1.40 frystyk 1050: break;
1051:
1052: case '?':
1.124 eric 1053: status = LineMode_load(lm, HTMainAnchor, C_HELP, YES, &req);
1.47 frystyk 1054: break;
1.40 frystyk 1055:
1056: case 'H':
1.68 frystyk 1057: if (CHECK_INPUT("HELP", token)) { /* help menu, ..*/
1.124 eric 1058: status = LineMode_load(lm, HTMainAnchor, C_HELP, YES, &req);
1.68 frystyk 1059: } else if (CHECK_INPUT("HOME", token)) { /* back HOME */
1.96 frystyk 1060: if (!HTHistory_canBacktrack(lm->history)) {
1.40 frystyk 1061: HText_scrollTop(HTMainText);
1062: } else {
1.104 frystyk 1063: req = Thread_new(lm, YES, LM_NO_UPDATE);
1.96 frystyk 1064: status = HTLoadAnchor(HTHistory_find(lm->history, 1), req);
1.40 frystyk 1065: }
1.48 frystyk 1066: } else
1067: found = NO;
1.40 frystyk 1068: break;
1069:
1070: case 'K': /* Keyword search ? */
1.68 frystyk 1071: if (is_index && CHECK_INPUT("KEYWORDS", token)) {
1.40 frystyk 1072: goto find;
1.48 frystyk 1073: } else
1074: found = NO;
1.40 frystyk 1075: break;
1076:
1077: case 'L':
1.68 frystyk 1078: if (CHECK_INPUT("LIST", token)) { /* List of references ? */
1.96 frystyk 1079: Reference_List(lm, !OutSource);
1.40 frystyk 1080: }
1.120 frystyk 1081: #ifdef HAVE_CHDIR
1.68 frystyk 1082: else if (CHECK_INPUT ("LCD", token)) { /* Local change dir ? */
1.40 frystyk 1083: lcd:
1084: if (!next_word) { /* Missing argument */
1.118 eric 1085: OutputData(lm->pView, "\nName of the new local directory missing.\n");
1.47 frystyk 1086: } else if (chdir (next_word)) { /* failed : say why */
1.118 eric 1087: OutputData(lm->pView, "\n ");
1.40 frystyk 1088: perror (next_word);
1.47 frystyk 1089: } else { /* Success : display new local directory */
1.127 frystyk 1090: #ifdef HAVE_GETCWD
1091: OutputData(lm->pView, "\nLocal directory is now:\n %s\n",
1092: getcwd (choice, sizeof(choice)));
1093: #else
1.120 frystyk 1094: #ifdef HAVE_GETWD
1.118 eric 1095: OutputData(lm->pView, "\nLocal directory is now:\n %s\n",
1.120 frystyk 1096: (char *) getwd (choice));
1097: #else
1098: #error "This platform doesn't support getwd or getcwd"
1.68 frystyk 1099: if (SHOW_MSG)
1.120 frystyk 1100: HTTrace("This platform doesn't support getwd or getcwd\n");
1.127 frystyk 1101: #endif /* HAVE_GETWD */
1.120 frystyk 1102: #endif /* HAVE_GETCWD */
1.40 frystyk 1103: }
1104: }
1.120 frystyk 1105: #endif /* HAVE_CHDIR */
1.124 eric 1106: else if (CHECK_INPUT("LUSER", token)) { /* List of references ? */
1107: if (next_word) {
1108: LoadPICSUser(lm, next_word);
1109: } else {
1110: HTTrace("URL needed\n");
1111: }
1112: } else
1.48 frystyk 1113: found = NO;
1.40 frystyk 1114: break;
1115:
1116: case 'M':
1.68 frystyk 1117: if (CHECK_INPUT("MANUAL", token)) { /* Read User manual */
1.124 eric 1118: status = LineMode_load(lm, HTMainAnchor, MANUAL, YES, &req);
1.48 frystyk 1119: } else
1120: found = NO;
1.40 frystyk 1121: break;
1122:
1123: case 'P':
1.68 frystyk 1124: if (CHECK_INPUT("POST", token)) {
1.96 frystyk 1125: status = Upload(lm, req, METHOD_POST);
1.40 frystyk 1126: }
1.70 frystyk 1127:
1.120 frystyk 1128: #ifdef HAVE_SYSTEM
1.96 frystyk 1129: else if (!lm->host && CHECK_INPUT("PRINT", token)) {
1.40 frystyk 1130: char * address = HTAnchor_address((HTAnchor *) HTMainAnchor);
1131: char * command;
1.62 frystyk 1132: char * tmplate = (char *) getenv("WWW_PRINT_COMMAND");
1.40 frystyk 1133: int result;
1134:
1.46 frystyk 1135: if (!tmplate) tmplate = "www -n -na -p66 '%s' | lpr";
1.126 hallam 1136: if ((command = (char *) HT_MALLOC(strlen(address)+strlen(tmplate)+20)) == NULL)
1.112 frystyk 1137: HT_OUTOFMEM("command");
1.46 frystyk 1138: sprintf(command, tmplate, address);
1.40 frystyk 1139: result = system(command);
1.112 frystyk 1140: HT_FREE(address);
1141: HT_FREE(command);
1.118 eric 1142: if (result) OutputData(lm->pView, " %s\n returns %d\n", command, result);
1.40 frystyk 1143: }
1144: #endif
1145: /* this command prints the entire current text to the
1146: terminal's printer; at the end it displays the top of the text */
1147: #ifdef SLAVE_PRINTER
1148: #define SLAVE_PRINTER_ON "\033\133\065\151"
1149: #define SLAVE_PRINTER_OFF "\033\133\064\151"
1150:
1.68 frystyk 1151: else if (CHECK_INPUT("PS", token)) {
1.118 eric 1152: OutputData(lm->pView, "%s",SLAVE_PRINTER_ON);
1153: OutputData(lm->pView, "\f"); /* Form feed for new page */
1.40 frystyk 1154: HText_scrollTop(HTMainText);
1155: while(HText_canScrollDown(HTMainText)) {
1156: HText_scrollDown(HTMainText);
1157: }
1.118 eric 1158: OutputData(lm->pView, "\f"); /* Form feed for new page */
1159: OutputData(lm->pView, "%s",SLAVE_PRINTER_OFF);
1.40 frystyk 1160: HText_scrollTop(HTMainText);
1161: }
1162: #endif
1.68 frystyk 1163: else if (CHECK_INPUT("PUT", token)) {
1.96 frystyk 1164: status = Upload(lm, req, METHOD_PUT);
1.62 frystyk 1165: } else
1.48 frystyk 1166: found = NO;
1.40 frystyk 1167: break;
1168:
1169: case 'Q': /* Quit program ? */
1.68 frystyk 1170: if (CHECK_INPUT("QUIT", token)) {
1.47 frystyk 1171:
1.40 frystyk 1172: /* JFG 9/7/92, following a complaint of 'q' mis-typed for '1'.
1173: JFG Then made optional because I hate it !!!
1174: TBL made it only affect remote logged on users. 921122 */
1175:
1.96 frystyk 1176: if (lm->host && (strcasecomp(token, "quit") != 0) ) {
1.118 eric 1177: OutputData(lm->pView, "\n Please type \"quit\" in full to leave www.\n");
1.76 frystyk 1178: } else {
1179: HTNet_killAll(); /* Kill all requests */
1180: status = NO;
1181: }
1.48 frystyk 1182: } else
1183: found = NO;
1.40 frystyk 1184: break;
1185:
1186: case 'R':
1.68 frystyk 1187: if (CHECK_INPUT("RECALL", token)) {
1.96 frystyk 1188: if (HTHistory_count(lm->history) <= 1) {
1.118 eric 1189: OutputData(lm->pView, "\n No other documents to recall.\n");
1.47 frystyk 1190: } else {
1191: /* Previous node number exists, or does the user just */
1192: /* require a list of nodes visited? */
1.69 frystyk 1193: if (next_word) {
1194: int cnt;
1195: if ((cnt = atoi(next_word)) > 0) {
1.104 frystyk 1196: req = Thread_new(lm, YES, LM_NO_UPDATE);
1.96 frystyk 1197: status = HTLoadAnchor(HTHistory_find(lm->history,cnt), req);
1.47 frystyk 1198: } else {
1.68 frystyk 1199: if (SHOW_MSG)
1.118 eric 1200: HTTrace("Bad command (%s), for list of commands type help\n", this_command);
1.47 frystyk 1201: }
1202: } else {
1.96 frystyk 1203: History_List(lm);
1.47 frystyk 1204: }
1.40 frystyk 1205: }
1.68 frystyk 1206: } else if (CHECK_INPUT("REFRESH", token)) {
1.50 frystyk 1207: HText_setStale(HTMainText); /* Force refresh */
1208: HText_refresh(HTMainText); /* Refresh screen */
1.68 frystyk 1209: } else if (CHECK_INPUT("RELOAD", token)) {
1.104 frystyk 1210: req = Thread_new(lm, YES, LM_NO_UPDATE);
1.90 frystyk 1211: HTRequest_setReloadMode(req, HT_FORCE_RELOAD);
1.124 eric 1212: status = HTLoadAnchor((HTAnchor*) (HTMainAnchor ? HTMainAnchor :
1213: lm->anchor), req);
1.48 frystyk 1214: } else
1215: found = NO;
1.40 frystyk 1216: break;
1217:
1218: case 'S': /* TBL 921009 */
1.68 frystyk 1219: if (CHECK_INPUT("SOURCE", token)) { /* Apply to source */
1.47 frystyk 1220: if (next_word) {
1221: OutSource = YES; /* Load and print as source */
1.68 frystyk 1222: token = next_word; /* Move up one word */
1.47 frystyk 1223: next_word = strtok (NULL, " \t\n\r");
1.68 frystyk 1224: this_command = the_choice + (token - choice);
1.47 frystyk 1225: other_words = the_choice + (next_word - choice);
1226: goto loop; /* Go treat as before */
1227: }
1.68 frystyk 1228: } else if (CHECK_INPUT("SET", token)) { /* config */
1.93 frystyk 1229: HTList * rules = HTRule_global();
1230: HTRule_parseLine(rules, other_words);
1.48 frystyk 1231: } else
1232: found = NO;
1.40 frystyk 1233: break;
1234:
1235: case 'T':
1.68 frystyk 1236: if (CHECK_INPUT("TOP", token)) { /* Return to top */
1.40 frystyk 1237: HText_scrollTop(HTMainText);
1.48 frystyk 1238: } else
1239: found = NO;
1.40 frystyk 1240: break;
1241:
1242: case 'U':
1.68 frystyk 1243: if (CHECK_INPUT("UP", token)) { /* Scroll up one page */
1.40 frystyk 1244: HText_scrollUp(HTMainText);
1.121 eric 1245: } else if (CHECK_INPUT("USER", token)) {
1246: if (next_word) {
1247: if (!strcasecomp(next_word, "?")) {
1248: ShowPICSUsers(lm);
1.124 eric 1249: SetPICSUser(lm, 0);
1.121 eric 1250: } else {
1.124 eric 1251: SetPICSUser(lm, next_word);
1.121 eric 1252: }
1253: } else {
1.124 eric 1254: SetPICSUser(lm, 0);
1.121 eric 1255: }
1256: } else
1.48 frystyk 1257: found = NO;
1.40 frystyk 1258: break;
1259:
1260: case 'V':
1.68 frystyk 1261: if (CHECK_INPUT("VERBOSE", token)) { /* Switch verbose mode */
1.96 frystyk 1262: WWWTRACE = WWWTRACE ? 0 : lm->trace;
1.118 eric 1263: OutputData(lm->pView, "\n Verbose mode %s.\n", WWWTRACE ? "ON":"OFF");
1.68 frystyk 1264: } else if (CHECK_INPUT("VERSION", token)) { /* Version */
1.118 eric 1265: VersionInfo(lm);
1.48 frystyk 1266: } else
1267: found = NO;
1.40 frystyk 1268: break;
1269:
1270: case 'Z':
1.50 frystyk 1271: HText_setStale(HTMainText); /* Force refresh */
1272: HText_refresh(HTMainText); /* Refresh screen */
1.76 frystyk 1273: HTNet_killAll(); /* Kill all requests */
1.44 frystyk 1274: break;
1.40 frystyk 1275:
1276: case '>':
1.96 frystyk 1277: if (!lm->host) {
1.58 frystyk 1278: HText *curText = HTMainText; /* Remember current main vindow */
1.104 frystyk 1279: req = Thread_new(lm, NO, LM_NO_UPDATE);
1.90 frystyk 1280: HTRequest_setReloadMode(req, HT_MEM_REFRESH);
1281: if (OutSource) HTRequest_setOutputFormat(req, WWW_SOURCE);
1.76 frystyk 1282: SaveOutputStream(req, token, next_word);
1.58 frystyk 1283: HText_select(curText);
1.40 frystyk 1284: }
1285: break;
1.1 timbl 1286:
1.50 frystyk 1287: #ifdef GOT_PIPE
1.40 frystyk 1288: case '|':
1.96 frystyk 1289: if (!lm->host) { /* Local only!!!! */
1.40 frystyk 1290: char * address = HTAnchor_address((HTAnchor *) HTMainAnchor);
1291: char * command;
1292: int result;
1.112 frystyk 1293: if ((command = (char *) HT_MALLOC(strlen(address) +strlen(this_command)+30)) == NULL)
1294: HT_OUTOFMEM("command");
1.40 frystyk 1295: sprintf(command, "www %s \"%s\" %s",
1296: OutSource ? "-source" : "-n -na -p", address,this_command);
1.118 eric 1297: OutputData(lm->pView, "Command: %s\n", command);
1.40 frystyk 1298: result = system(command);
1.118 eric 1299: if (result) OutputData(lm->pView, " %s returns %d\n", command, result);
1.112 frystyk 1300: HT_FREE(command);
1301: HT_FREE(address);
1.14 frystyk 1302: }
1.47 frystyk 1303: break;
1.40 frystyk 1304: #endif
1305:
1.120 frystyk 1306: #ifdef HAVE_SYSTEM
1.40 frystyk 1307: case '!':
1.96 frystyk 1308: if (!lm->host) { /* Local only! */
1.40 frystyk 1309: int result;
1.118 eric 1310: if (SHOW_MSG) HTTrace("Executing `%s\'\n", this_command);
1.40 frystyk 1311: result = system(strchr(this_command, '!') + 1);
1.118 eric 1312: if (result) OutputData(lm->pView, " %s returns %d\n",
1.96 frystyk 1313: strchr(this_command, '!') + 1, result);
1.1 timbl 1314: }
1.47 frystyk 1315: break;
1.120 frystyk 1316: #endif /* HAVE_SYSTEM */
1.40 frystyk 1317: default:
1.48 frystyk 1318: found = NO;
1319: break;
1320: } /* Switch on 1st character */
1321:
1322: if (!found) {
1.68 frystyk 1323: if (is_index && *token) { /* No commands, search keywords */
1.47 frystyk 1324: next_word = other_words = this_command;
1.48 frystyk 1325: found = YES;
1.47 frystyk 1326: goto find;
1327: } else {
1.68 frystyk 1328: if (SHOW_MSG)
1.118 eric 1329: HTTrace("Bad command (%s), for list of commands type help\n", this_command);
1.47 frystyk 1330: }
1.48 frystyk 1331: }
1.96 frystyk 1332: MakeCommandLine(lm, is_index);
1.112 frystyk 1333: HT_FREE(the_choice);
1.96 frystyk 1334:
1335: /*
1336: ** If we have created a new Request and is to update the history list then
1337: ** we can set the inactive bit on this request object.
1338: */
1.104 frystyk 1339: if (cur_req == req)
1340: cur_context->state |= LM_NO_UPDATE;
1.115 frystyk 1341: else
1.104 frystyk 1342: cur_context->state |= LM_INACTIVE;
1.76 frystyk 1343: return (status==YES) ? HT_OK : HT_ERROR;
1.40 frystyk 1344: }
1345:
1.96 frystyk 1346: /* readConsole
1347: ** -----------
1348: ** non-blocking read of the WIN32 console. EGP
1349: */
1.97 frystyk 1350:
1.106 frystyk 1351: #ifdef WWW_WIN_CONSOLE
1.89 frystyk 1352: PUBLIC BOOL readConsole(HANDLE conIn, char* buf, int len, int* pRed)
1353: {
1354: DWORD recordIndex, bufferIndex, toRead, red;
1355: PINPUT_RECORD pInput;
1356:
1357: /* grab the pending input records (keystrokes plus other garbage). */
1358: GetNumberOfConsoleInputEvents(conIn, &toRead);
1359: if (len < (int)toRead) /* we'll get the rest on the next pass(es). */
1360: toRead = len;
1.112 frystyk 1361: if ((pInput = (PINPUT_RECORD) HT_MALLOC(toRead * sizeof(INPUT_RECORD))) == NULL) /* room for n input records */
1.89 frystyk 1362: return (FALSE);
1363: ReadConsoleInput(conIn, pInput, toRead, &red);
1364:
1365: for (recordIndex = bufferIndex = 0; recordIndex < red; recordIndex++) {
1366: /* grab all keydown events */
1.97 frystyk 1367: #if 1
1368: KEY_EVENT_RECORD keyEvent = pInput[recordIndex].Event.KeyEvent; /* only used if EventType == KEY_EVENT */
1369: if (pInput[recordIndex].EventType == KEY_EVENT && keyEvent.bKeyDown) {
1370: while (keyEvent.wRepeatCount && keyEvent.uChar.AsciiChar) {
1371: /* stuff the buffer with the keys */
1372: buf[bufferIndex] = keyEvent.uChar.AsciiChar;
1373: if (buf[bufferIndex] == '\r')
1374: buf[bufferIndex] = '\n';
1375: if (buf[bufferIndex] == '\b')
1.118 eric 1376: OutputData(lm->pView, "\b ");
1377: OutputData(lm->pView, "%c", buf[bufferIndex]);
1.97 frystyk 1378: bufferIndex++;
1379: keyEvent.wRepeatCount--;
1380: }
1381: }
1382: #else
1383: if (pInput[recordIndex].EventType == KEY_EVENT && pInput[recordIndex].Event.KeyEvent.bKeyDown) {
1384: while (pInput[recordIndex].Event.KeyEvent.wRepeatCount && pInput[recordIndex].Event.KeyEvent.uChar.AsciiChar) {
1385: /* stuff the buffer with the keys */
1386: buf[bufferIndex] = pInput[recordIndex].Event.KeyEvent.uChar.AsciiChar;
1387: if (buf[bufferIndex] == '\r')
1388: buf[bufferIndex] = '\n';
1389: if (buf[bufferIndex] == '\b')
1.118 eric 1390: OutputData(lm->pView, "\b ");
1391: OutputData(lm->pView, "%c", buf[bufferIndex]);
1.97 frystyk 1392: bufferIndex++;
1393: pInput[recordIndex].Event.KeyEvent.wRepeatCount--;
1394: }
1395: }
1396: #endif
1397:
1.89 frystyk 1398: }
1399:
1.112 frystyk 1400: HT_FREE(pInput);
1.97 frystyk 1401: *pRed = bufferIndex; /* actual characters stuck into buffer */
1.89 frystyk 1402: return (TRUE);
1403: }
1.106 frystyk 1404: #endif /* WWW_WIN_CONSOLE */
1.89 frystyk 1405:
1.96 frystyk 1406: /* bufferInput
1407: ** -----------
1408: ** Read available characters from buf into stat. buf maybe bigger or
1409: ** smaller than stat.
1410: */
1.106 frystyk 1411: PUBLIC int bufferInput (char* buf, int len, SOCKET s, HTRequest * req, SockOps ops)
1.89 frystyk 1412: {
1413: static char stat[RESPONSE_LENGTH];
1414: static int iStat = 0;
1415: static int ignoreNext = 0;
1416: int iBuf;
1417: for (iBuf = 0; iBuf < len; iBuf++) {
1418: switch (buf[iBuf]) {
1419: case '\r':
1420: case '\n':
1421: if (ignoreNext)
1422: ignoreNext = 0;
1423: else {
1424: int ret;
1425: stat[iStat] = 0;
1426: iStat = 0;
1.106 frystyk 1427: if ((ret = (*PInputParser)(stat, s, req, ops)) != HT_OK)
1.89 frystyk 1428: return (ret);
1429: }
1430: break;
1431: case '\b':
1.96 frystyk 1432: if (iStat) /* don't worry about ignoreNext as iStat will be 0*/
1.89 frystyk 1433: iStat--;
1434: break;
1435: default:
1436: if (!ignoreNext)
1437: stat[iStat++] = buf[iBuf];
1438: }
1439: if (iStat == sizeof(stat)) {
1.118 eric 1440: HTTrace("Read Console... BUFFER OVERRUN\n");
1.89 frystyk 1441: iStat = 0;
1442: ignoreNext = 1;
1443: }
1444: }
1445: return (HT_OK);
1446: }
1447:
1448: PRIVATE int scan_command (SOCKET s, HTRequest * req, SockOps ops)
1449: {
1.91 frystyk 1450: /* buf happens to == eatText's buffer but not neccesary */
1451: static char buf[RESPONSE_LENGTH];
1.89 frystyk 1452: int red;
1453: int ret;
1.91 frystyk 1454:
1.106 frystyk 1455: #ifndef WWW_MSWINDOWS
1.89 frystyk 1456: if (!fgets(buf, sizeof(buf), stdin)) /* Read User Input */
1.106 frystyk 1457: return HT_ERROR; /* Exit if EOF */
1458: return ((*PInputParser)(buf, s, req, ops));
1459: #if 0
1.89 frystyk 1460: if ((red = read(s, buf, sizeof(buf))) < 0) {
1461: #ifdef EAGAIN
1462: if (socerrno==EINPROGRESS || socerrno==EAGAIN)
1463: #else
1464: if (socerrno==EINPROGRESS)
1465: #endif
1466: return (HT_OK);
1.118 eric 1467: if (PROT_TRACE) HTTrace("Read Console... READ ERROR\n");
1.89 frystyk 1468: return HT_ERROR;
1469: }
1.106 frystyk 1470: #endif
1471: #else
1472:
1473: while(1) {
1474: #ifdef WWW_WIN_CONSOLE
1475: if (!readConsole((HANDLE)s, buf, sizeof(buf), &red)) {
1.118 eric 1476: if (PROT_TRACE) HTTrace("Read Console... READ ERROR\n");
1.106 frystyk 1477: return HT_ERROR;
1478: }
1479: #else /* !WWW_WIN_CONSOLE */
1480: #endif /* !WWW_WIN_CONSOLE */
1.96 frystyk 1481: if (!red) return (HT_OK);
1.89 frystyk 1482: ret = bufferInput(buf, red, s, req, ops);
1.96 frystyk 1483: if (ret != HT_OK) return (ret);
1.89 frystyk 1484: }
1.91 frystyk 1485: #endif
1.89 frystyk 1486: }
1.40 frystyk 1487:
1.108 frystyk 1488: /* authentication_handler
1489: ** ----------------------
1490: ** This function is registered to handle access authentication,
1491: ** for example for HTTP
1492: */
1.128 frystyk 1493: PRIVATE int authentication_handler (HTRequest * request, void * param,
1494: int status)
1.108 frystyk 1495: {
1496: Context * context = (Context *) HTRequest_context(request);
1497: LineMode * lm = context->lm;
1498:
1499: /* Ask the authentication module for getting credentials */
1.119 frystyk 1500: if (HTAuth_parse(request)) {
1.108 frystyk 1501: HTMethod method = HTRequest_method(request);
1502:
1503: /* Make sure we do a reload from cache */
1504: HTRequest_setReloadMode(request, HT_FORCE_RELOAD);
1505:
1506: /* Log current request */
1507: if (HTLog_isOpen()) HTLog_add(request, status);
1508:
1509: /* Start request with new credentials */
1510: if (HTMethod_hasEntity(method)) { /* PUT, POST etc. */
1511: HTCopyAnchor((HTAnchor *) context->source, request);
1512: } else /* GET, HEAD, DELETE etc. */
1513: HTLoadAnchor((HTAnchor *) HTRequest_anchor(request), request);
1514: } else {
1.118 eric 1515: OutputData(lm->pView, "Access denied\n");
1.108 frystyk 1516: if (!HTAlert_interactive()) Cleanup(lm, -1);
1517: }
1518: return HT_ERROR; /* Make sure this is the last callback in the list */
1519: }
1520:
1521: /* redirection_handler
1522: ** -------------------
1523: ** This function is registered to handle permanent and temporary
1524: ** redirections
1525: */
1.128 frystyk 1526: PRIVATE int redirection_handler (HTRequest * request, void * param, int status)
1.108 frystyk 1527: {
1528: Context * context = (Context *) HTRequest_context(request);
1529: HTMethod method = HTRequest_method(request);
1530: LineMode * lm = context->lm;
1531: HTAnchor * new_anchor = HTRequest_redirection(request);
1532:
1533: /* Make sure we do a reload from cache */
1534: HTRequest_setReloadMode(request, HT_FORCE_RELOAD);
1535:
1536: /* If destination specified then bind source anchor with new destination */
1537: if (HTMethod_hasEntity(method)) {
1538: HTAnchor_removeAllLinks((HTAnchor *) context->source);
1539: HTAnchor_link((HTAnchor *) context->source, new_anchor, NULL, method);
1540: }
1541:
1542: /* Log current request */
1543: if (HTLog_isOpen()) HTLog_add(request, status);
1544:
1545: /* Start new request */
1546: if (HTRequest_retry(request)) {
1547: if (HTMethod_hasEntity(method)) /* PUT, POST etc. */
1548: HTCopyAnchor((HTAnchor *) context->source, request);
1549: else /* GET, HEAD, DELETE etc. */
1550: HTLoadAnchor(new_anchor, request);
1551: } else {
1.118 eric 1552: OutputData(lm->pView, "Too many redirections detected\n");
1.108 frystyk 1553: if (!HTAlert_interactive()) Cleanup(lm, -1);
1554: }
1555: return HT_ERROR; /* Make sure this is the last callback in the list */
1556: }
1557:
1.76 frystyk 1558: /* terminate_handler
1559: ** -----------------
1.96 frystyk 1560: ** This function is registered to handle the result of the request
1.1 timbl 1561: */
1.128 frystyk 1562: PRIVATE int terminate_handler (HTRequest * request, void * param, int status)
1.40 frystyk 1563: {
1.96 frystyk 1564: Context * context = (Context *) HTRequest_context(request);
1.121 eric 1565: LineMode * lm;
1566: BOOL is_index;
1567:
1568: lm = context->lm;
1.126 hallam 1569: if (CSApp_unregisterReq(request) == NO)
1570: HTTrace("PICS request not found\n");
1.121 eric 1571: is_index = HTAnchor_isIndex(HTMainAnchor);
1.40 frystyk 1572: if (status == HT_LOADED) {
1.96 frystyk 1573:
1574: if (HTAlert_interactive()) {
1575: HText_setStale(HTMainText);
1576: MakeCommandLine(lm, is_index);
1577: } else {
1578: if (lm->flags & LM_REFS) Reference_List(lm, NO);
1579: Cleanup(lm, 0);
1580: }
1.69 frystyk 1581:
1582: /* Record new history if we have not moved around in the old one */
1.96 frystyk 1583: if (context->state & LM_UPDATE)
1584: HTHistory_replace(lm->history, (HTAnchor *) HTMainAnchor);
1.69 frystyk 1585:
1.40 frystyk 1586: /* Now generate the new prompt line as a function of the result */
1587: if (!HText_canScrollDown(HTMainText) &&
1588: !HTAnchor_hasChildren(HTMainAnchor) && !is_index &&
1.96 frystyk 1589: (!HTHistory_canBacktrack(lm->history))) {
1.91 frystyk 1590: return HT_OK;
1.40 frystyk 1591: }
1.96 frystyk 1592:
1.134 eric 1593: } else { /* No page loaded so sit around and wait for a go command */
1594: MakeCommandLine(lm, is_index);
1.76 frystyk 1595: }
1.96 frystyk 1596: context->state |= LM_DONE;
1597: Thread_cleanup(lm);
1598: if (!HTAlert_interactive()) Cleanup(lm, -1);
1.76 frystyk 1599: return HT_OK;
1.40 frystyk 1600: }
1.1 timbl 1601:
1.81 frystyk 1602: /* timeout_handler
1603: ** ---------------
1.96 frystyk 1604: ** This function is registered to handle timeout in select eventloop
1.81 frystyk 1605: */
1606: PRIVATE int timeout_handler (HTRequest * request)
1607: {
1.96 frystyk 1608: if (!HTAlert_interactive()) {
1609: Context * context = (Context *) HTRequest_context(request);
1610: LineMode * lm = context->lm;
1.127 frystyk 1611: if (SHOW_MSG) HTTrace("Request timed out");
1.96 frystyk 1612: HTNet_killAll();
1613: Cleanup(lm, -1);
1614: }
1.118 eric 1615: if (SHOW_MSG) HTTrace(".");
1.81 frystyk 1616: return 0;
1617: }
1618:
1.96 frystyk 1619: /* header_handler
1620: ** ---------------
1621: ** This function is registered to handle unknown MIME headers
1622: */
1.120 frystyk 1623: PRIVATE int header_handler (HTRequest * request, const char * token)
1.96 frystyk 1624: {
1.118 eric 1625: if (SHOW_MSG) HTTrace("Parsing unknown header `%s\'\n", token);
1.96 frystyk 1626: return HT_OK;
1627: }
1628:
1.40 frystyk 1629: /* ------------------------------------------------------------------------- */
1630: /* MAIN PROGRAM */
1631: /* ------------------------------------------------------------------------- */
1.1 timbl 1632:
1.90 frystyk 1633: int main (int argc, char ** argv)
1.40 frystyk 1634: {
1.68 frystyk 1635: int status = 0;
1636: int arg; /* Index into argv */
1637: HTChunk * keywords = NULL; /* From command line */
1638: int keycnt = 0;
1.116 frystyk 1639: HTRequest * request = NULL;
1.101 frystyk 1640: LineMode * lm;
1.121 eric 1641: char * picsUser = NULL;
1.126 hallam 1642: /* char * picsUserList = NULL; */
1.85 frystyk 1643:
1.96 frystyk 1644: /* Starts Mac GUSI socket library */
1645: #ifdef GUSI
1.75 frystyk 1646: GUSISetup(GUSIwithSIOUXSockets);
1647: GUSISetup(GUSIwithInternetSockets);
1648: #endif
1649:
1650: #ifdef __MWERKS__ /* STR */
1651: InitGraf((Ptr) &qd.thePort);
1652: InitFonts();
1653: InitWindows();
1654: InitMenus(); TEInit();
1655: InitDialogs(nil);
1656: InitCursor();
1657: SIOUXSettings.asktosaveonclose = false;
1658: argc=ccommand(&argv);
1659: #endif
1660:
1.68 frystyk 1661: /* HWL 18/7/94: patch from agl@glas2.glas.apc.org (Anton Tropashko) */
1.40 frystyk 1662: #ifdef CYRILLIC
1663: arc.locale=0; arc.encoding=0; arc.i_encoding=0; doinull();
1.1 timbl 1664: #endif
1665:
1.117 frystyk 1666: /* Initiate W3C Reference Library */
1667: HTLibInit(APP_NAME, APP_VERSION);
1668:
1.108 frystyk 1669: /* Create a new Line Mode object */
1.106 frystyk 1670: lm = LineMode_new();
1.115 frystyk 1671: request = Thread_new(lm, NO, LM_UPDATE);
1.96 frystyk 1672:
1673: /* Scan command Line for parameters */
1674: for (arg=1; arg<argc ; arg++) {
1.40 frystyk 1675: if (*argv[arg] == '-') {
1676:
1677: /* - alone => filter */
1.96 frystyk 1678: if (argv[arg][1] == '\0') {
1679: lm->flags |= LM_FILTER;
1.94 frystyk 1680: HTAlert_setInteractive(NO);
1.40 frystyk 1681:
1.96 frystyk 1682: /* non-interactive */
1683: } else if (!strcmp(argv[arg], "-n")) {
1684: HTAlert_setInteractive(NO);
1.40 frystyk 1685:
1686: /* from -- Initial represntation (only with filter) */
1.96 frystyk 1687: } else if (!strcmp(argv[arg], "-from")) {
1688: lm->format = (arg+1 < argc && *argv[arg+1] != '-') ?
1689: HTAtom_for(argv[++arg]) : WWW_HTML;
1690: HTAlert_setInteractive(NO);
1.40 frystyk 1691:
1.96 frystyk 1692: /* to -- Final representation */
1693: } else if (!strcmp(argv[arg], "-to")) {
1694: HTFormat format = (arg+1 < argc && *argv[arg+1] != '-') ?
1695: HTAtom_for(argv[++arg]) : DEFAULT_FORMAT;
1.115 frystyk 1696: HTRequest_setOutputFormat(request, format);
1.96 frystyk 1697: HTAlert_setInteractive(NO);
1698:
1699: /* reformat html */
1700: } else if (!strcmp(argv[arg], "-reformat")) {
1.115 frystyk 1701: HTRequest_setOutputFormat(request, WWW_HTML);
1.96 frystyk 1702: lm->flags |= LM_REFORMAT;
1703: HTAlert_setInteractive(NO);
1704:
1705: /* List References */
1706: } else if (!strncmp(argv[arg], "-list", 5)) {
1707: lm->flags |= LM_REFS;
1708: HTAlert_setInteractive(NO);
1709:
1.100 frystyk 1710: /* original output */
1.96 frystyk 1711: } else if (!strcmp(argv[arg], "-raw")) {
1.115 frystyk 1712: HTRequest_setOutputFormat(request, WWW_RAW);
1.96 frystyk 1713: HTAlert_setInteractive(NO);
1714:
1715: /* source please */
1716: } else if (!strcmp(argv[arg], "-source")) {
1.115 frystyk 1717: HTRequest_setOutputFormat(request, WWW_SOURCE);
1.96 frystyk 1718: HTAlert_setInteractive(NO);
1719:
1720: /* HEAD method */
1721: } else if (!strcasecomp(argv[arg], "-head")) {
1.115 frystyk 1722: HTRequest_setMethod(request, METHOD_HEAD);
1723: HTRequest_setOutputFormat(request, WWW_MIME);
1.96 frystyk 1724: HTAlert_setInteractive(NO);
1725:
1.100 frystyk 1726: /* output filename */
1.96 frystyk 1727: } else if (!strcmp(argv[arg], "-o")) {
1728: lm->outputfile = (arg+1 < argc && *argv[arg+1] != '-') ?
1729: argv[++arg] : DEFAULT_OUTPUT_FILE;
1730: HTAlert_setInteractive(NO);
1731:
1732: /* print version and exit */
1733: } else if (!strcmp(argv[arg], "-version")) {
1.119 frystyk 1734: VersionInfo(lm);
1.96 frystyk 1735: Cleanup(lm, 0);
1736:
1737: /* -? or -help: show the command line help page */
1738: } else if (!strcmp(argv[arg],"-?") || !strcmp(argv[arg],"-help")) {
1739: lm->anchor = (HTParentAnchor *) HTAnchor_findAddress(L_HELP);
1740: keycnt = 1;
1.40 frystyk 1741:
1742: #ifdef CYRILLIC
1743: /* HWL 18/7/94: applied patch from agl@glas2.glas.apc.org
1744: (Anton Tropashko) */
1745: } else if (!strcmp(argv[arg], "-koi2alt")) {
1.118 eric 1746: doia2k(); OutputData(lm->pView, "Ahak2a!");
1.40 frystyk 1747: #endif
1748:
1749: /* Page size */
1750: } else if (!strncmp(argv[arg], "-p", 2)) {
1751: if (*(argv[arg]+2)) {
1752: if (sscanf(argv[arg]+2, "%d", &HTScreenHeight) < 1)
1753: HTScreenHeight = -1;
1754: else {
1755: if(HTScreenHeight < MIN_SCREEN_HEIGHT)
1756: HTScreenHeight = MIN_SCREEN_HEIGHT;
1757: if(HTScreenHeight > MAX_SCREEN_HEIGHT)
1758: HTScreenHeight = MAX_SCREEN_HEIGHT;
1759: }
1760: } else if (arg+1 < argc && *argv[arg+1] != '-') {
1761: if (sscanf(argv[++arg], "%d", &HTScreenHeight) < 1)
1762: HTScreenHeight = -1;
1763: else {
1764: if(HTScreenHeight < MIN_SCREEN_HEIGHT)
1765: HTScreenHeight = MIN_SCREEN_HEIGHT;
1766: if(HTScreenHeight > MAX_SCREEN_HEIGHT)
1767: HTScreenHeight = MAX_SCREEN_HEIGHT;
1768: }
1769: }
1.1 timbl 1770:
1.40 frystyk 1771: /* Page width */
1772: } else if (!strncmp(argv[arg], "-w", 2)) {
1773: if (*(argv[arg]+2)) {
1774: if (sscanf(argv[arg]+2, "%d", &HTScreenWidth) < 1)
1775: HTScreenWidth = SCREEN_WIDTH;
1776: } else if (arg+1 < argc && *argv[arg+1] != '-') {
1777: if (sscanf(argv[++arg], "%d", &HTScreenWidth) < 1)
1778: HTScreenWidth = SCREEN_WIDTH;
1.14 frystyk 1779: }
1.40 frystyk 1780: if(HTScreenWidth < MIN_SCREEN_WIDTH)
1781: HTScreenWidth = MIN_SCREEN_WIDTH;
1782: if(HTScreenWidth > MAX_SCREEN_WIDTH)
1783: HTScreenWidth = MAX_SCREEN_WIDTH;
1784:
1785: /* Telnet from */
1786: } else if (!strcmp(argv[arg], "-h")) {
1787: if (arg+1 < argc && *argv[arg+1] != '-') {
1.96 frystyk 1788: lm->host = argv[++arg]; /* Use host name */
1.92 frystyk 1789: HTLib_setSecure(YES); /* No easy access */
1.14 frystyk 1790: }
1.40 frystyk 1791:
1.96 frystyk 1792: /* log file */
1.40 frystyk 1793: } else if (!strcmp(argv[arg], "-l")) {
1.96 frystyk 1794: lm->logfile = (arg+1 < argc && *argv[arg+1] != '-') ?
1.68 frystyk 1795: argv[++arg] : DEFAULT_LOG_FILE;
1.51 frystyk 1796:
1.96 frystyk 1797: /* rule file */
1798: } else if (!strcmp(argv[arg], "-r")) {
1799: lm->rules = (arg+1 < argc && *argv[arg+1] != '-') ?
1800: argv[++arg] : DEFAULT_RULE_FILE;
1.68 frystyk 1801:
1.96 frystyk 1802: /* timeout -- Change the default request timeout */
1803: } else if (!strcmp(argv[arg], "-timeout")) {
1804: int timeout = (arg+1 < argc && *argv[arg+1] != '-') ?
1805: atoi(argv[++arg]) : -1;
1806: if (timeout > 0) lm->tv->tv_sec = timeout;
1.40 frystyk 1807:
1.121 eric 1808: /* PICS user */
1809: } else if (!strcmp(argv[arg], "-u")) {
1810: picsUser = (arg+1 < argc && *argv[arg+1] != '-') ?
1.124 eric 1811: argv[++arg] : "user";
1.132 eric 1812: } else if (!strcmp(argv[arg], "-unp")) {
1813: lm->noPICSPasswords = 1;
1.126 hallam 1814: #if 0 /* old version of user list file, still works when enabeled here */
1.124 eric 1815: /* PICS user list */
1816: } else if (!strcmp(argv[arg], "-ul")) {
1817: picsUserList = (arg+1 < argc && *argv[arg+1] != '-') ?
1818: argv[++arg] : "users.url";
1.126 hallam 1819: #endif
1820: /* PICS user list */
1821: } else if (!strcmp(argv[arg], "-ul")) {
1822: lm->userList = (arg+1 < argc && *argv[arg+1] != '-') ?
1823: argv[++arg] : DEFAULT_USERLIST_FILE;
1.121 eric 1824:
1.126 hallam 1825: /* PICS mode */
1826: } else if (!strcmp(argv[arg], "-pics")) {
1827: lm->userList = DEFAULT_USERLIST_FILE;
1828:
1.108 frystyk 1829: /* preemptive or non-preemptive access */
1.50 frystyk 1830: } else if (!strcmp(argv[arg], "-single")) {
1.115 frystyk 1831: HTRequest_setPreemptive(request, YES);
1.96 frystyk 1832: lm->flags |= LM_PREEMTIVE;
1.50 frystyk 1833:
1.96 frystyk 1834: /* Specify a cache root (caching is otherwise disabled) */
1835: } else if (!strcmp(argv[arg], "-cacheroot")) {
1836: HTCache_enable((arg+1>=argc || *argv[arg+1]=='-') ?
1837: NULL : argv[++arg]);
1.68 frystyk 1838:
1.96 frystyk 1839: /* Handling of Expire (cache) */
1.68 frystyk 1840: } else if (!strncmp(argv[arg], "-x", 2)) {
1841: char *p = argv[arg]+2;
1842: for(;*p;p++) {
1843: switch (argv[arg][2]) {
1844: case 'i':
1.76 frystyk 1845: HTCache_setExpiresMode(HT_EXPIRES_IGNORE, NULL);
1.68 frystyk 1846: break;
1847: case 'n':
1.76 frystyk 1848: HTCache_setExpiresMode(HT_EXPIRES_NOTIFY, "Document has expired, but I show it anyway");
1.68 frystyk 1849: break;
1850: case 'a':
1.76 frystyk 1851: HTCache_setExpiresMode(HT_EXPIRES_AUTO, NULL);
1.68 frystyk 1852: break;
1853: default:
1854: if (SHOW_MSG)
1.118 eric 1855: HTTrace("Bad parameter (%s) for option -x\n", argv[arg]);
1.68 frystyk 1856: break;
1857: }
1858: }
1859:
1.40 frystyk 1860: /* Anchor format */
1861: } else if (!strcmp(argv[arg], "-a")) {
1862: if (arg+1 < argc && *argv[arg+1] != '-')
1863: end_reference = argv[++arg]; /* New representation */
1864:
1865: /* Anchor format */
1866: } else if (!strcmp(argv[arg], "-ar")) {
1867: if (arg+1 < argc && *argv[arg+1] != '-')
1868: reference_mark = argv[++arg]; /* Change representation */
1869:
1870: /* Anchor format */
1871: } else if (!strcmp(argv[arg], "-as")) {
1872: if (arg+1 < argc && *argv[arg+1] != '-')
1873: start_reference = argv[++arg]; /* Change representation */
1874:
1875: /* No anchors */
1876: } else if (!strcmp(argv[arg], "-na")) {
1877: display_anchors = NO;
1878:
1879: #ifndef NO_DIR_OPTIONS
1880: } else if (!strncmp(argv[arg], "-d", 2)) {
1881: char *p = argv[arg]+2;
1882: for(;*p;p++) {
1883: switch (argv[arg][2]) {
1.82 frystyk 1884: case 'r':HTFile_setDirReadme(HT_DIR_README_NONE); break;
1885: case 't':HTFile_setDirReadme(HT_DIR_README_TOP); break;
1886: case 'b':HTFile_setDirReadme(HT_DIR_README_BOTTOM);break;
1887: case 'n':HTFile_setDirAccess(HT_DIR_FORBID); break;
1888: case 's':HTFile_setDirAccess(HT_DIR_SELECTIVE); break;
1889: case 'y':HTFile_setDirAccess(HT_DIR_OK); break;
1.76 frystyk 1890: default:
1.68 frystyk 1891: if (SHOW_MSG)
1.118 eric 1892: HTTrace("Bad parameter (%s) in -d option\n",
1.68 frystyk 1893: argv[arg]);
1.40 frystyk 1894: }
1.96 frystyk 1895: }
1.40 frystyk 1896: #endif
1.1 timbl 1897:
1.85 frystyk 1898: #ifdef WWWTRACE
1.96 frystyk 1899: /* trace flags */
1.40 frystyk 1900: } else if (!strncmp(argv[arg], "-v", 2)) {
1901: char *p = argv[arg]+2;
1.93 frystyk 1902: WWWTRACE = 0;
1.40 frystyk 1903: for(; *p; p++) {
1904: switch (*p) {
1.93 frystyk 1905: case 'a': WWWTRACE |= SHOW_ANCHOR_TRACE; break;
1906: case 'b': WWWTRACE |= SHOW_BIND_TRACE; break;
1907: case 'c': WWWTRACE |= SHOW_CACHE_TRACE; break;
1908: case 'g': WWWTRACE |= SHOW_SGML_TRACE; break;
1.119 frystyk 1909: case 'h': WWWTRACE |= SHOW_AUTH_TRACE; break;
1.126 hallam 1910: case 'i': WWWTRACE |= SHOW_PICS_TRACE; break;
1.127 frystyk 1911: case 'o': WWWTRACE |= SHOW_CORE_TRACE; break;
1.93 frystyk 1912: case 'p': WWWTRACE |= SHOW_PROTOCOL_TRACE; break;
1913: case 's': WWWTRACE |= SHOW_STREAM_TRACE; break;
1914: case 't': WWWTRACE |= SHOW_THREAD_TRACE; break;
1915: case 'u': WWWTRACE |= SHOW_URI_TRACE; break;
1.40 frystyk 1916: default:
1.68 frystyk 1917: if (SHOW_MSG)
1.118 eric 1918: HTTrace("Bad parameter (%s) in -v option\n",
1.76 frystyk 1919: argv[arg]);
1.40 frystyk 1920: }
1.96 frystyk 1921: }
1922: if (!WWWTRACE) WWWTRACE = SHOW_ALL_TRACE;
1923: lm->trace = WWWTRACE; /* Remember setting */
1.1 timbl 1924: #endif
1.14 frystyk 1925:
1.40 frystyk 1926: } else {
1.118 eric 1927: if (SHOW_MSG) HTTrace("Bad Argument (%s)\n", argv[arg]);
1.40 frystyk 1928: }
1929: } else { /* If no leading `-' then check for main argument */
1.68 frystyk 1930: if (!keycnt) {
1.96 frystyk 1931: char * ref = HTParse(argv[arg], lm->cwd, PARSE_ALL);
1932: lm->anchor = (HTParentAnchor *) HTAnchor_findAddress(ref);
1.79 frystyk 1933: keycnt = 1;
1.112 frystyk 1934: HT_FREE(ref);
1.40 frystyk 1935: } else { /* Check for successive keyword arguments */
1.79 frystyk 1936: char *escaped = HTEscape(argv[arg], URL_XALPHAS);
1.68 frystyk 1937: if (keycnt++ <= 1)
1.104 frystyk 1938: keywords = HTChunk_new(128);
1.68 frystyk 1939: else
1.104 frystyk 1940: HTChunk_putc(keywords, ' ');
1941: HTChunk_puts(keywords, HTStrip(escaped));
1.112 frystyk 1942: HT_FREE(escaped);
1.68 frystyk 1943: }
1.79 frystyk 1944: }
1945: }
1.40 frystyk 1946:
1.96 frystyk 1947: #ifdef CATCH_SIG
1948: SetSignal();
1949: #endif
1950:
1.123 frystyk 1951: /* Initialize the protocol modules */
1952: HTAccessInit();
1953:
1954: /* Setup authentication manager */
1955: HTAuthCall_add("basic", HTBasic_parse, HTBasic_generate, HTBasic_delete);
1956: HTAuthCall_add("digest", HTDigest_parse,HTDigest_generate,HTDigest_delete);
1957:
1958: /* Initialize set of converters */
1959: lm->converters = HTList_new();
1960: HTConverterInit(lm->converters);
1961: HTFormat_setConversion(lm->converters);
1962:
1.127 frystyk 1963: /* Set up encoders and decoders */
1.129 frystyk 1964: lm->encoders = HTList_new();
1965: HTEncoderInit(lm->encoders);
1966: HTFormat_setTransferCoding(lm->encoders);
1.127 frystyk 1967:
1.123 frystyk 1968: /* Initialize bindings between file suffixes and media types */
1969: HTFileInit();
1970:
1971: /* Set up default set of icons */
1972: HTStdIconInit(NULL);
1973:
1974: /* Get any proxy or gateway environment variables */
1975: HTProxy_getEnvVar();
1976:
1.96 frystyk 1977: /* Make home page address */
1978: if (!lm->anchor) lm->anchor = HTHomeAnchor();
1979:
1980: /* Do we need list of presenters? */
1.94 frystyk 1981: if (HTAlert_interactive()) {
1.96 frystyk 1982: lm->presenters = HTList_new();
1983: HTPresenterInit(lm->presenters);
1.115 frystyk 1984: HTRequest_setConversion(request, lm->presenters, NO);
1.86 frystyk 1985: }
1986:
1.40 frystyk 1987: if (HTScreenHeight == -1) { /* Default page size */
1.120 frystyk 1988: if (HTAlert_interactive())
1989: scrsize(&HTScreenHeight, &HTScreenWidth);
1990: else
1.42 frystyk 1991: HTScreenHeight = 999999;
1.40 frystyk 1992: }
1.23 frystyk 1993:
1.120 frystyk 1994: /* Disable HT_FREE directory browsing when using telnet host */
1.96 frystyk 1995: if (lm->host && HTFile_dirAccess() == HT_DIR_OK)
1.82 frystyk 1996: HTFile_setDirAccess(HT_DIR_SELECTIVE);
1.1 timbl 1997:
1.40 frystyk 1998: /* Open output file */
1.94 frystyk 1999: if (!HTAlert_interactive()) {
1.106 frystyk 2000: #ifndef WWW_WIN_WINDOW
1.96 frystyk 2001: if (lm->outputfile) {
1.99 frystyk 2002: if ((OUTPUT = fopen(lm->outputfile, "wb")) == NULL) {
1.118 eric 2003: if (SHOW_MSG) HTTrace("Can't open `%s'\\n",
1.96 frystyk 2004: lm->outputfile);
1.118 eric 2005: OUTPUT = stdout;
1.96 frystyk 2006: }
2007: }
1.115 frystyk 2008: HTRequest_setOutputStream(request,
2009: HTFWriter_new(request, OUTPUT, YES));
1.99 frystyk 2010: #endif
1.58 frystyk 2011:
1.96 frystyk 2012: /*
2013: ** To reformat HTML, just put it through a parser running
1.68 frystyk 2014: ** into a regenerator tbl 940613
2015: */
1.96 frystyk 2016: if (lm->flags & LM_REFORMAT) {
2017: HTStructured * html =
1.115 frystyk 2018: HTMLGenerator(request, NULL, WWW_HTML,
2019: HTRequest_outputFormat(request),
2020: HTRequest_outputStream(request));
2021: HTRequest_setOutputStream(request, SGML_new(&HTMLP_dtd, html));
1.40 frystyk 2022: }
2023: }
2024:
1.96 frystyk 2025: /* Log file specifed? */
2026: if (lm->logfile) HTLog_open(lm->logfile, YES, YES);
1.1 timbl 2027:
1.68 frystyk 2028: /* Just convert formats */
1.96 frystyk 2029: if (lm->flags & LM_FILTER) {
2030: #ifdef STDIN_FILENO
1.115 frystyk 2031: HTRequest_setAnchor(request, (HTAnchor *) lm->anchor);
2032: HTRequest_setPreemptive(request, YES);
2033: HTLoadSocket(STDIN_FILENO, request, FD_NONE);
1.95 frystyk 2034: #endif
1.96 frystyk 2035: Cleanup(lm, 0);
1.40 frystyk 2036: }
1.96 frystyk 2037:
1.113 frystyk 2038: /* Register our User Prompts etc in the Alert Manager */
2039: if (HTAlert_interactive()) {
2040: HTAlert_add(HTError_print, HT_A_MESSAGE);
2041: HTAlert_add(HTConfirm, HT_A_CONFIRM);
2042: HTAlert_add(HTPrompt, HT_A_PROMPT);
2043: HTAlert_add(HTPromptPassword, HT_A_SECRET);
2044: HTAlert_add(HTPromptUsernameAndPassword, HT_A_USER_PW);
2045: }
2046:
1.109 frystyk 2047: /* Rule file specified? */
2048: if (lm->rules) {
2049: HTList * list = HTList_new();
2050: HTRequest * rr = Thread_new(lm, NO, LM_NO_UPDATE);
2051: char * rules = HTParse(lm->rules, lm->cwd, PARSE_ALL);
2052: HTParentAnchor * ra = (HTParentAnchor *) HTAnchor_findAddress(rules);
2053: HTRequest_setPreemptive(rr, YES);
2054: HTConversion_add(list, "application/x-www-rules", "*/*", HTRules,
2055: 1.0, 0.0, 0.0);
2056: HTRequest_setConversion(rr, list, YES);
2057: if (HTLoadAnchor((HTAnchor *) ra, rr) != YES)
1.118 eric 2058: if (SHOW_MSG) HTTrace("Can't access rules\n");
1.109 frystyk 2059: HTConversion_deleteAll(list);
1.112 frystyk 2060: HT_FREE(rules);
1.102 frystyk 2061: }
1.94 frystyk 2062:
1.76 frystyk 2063: /* Register a call back function for the Net Manager */
1.128 frystyk 2064: HTNetCall_addBefore(HTLoadStart, NULL, 0);
2065: HTNetCall_addAfter(authentication_handler, NULL, HT_NO_ACCESS);
2066: HTNetCall_addAfter(redirection_handler, NULL, HT_PERM_REDIRECT);
2067: HTNetCall_addAfter(redirection_handler, NULL, HT_TEMP_REDIRECT);
2068: HTNetCall_addAfter(HTLoadTerminate, NULL, HT_ALL);
2069: HTNetCall_addAfter(terminate_handler, NULL, HT_ALL);
1.96 frystyk 2070:
1.127 frystyk 2071: /* Register a transport */
1.128 frystyk 2072: HTTransportInit();
1.127 frystyk 2073:
1.96 frystyk 2074: /* Register our own MIME header handler for extra headers */
1.121 eric 2075: /* HTHeader_addParser("*", NO, header_handler);
2076: */
1.96 frystyk 2077: /* Set timeout on sockets */
2078: if (lm->tv->tv_sec < 0) {
2079: lm->tv->tv_sec = HTAlert_interactive() ?
2080: DEFAULT_I_TIMEOUT : DEFAULT_NI_TIMEOUT;
1.93 frystyk 2081: }
1.115 frystyk 2082: HTEvent_registerTimeout(lm->tv, request, timeout_handler, NO);
1.96 frystyk 2083:
2084: /* Set max number of sockets we want open simultanously */
2085: HTNet_setMaxSocket(6);
2086:
2087: /* Set the DNS cache timeout */
2088: HTDNS_setTimeout(3600);
1.121 eric 2089:
1.126 hallam 2090: CSApp_registerApp(PICSCallback, CSApp_callOnBad, PICS_userCallback,
2091: (void *)lm);
2092: /* if (picsUserList && !CSUserList_load(picsUserList, lm->cwd))
2093: HTTrace("Unable to load PICS user list \"%s\".\n", picsUserList); */
1.124 eric 2094: if (picsUser && !LoadPICSUser(lm, picsUser))
2095: HTTrace("Unable to load PICS user \"%s\".\n", picsUser);
1.96 frystyk 2096:
1.126 hallam 2097: /* PICS user list specified? */
2098: if (lm->userList)
2099: LoadPICSUser(lm, lm->userList);
2100:
2101: /* request was registered in Thread_new before command line parsing
2102: loaded the PICS user, so re-register to give it the correct user */
2103: CSApp_unregisterReq(request);
2104: CSApp_registerReq(request, lm->pCSUser, PICSCallback,
2105: CSApp_callOnBad, (void *)lm);
2106:
1.96 frystyk 2107: /* Start the request */
2108: if (keywords)
1.115 frystyk 2109: status = HTSearch(HTChunk_data(keywords), lm->anchor, request);
1.96 frystyk 2110: else
1.115 frystyk 2111: status = HTLoadAnchor((HTAnchor *) lm->anchor, request);
1.96 frystyk 2112:
1.104 frystyk 2113: if (keywords) HTChunk_delete(keywords);
1.96 frystyk 2114: if (status != YES) {
1.118 eric 2115: if (SHOW_MSG) HTTrace("Couldn't load home page\n");
1.124 eric 2116: CSApp_unregisterDefaultUser();
2117: CSApp_unregisterApp();
1.96 frystyk 2118: Cleanup(lm, -1);
1.76 frystyk 2119: }
1.68 frystyk 2120:
1.96 frystyk 2121: /* Set up the rest if we are in interactive mode */
1.94 frystyk 2122: if (HTAlert_interactive()) {
1.73 frystyk 2123:
1.96 frystyk 2124: /* Start History manager */
2125: lm->history = HTHistory_new();
1.73 frystyk 2126:
2127: /* Register our own memory cache handler (implemented in GridText.c) */
2128: HTMemoryCache_register(HTMemoryCache);
2129:
1.83 frystyk 2130: /*
2131: ** Register STDIN as the user socket IF not STDIN is connected to
2132: ** /dev/null or other non-terminal devices
2133: */
1.82 frystyk 2134: #ifdef STDIN_FILENO
1.83 frystyk 2135: if (isatty(STDIN_FILENO)) {
1.115 frystyk 2136: HTEvent_RegisterTTY(STDIN_FILENO, lm->console, (SockOps)FD_READ,
1.97 frystyk 2137: scan_command, HT_PRIORITY_MAX);
1.83 frystyk 2138: }
1.82 frystyk 2139: #else
1.115 frystyk 2140: HTEvent_RegisterTTY(0, lm->console, (SockOps)FD_READ, scan_command, 1);
1.82 frystyk 2141: #endif
1.96 frystyk 2142: }
1.77 frystyk 2143:
1.96 frystyk 2144: /* Go into the event loop... */
1.115 frystyk 2145: HTEvent_Loop(request);
1.73 frystyk 2146:
1.96 frystyk 2147: /* Only gets here if event loop fails */
2148: Cleanup(lm, 0);
2149: return 0;
1.14 frystyk 2150: }
1.112 frystyk 2151:
Webmaster